[SCM] ardour/master: Imported Upstream version 4.6~dfsg

umlaeute at users.alioth.debian.org umlaeute at users.alioth.debian.org
Mon Jan 18 21:15:34 UTC 2016


The following commit has been merged in the master branch:
commit 543135382b8050078c76b39cf16c425ceede69bd
Author: IOhannes m zmölnig <zmoelnig at umlautQ.umlaeute.mur.at>
Date:   Mon Jan 18 21:12:43 2016 +0100

    Imported Upstream version 4.6~dfsg

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3794904
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,135 @@
+*.[oa]
+*.o
+*.os
+*.binding
+*.so
+*.dylib
+*.pyc
+
+# autotools
+aclocal.m4
+config.log
+config.status
+config.guess
+config.sub
+Makefile
+Makefile.in
+autom4te.cache
+stamp-h1
+libtool
+ltmain.sh
+install-sh
+depcomp
+.deps
+
+# OSX
+.DS_STORE
+
+# misc editor/tools
+*~
+*.swp
+*.kdev4
+.gdb_history
+core
+core.*
+vgcore.*
+cscope.files
+cscope.out
+tags
+
+# generated folders doc, build, packaging
+.waf-*
+.waf3-*
+.lock-waf*
+/build/
+/doc/html/
+/doc/latex/
+
+
+# translations
+/gtk2_ardour/po/*.mo
+/gtk2_ardour/*.pot
+/libs/ardour/po/*.mo
+/libs/ardour/ardour3.pot
+/libs/ardour/libardour.pot
+/libs/gtkmm2ext/po/*.mo
+/libs/gtkmm2ext/libgtkmm2ext.pot
+/gtk2_ardour/appdata/po/*.mo
+/gtk2_ardour/ardour.appdata.xml.in
+
+# /gtk2_ardour/
+/gtk2_ardour/ardour.sh
+/gtk2_ardour/ardev_common.sh
+/gtk2_ardour/*.bindings
+/gtk2_ardour/*.rc
+
+# /libs/ardour/
+/libs/ardour/revision.cc
+/libs/ardour/config_text.cc
+
+# /libs/gtkmm2ext/
+/libs/gtkmm2ext/*.pot
+/libs/gtkmm2ext/*.mo
+/libs/gtkmm2ext/*.po
+
+/libs/taglib/taglib/flacproperties.h
+/libs/taglib/taglib/apefooter.h
+/libs/taglib/taglib/apeitem.h
+/libs/taglib/taglib/apetag.h
+/libs/taglib/taglib/attachedpictureframe.h
+/libs/taglib/taglib/commentsframe.h
+/libs/taglib/taglib/flacfile.h
+/libs/taglib/taglib/id3v2tag.h
+/libs/taglib/taglib/generalencapsulatedobjectframe.h
+/libs/taglib/taglib/id3v1genres.h
+/libs/taglib/taglib/id3v1tag.h
+/libs/taglib/taglib/id3v2extendedheader.h
+/libs/taglib/taglib/id3v2footer.h
+/libs/taglib/taglib/id3v2frame.h
+/libs/taglib/taglib/id3v2framefactory.h
+/libs/taglib/taglib/id3v2header.h
+/libs/taglib/taglib/id3v2synchdata.h
+/libs/taglib/taglib/oggpageheader.h
+/libs/taglib/taglib/mpcfile.h
+/libs/taglib/taglib/mpcproperties.h
+/libs/taglib/taglib/mpegfile.h
+/libs/taglib/taglib/mpegheader.h
+/libs/taglib/taglib/mpegproperties.h
+/libs/taglib/taglib/oggfile.h
+/libs/taglib/taglib/oggflacfile.h
+/libs/taglib/taglib/oggpage.h
+/libs/taglib/taglib/textidentificationframe.h
+/libs/taglib/taglib/relativevolumeframe.h
+/libs/taglib/taglib/speexfile.h
+/libs/taglib/taglib/speexproperties.h
+/libs/taglib/taglib/taglib.h
+/libs/taglib/taglib/tbytevector.h
+/libs/taglib/taglib/tbytevectorlist.h
+/libs/taglib/taglib/tdebug.h
+/libs/taglib/taglib/tlist.h
+/libs/taglib/taglib/tmap.h
+/libs/taglib/taglib/trueaudiofile.h
+/libs/taglib/taglib/trueaudioproperties.h
+/libs/taglib/taglib/tstring.h
+/libs/taglib/taglib/tstringlist.h
+/libs/taglib/taglib/tfile.h
+/libs/taglib/taglib/urllinkframe.h
+/libs/taglib/taglib/unicode.h
+/libs/taglib/taglib/uniquefileidentifierframe.h
+/libs/taglib/taglib/unknownframe.h
+/libs/taglib/taglib/unsynchronizedlyricsframe.h
+/libs/taglib/taglib/xiphcomment.h
+/libs/taglib/taglib/vorbisfile.h
+/libs/taglib/taglib/vorbisproperties.h
+/libs/taglib/taglib/wavpackfile.h
+/libs/taglib/taglib/wavpackproperties.h
+/libs/taglib/taglib/xingheader.h
+/libs/taglib/taglib/tlist.tcc
+/libs/taglib/taglib/tmap.tcc
+
+/MSVCMixbus3/MSVCMixbus3.vsprops
+/MSVCardour3/MSVCMixbus3.vsprops
+/icons/win32/msvc_resources.rc
+/tools/osx_packaging/Ardour/*.app
+
+/MSVCvst_scan/vst_scan.rc
diff --git a/gtk2_ardour/about.cc b/gtk2_ardour/about.cc
index bcaf84e..707cf0b 100644
--- a/gtk2_ardour/about.cc
+++ b/gtk2_ardour/about.cc
@@ -145,6 +145,7 @@ static const char* authors[] = {
 	N_("Dave Flick"),
 	N_("Hans Fugal"),
 	N_("Robin Gareus"),
+	N_("Nil Geisweiller"),
 	N_("Christopher George"),
 	N_("Chris Goddard"),
 	N_("J. Abelardo Gutierrez"),
@@ -593,17 +594,17 @@ About::About ()
 	}
 
 #if defined __x86_64__ || defined _M_X64
-	const std::string cpu_arch = _("Intel 64 bit");
+	const std::string cpu_arch = _("Intel 64-bit");
 #elif defined __i386__  || defined _M_IX86
-	const std::string cpu_arch = _("Intel 32 bit");
+	const std::string cpu_arch = _("Intel 32-bit");
 #elif defined __ppc__ && defined  __LP64__
-	const std::string cpu_arch = _("PowerPC 64bit");
+	const std::string cpu_arch = _("PowerPC 64-bit");
 #elif defined __ppc__
-	const std::string cpu_arch = _("PowerPC 32bit");
+	const std::string cpu_arch = _("PowerPC 32-bit");
 #elif defined  __LP64__
-	const std::string cpu_arch = _("64bit");
+	const std::string cpu_arch = _("64-bit");
 #else
-	const std::string cpu_arch = _("32bit"); // ARM, ALPHA,..
+	const std::string cpu_arch = _("32-bit"); // ARM, ALPHA,..
 #endif
 	std::string codename = CODENAME;
 	if (ARDOUR::Profile->get_mixbus() || ARDOUR::Profile->get_trx()) {
diff --git a/gtk2_ardour/ambiguous_file_dialog.cc b/gtk2_ardour/ambiguous_file_dialog.cc
index be4bdc2..98d0eae 100644
--- a/gtk2_ardour/ambiguous_file_dialog.cc
+++ b/gtk2_ardour/ambiguous_file_dialog.cc
@@ -29,8 +29,10 @@ using namespace Gtk;
 AmbiguousFileDialog::AmbiguousFileDialog (const string& file, const vector<string>& paths)
 	: ArdourDialog (_("Ambiguous File"), true, false)
 {
-	get_vbox()->set_spacing (6);
+	/* This dialog is always shown programatically. Center the window.*/
+	set_position (Gtk::WIN_POS_CENTER);
 
+	get_vbox()->set_spacing (6);
 	Label* l = manage (new Label);
 	l->set_markup (string_compose (_("%1 has found the file <i>%2</i> in the following places:\n\n"), PROGRAM_NAME, file));
 	get_vbox()->pack_start (*l);
diff --git a/gtk2_ardour/appdata/po/de.po b/gtk2_ardour/appdata/po/de.po
new file mode 100644
index 0000000..bb8029e
--- /dev/null
+++ b/gtk2_ardour/appdata/po/de.po
@@ -0,0 +1,58 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: 2015-11-06 11:59+0100\n"
+"PO-Revision-Date: 2015-11-06 16:00+0100\n"
+"Last-Translator: Nils Philippsen <nils at tiptoe.de>\n"
+"Language-Team: \n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.8.5\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+# Intentionally left untranslated.
+#. (itstool) path: component/name
+#: /home/nils/src/ardour/gtk2_ardour/ardour.appdata.xml.in.in:6
+msgid "Ardour"
+msgstr ""
+
+# Intentionally left untranslated.
+#. (itstool) path: component/summary
+#: /home/nils/src/ardour/gtk2_ardour/ardour.appdata.xml.in.in:8
+msgid "Digital Audio Workstation"
+msgstr ""
+
+#. (itstool) path: description/p
+#: /home/nils/src/ardour/gtk2_ardour/ardour.appdata.xml.in.in:10
+msgid ""
+"Ardour is a multi-channel digital audio workstation, allowing you to record, "
+"edit, mix and master audio and MIDI projects."
+msgstr ""
+"Ardour ist eine mehrkanalige Digital Audio Workstation (DAW), die es Ihnen "
+"erlaubt, Audio- und MIDI-Projekte aufzunehmen, zu bearbeiten, zu mischen und "
+"zu mastern."
+
+#. (itstool) path: description/p
+#: /home/nils/src/ardour/gtk2_ardour/ardour.appdata.xml.in.in:14
+msgid ""
+"It is targeted at audio engineers, musicians, soundtrack editors and "
+"composers."
+msgstr ""
+"Es ist für Toningenieure, Musiker, Bearbeiter von Soundtracks und "
+"Komponisten gedacht."
+
+#. (itstool) path: screenshot/caption
+#: /home/nils/src/ardour/gtk2_ardour/ardour.appdata.xml.in.in:23
+msgid ""
+"The Editor window where you can arrange audio and MIDI data along a timeline"
+msgstr ""
+"Das Editorfenster, in dem Sie Audio- und Midi-Daten entlang einer Zeitachse "
+"anordnen können"
+
+#. (itstool) path: screenshot/caption
+#: /home/nils/src/ardour/gtk2_ardour/ardour.appdata.xml.in.in:27
+msgid "The Mixer window which includes channel strips for each track and bus"
+msgstr "Das Mixerfenster, das die Kanalzüge für alle Spuren und Busse enthält"
diff --git a/gtk2_ardour/appdata/po/fr.po b/gtk2_ardour/appdata/po/fr.po
new file mode 100644
index 0000000..466857b
--- /dev/null
+++ b/gtk2_ardour/appdata/po/fr.po
@@ -0,0 +1,56 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: 2015-11-06 11:59+0100\n"
+"PO-Revision-Date: 2015-11-23 16:44+0200\n"
+"Last-Translator: Olivier Humbert <trebmuh at tuxfamily.org>\n"
+"Language-Team: \n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+# Intentionally left untranslated.
+#. (itstool) path: component/name
+#: ./gtk2_ardour/ardour.appdata.xml.in.in:6
+msgid "Ardour"
+msgstr ""
+
+#. (itstool) path: component/summary
+#: ./gtk2_ardour/ardour.appdata.xml.in.in:8
+msgid "Digital Audio Workstation"
+msgstr "Station de travail audio-numérique"
+
+#. (itstool) path: description/p
+#: ./gtk2_ardour/ardour.appdata.xml.in.in:10
+msgid ""
+"Ardour is a multi-channel digital audio workstation, allowing you to record, "
+"edit, mix and master audio and MIDI projects."
+msgstr ""
+"Ardour est une station de travail audio-numérique multi-piste, vous permettant "
+"d'enregistrer, de mixer et de mastériser des projets audio et MIDI."
+
+#. (itstool) path: description/p
+#: ./gtk2_ardour/ardour.appdata.xml.in.in:14
+msgid ""
+"It is targeted at audio engineers, musicians, soundtrack editors and "
+"composers."
+msgstr ""
+"Il est conçu pour les ingénieurs audio, les musiciens, les éditeurs de "
+"pistes audio et les compositeurs."
+
+#. (itstool) path: screenshot/caption
+#: ./gtk2_ardour/ardour.appdata.xml.in.in:23
+msgid ""
+"The Editor window where you can arrange audio and MIDI data along a timeline"
+msgstr ""
+"La fenêtre d'édition où vous pouvez arranger les données MIDI et audio le long "
+"d'une ligne de temps"
+
+#. (itstool) path: screenshot/caption
+#: ./gtk2_ardour/ardour.appdata.xml.in.in:27
+msgid "The Mixer window which includes channel strips for each track and bus"
+msgstr ""
+"La fenêtre de mixeur qui inclut les tranches de canaux pour chaque piste "
+"et bus"
diff --git a/gtk2_ardour/ardev_common.sh.in b/gtk2_ardour/ardev_common.sh.in
index cf372c0..e3161e0 100644
--- a/gtk2_ardour/ardev_common.sh.in
+++ b/gtk2_ardour/ardev_common.sh.in
@@ -11,11 +11,10 @@ libs=$TOP/@LIBS@
 #
 
 export ARDOUR_PATH=$TOP/gtk2_ardour/icons:$TOP/gtk2_ardour/pixmaps:$TOP/build/gtk2_ardour:$TOP/gtk2_ardour:.
-export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie:$libs/surfaces/wiimote
+export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/faderport:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie:$libs/surfaces/wiimote
 export ARDOUR_PANNER_PATH=$libs/panners
 export ARDOUR_DATA_PATH=$TOP:$TOP/build:$TOP/gtk2_ardour:$TOP/build/gtk2_ardour:.
 export ARDOUR_MIDIMAPS_PATH=$TOP/midi_maps:.
-export ARDOUR_MCP_PATH=$TOP/mcp:.
 export ARDOUR_EXPORT_FORMATS_PATH=$TOP/export:.
 export ARDOUR_BACKEND_PATH=$libs/backends/jack:$libs/backends/wavesaudio:$libs/backends/dummy:$libs/backends/alsa:$libs/backends/coreaudio:$libs/backends/portaudio:$libs/backends/asio
 export ARDOUR_TEST_PATH=$TOP/libs/ardour/test/data
diff --git a/gtk2_ardour/ardour3.xml b/gtk2_ardour/ardour-mime-info.xml
similarity index 85%
rename from gtk2_ardour/ardour3.xml
rename to gtk2_ardour/ardour-mime-info.xml
index 4b101c6..28b19d0 100644
--- a/gtk2_ardour/ardour3.xml
+++ b/gtk2_ardour/ardour-mime-info.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
-  <mime-type type="application/x-ardour3">
+  <mime-type type="application/x-ardour">
   <sub-class-of type="application/xml"/>
   <comment>Ardour session file</comment>
   <glob pattern="*.ardour"/>
diff --git a/gtk2_ardour/ardour.appdata.xml.in.in b/gtk2_ardour/ardour.appdata.xml.in.in
new file mode 100644
index 0000000..1b2b940
--- /dev/null
+++ b/gtk2_ardour/ardour.appdata.xml.in.in
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component type="desktop">
+  <id>@ARDOUR_EXEC at .desktop</id>
+  <metadata_license>CC0-1.0</metadata_license>
+  <project_license>GPL-2.0+</project_license>
+  <name>Ardour</name>
+  <releases>
+    <release version="@VERSION@" />
+  </releases>
+  <summary>Digital Audio Workstation</summary>
+  <description>
+    <p>
+      Ardour is a multi-channel digital audio workstation, allowing you to
+      record, edit, mix and master audio and MIDI projects.
+    </p>
+    <p>
+      It is targeted at audio engineers, musicians, soundtrack editors and
+      composers.
+    </p>
+  </description>
+  <url type="homepage">http://ardour.org</url>
+  <screenshots>
+      <screenshot type="default">
+        <image>http://community.ardour.org/files/images/ardour-editor-window-1600x900.png</image>
+        <caption>The Editor window where you can arrange audio and MIDI data along a timeline</caption>
+      </screenshot>
+      <screenshot>
+        <image>http://community.ardour.org/files/images/ardour-mixer-window-1600x900.png</image>
+        <caption>The Mixer window which includes channel strips for each track and bus</caption>
+      </screenshot>
+  </screenshots>
+</component>
diff --git a/gtk2_ardour/ardour3.desktop.in b/gtk2_ardour/ardour.desktop.in
similarity index 71%
rename from gtk2_ardour/ardour3.desktop.in
rename to gtk2_ardour/ardour.desktop.in
index b27ef12..cbd7a53 100644
--- a/gtk2_ardour/ardour3.desktop.in
+++ b/gtk2_ardour/ardour.desktop.in
@@ -1,9 +1,9 @@
 [Desktop Entry]
 Name=Ardour
 Comment=Ardour Digital Audio Workstation
-Exec=ardour3
-Icon=ardour3
+Exec=@ARDOUR_EXEC@
+Icon=@ARDOUR_ICON@
 Terminal=false
-MimeType=application/x-ardour3;
+MimeType=application/x-ardour;
 Type=Application
 Categories=AudioVideo;Audio;AudioEditing;X-Recorders;X-Multitrack;X-Jack;
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
index f997347..411b262 100644
--- a/gtk2_ardour/ardour.menus.in
+++ b/gtk2_ardour/ardour.menus.in
@@ -313,6 +313,7 @@
         <menuitem action='quantize-region'/>
         <menuitem action='legatize-region'/>
         <menuitem action='remove-overlap'/>
+        <menuitem action='transform-region'/>
         <menuitem action='fork-region'/>
         <menuitem action='show-region-list-editor'/>
       </menu>
@@ -373,6 +374,7 @@
 
     <menu action='TrackMenu'>
       <menuitem action='AddTrackBus'/>	
+      <menuitem action='duplicate-routes'/>	
       <separator/>
       <menuitem action='track-record-enable-toggle'/>
       <menuitem action='track-solo-toggle'/>
@@ -502,6 +504,8 @@
 
       <menuitem action='show-editor-mixer'/>
       <menuitem action='show-editor-list'/>
+      <menuitem action='ToggleMixerList'/>
+      <menuitem action='ToggleMonitorSection'/>
       <menuitem action='ToggleMeasureVisibility'/>
       <menuitem action='ToggleSummary'/>
       <menuitem action='ToggleGroupTabs'/>
@@ -539,9 +543,14 @@
 #ifndef GTKOSX
       <menuitem action='toggle-about'/>
 #endif
-      <menuitem action='Chat'/>
-      <menuitem action='Manual'/>
-      <menuitem action='Reference'/>
+      <menuitem action='chat'/>
+      <menuitem action='manual'/>
+      <menuitem action='reference'/>
+      <menuitem action='forums'/>
+      <menuitem action='howto-report'/>
+      <menuitem action='tracker'/>
+      <menuitem action='website'/>
+      <menuitem action='website-dev'/>
     </menu>
   </menubar>
 
@@ -649,6 +658,7 @@
       <menuitem action='quantize-region'/>
       <menuitem action='legatize-region'/>
       <menuitem action='remove-overlap'/>
+      <menuitem action='transform-region'/>
       <menuitem action='fork-region'/>
       <menuitem action='show-region-list-editor'/>
     </menu>
diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc
index 7eaa960..a4f346a 100644
--- a/gtk2_ardour/ardour_button.cc
+++ b/gtk2_ardour/ardour_button.cc
@@ -759,7 +759,7 @@ ArdourButton::on_button_release_event (GdkEventButton *ev)
 	if (ev->button == 1 && _hovering && (_elements & Indicator) && _led_rect && _distinct_led_click) {
 		if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width &&
 		    ev->y >= _led_rect->y && ev->y < _led_rect->y + _led_rect->height) {
-			signal_led_clicked(); /* EMIT SIGNAL */
+			signal_led_clicked(ev); /* EMIT SIGNAL */
 			return true;
 		}
 	}
diff --git a/gtk2_ardour/ardour_button.h b/gtk2_ardour/ardour_button.h
index 27b4078..25986cc 100644
--- a/gtk2_ardour/ardour_button.h
+++ b/gtk2_ardour/ardour_button.h
@@ -90,7 +90,7 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable
 	void set_layout_font (const Pango::FontDescription&);
 	void set_text_ellipsize (Pango::EllipsizeMode);
 
-	sigc::signal<void> signal_led_clicked;
+	sigc::signal<void, GdkEventButton*> signal_led_clicked;
 	sigc::signal<void> signal_clicked;
 
 	boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
diff --git a/gtk2_ardour/ardour_dialog.cc b/gtk2_ardour/ardour_dialog.cc
index 0df32bb..f8071c2 100644
--- a/gtk2_ardour/ardour_dialog.cc
+++ b/gtk2_ardour/ardour_dialog.cc
@@ -40,7 +40,7 @@ ArdourDialog::ArdourDialog (string title, bool modal, bool use_seperator)
         , _splash_pushed (false)
 {
 	init ();
-	set_position (Gtk::WIN_POS_CENTER);
+	set_position (Gtk::WIN_POS_MOUSE);
 }
 
 ArdourDialog::ArdourDialog (Gtk::Window& parent, string title, bool modal, bool use_seperator)
diff --git a/gtk2_ardour/ardour_dropdown.cc b/gtk2_ardour/ardour_dropdown.cc
index 78100aa..5c0e25f 100644
--- a/gtk2_ardour/ardour_dropdown.cc
+++ b/gtk2_ardour/ardour_dropdown.cc
@@ -49,6 +49,7 @@ using namespace std;
 
 
 ArdourDropdown::ArdourDropdown (Element e)
+	: _scrolling_disabled(false)
 {
 //	signal_button_press_event().connect (sigc::mem_fun(*this, &ArdourDropdown::on_mouse_pressed));
 
@@ -74,6 +75,10 @@ ArdourDropdown::on_scroll_event (GdkEventScroll* ev)
 {
 	using namespace Menu_Helpers;
 
+	if (_scrolling_disabled) {
+		return false;
+	}
+
 	const MenuItem * current_active = _menu.get_active();
 	const MenuList& items = _menu.items ();
 	int c = 0;
@@ -142,4 +147,8 @@ ArdourDropdown::AddMenuElem (Menu_Helpers::Element e)
 	items.push_back (e);
 }
 
-
+void
+ArdourDropdown::disable_scrolling()
+{
+	_scrolling_disabled = true;
+}
diff --git a/gtk2_ardour/ardour_dropdown.h b/gtk2_ardour/ardour_dropdown.h
index 7069768..638f54c 100644
--- a/gtk2_ardour/ardour_dropdown.h
+++ b/gtk2_ardour/ardour_dropdown.h
@@ -42,8 +42,12 @@ class ArdourDropdown : public ArdourButton
 	void clear_items ();
 	void AddMenuElem (Gtk::Menu_Helpers::Element e);
 
+	void disable_scrolling();
+
   private:
 	Gtk::Menu      _menu;
+
+	bool _scrolling_disabled;
 };
 
 #endif /* __gtk2_ardour_ardour_dropdown_h__ */
diff --git a/gtk2_ardour/ardour_knob.cc b/gtk2_ardour/ardour_knob.cc
index f7e4a93..8cea0f4 100644
--- a/gtk2_ardour/ardour_knob.cc
+++ b/gtk2_ardour/ardour_knob.cc
@@ -365,14 +365,14 @@ ArdourKnob::on_motion_notify_event (GdkEventMotion *ev)
 				delta = tozero + remain;
 				_dead_zone_delta = 0;
 			} else {
-				c->set_value (c->normal());
+				c->set_value (c->normal(), Controllable::NoGroup);
 				_dead_zone_delta = remain / px_deadzone;
 				return true;
 			}
 		}
 
 		if (fabsf (rintf((val - _normal) / scale) + _dead_zone_delta) < 1) {
-			c->set_value (c->normal());
+			c->set_value (c->normal(), Controllable::NoGroup);
 			_dead_zone_delta += delta / px_deadzone;
 			return true;
 		}
@@ -430,7 +430,7 @@ ArdourKnob::on_button_release_event (GdkEventButton *ev)
 	if ( (_grabbed_y == ev->y && _grabbed_x == ev->x) && Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {  //no move, shift-click sets to default
 		boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable();
 		if (!c) return false;
-		c->set_value (c->normal());
+		c->set_value (c->normal(), Controllable::NoGroup);
 		return true;
 	}
 
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index fc28ee7..0d6d9e8 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -111,6 +111,7 @@ typedef uint64_t microseconds_t;
 #include "audio_region_view.h"
 #include "big_clock_window.h"
 #include "bundle_manager.h"
+#include "duplicate_routes_dialog.h"
 #include "engine_dialog.h"
 #include "export_video_dialog.h"
 #include "export_video_infobox.h"
@@ -224,7 +225,7 @@ libxml_structured_error_func (void* /* parsing_context*/,
 
 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
 
-	: Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
+	: Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
 	, session_loaded (false)
 	, gui_object_state (new GUIObjectState)
 	, primary_clock   (new MainClock (X_("primary"),   X_("transport"), true ))
@@ -284,6 +285,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
 	, _status_bar_visibility (X_("status-bar"))
 	, _feedback_exists (false)
 	, _log_not_acknowledged (LogLevelNone)
+	, duplicate_routes_dialog (0)
 {
 	Gtkmm2ext::init (localedir);
 
@@ -478,6 +480,7 @@ ARDOUR_UI::engine_stopped ()
 void
 ARDOUR_UI::engine_running ()
 {
+	ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
 	if (first_time_engine_run) {
 		post_engine();
 		first_time_engine_run = false;
@@ -492,6 +495,8 @@ ARDOUR_UI::engine_running ()
 	update_sample_rate (AudioEngine::instance()->sample_rate());
 	update_timecode_format ();
 	update_peak_thread_work ();
+	ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
+	ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
 }
 
 void
@@ -1697,11 +1702,9 @@ ARDOUR_UI::open_session ()
 		open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
 	}
 
+	Gtkmm2ext::add_volume_shortcuts (open_session_selector);
 	try {
 		/* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
-#ifdef GTKOSX
-		open_session_selector.add_shortcut_folder_uri("file:///Volumes");
-#endif
 		string default_session_folder = Config->get_default_session_parent_dir();
 		open_session_selector.add_shortcut_folder (default_session_folder);
 	}
@@ -2107,7 +2110,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
 	if (affect_transport) {
 		if (rolling) {
 			_session->request_stop (with_abort, true);
-		} else {
+		} else if (!_session->config.get_external_sync()) {
 			if (UIConfiguration::instance().get_follow_edits() && ( editor->get_selection().time.front().start == _session->transport_frame() ) ) {  //if playhead is exactly at the start of a range, we can assume it was placed there by follow_edits
 				_session->request_play_range (&editor->get_selection().time, true);
 				_session->set_requested_return_frame( editor->get_selection().time.front().start );  //force an auto-return here
@@ -2120,9 +2123,13 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
 void
 ARDOUR_UI::toggle_session_auto_loop ()
 {
+	if (!_session) {
+		return;
+	}
+
 	Location * looploc = _session->locations()->auto_loop_location();
 
-	if (!_session || !looploc) {
+	if (!looploc) {
 		return;
 	}
 
@@ -2175,7 +2182,7 @@ ARDOUR_UI::transport_rewind (int option)
 {
 	float current_transport_speed;
 
-       	if (_session) {
+	if (_session) {
 		current_transport_speed = _session->transport_speed();
 
 		if (current_transport_speed >= 0.0f) {
@@ -2285,7 +2292,7 @@ ARDOUR_UI::map_transport_state ()
 			auto_loop_button.set_active (false);
 		}
 
-		if (UIConfiguration::instance().get_follow_edits()) {
+		if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
 			/* light up both roll and play-selection if they are joined */
 			roll_button.set_active (true);
 			play_selection_button.set_active (true);
@@ -2388,7 +2395,7 @@ ARDOUR_UI::save_session_as ()
 	}
 
 
- 	Session::SaveAs sa;
+	Session::SaveAs sa;
 
 	sa.new_parent_folder = save_as_dialog->new_parent_folder ();
 	sa.new_name = save_as_dialog->new_name ();
@@ -2441,6 +2448,47 @@ ARDOUR_UI::save_session_as ()
 	}
 }
 
+bool
+ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
+{
+	string snapname;
+
+	prompter.get_result (snapname);
+
+	bool do_save = (snapname.length() != 0);
+
+	if (do_save) {
+		char illegal = Session::session_name_is_legal(snapname);
+		if (illegal) {
+			MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
+					     "snapshot names may not contain a '%1' character"), illegal));
+			msg.run ();
+			return false;
+		}
+	}
+
+	vector<std::string> p;
+	get_state_files_in_directory (_session->session_directory().root_path(), p);
+	vector<string> n = get_file_names_no_extension (p);
+
+	if (find (n.begin(), n.end(), snapname) != n.end()) {
+
+		do_save = overwrite_file_dialog (prompter,
+						 _("Confirm Snapshot Overwrite"),
+						 _("A snapshot already exists with that name. Do you want to overwrite it?"));
+	}
+
+	if (do_save) {
+		save_state (snapname, switch_to_it);
+	}
+	else {
+		return false;
+	}
+
+	return true;
+}
+
+
 /** Ask the user for the name of a new snapshot and then take it.
  */
 
@@ -2448,7 +2496,6 @@ void
 ARDOUR_UI::snapshot_session (bool switch_to_it)
 {
 	ArdourPrompter prompter (true);
-	string snapname;
 
 	prompter.set_name ("Prompter");
 	prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
@@ -2460,7 +2507,9 @@ ARDOUR_UI::snapshot_session (bool switch_to_it)
 		prompter.set_prompt (_("Name of new snapshot"));
 	}
 
-	if (!switch_to_it) {
+	if (switch_to_it) {
+		prompter.set_initial_text (_session->snap_name());
+	} else {
 		char timebuf[128];
 		time_t n;
 		struct tm local_time;
@@ -2471,49 +2520,19 @@ ARDOUR_UI::snapshot_session (bool switch_to_it)
 		prompter.set_initial_text (timebuf);
 	}
 
-  again:
-	switch (prompter.run()) {
-	case RESPONSE_ACCEPT:
-	{
-		prompter.get_result (snapname);
-
-		bool do_save = (snapname.length() != 0);
-
-		if (do_save) {
-			char illegal = Session::session_name_is_legal(snapname);
-			if (illegal) {
-				MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
-				                     "snapshot names may not contain a '%1' character"), illegal));
-				msg.run ();
-				goto again;
-			}
-		}
-
-		vector<std::string> p;
-		get_state_files_in_directory (_session->session_directory().root_path(), p);
-		vector<string> n = get_file_names_no_extension (p);
-		if (find (n.begin(), n.end(), snapname) != n.end()) {
-
-			ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
-			Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
-			confirm.get_vbox()->pack_start (m, true, true);
-			confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
-			confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
-			confirm.show_all ();
-			switch (confirm.run()) {
-			case RESPONSE_CANCEL:
-				do_save = false;
-			}
+	bool finished = false;
+	while (!finished) {
+		switch (prompter.run()) {
+		case RESPONSE_ACCEPT:
+		{
+			finished = process_snapshot_session_prompter (prompter, switch_to_it);
+			break;
 		}
 
-		if (do_save) {
-			save_state (snapname, switch_to_it);
+		default:
+			finished = true;
+			break;
 		}
-		break;
-	}
-
-	default:
-		break;
 	}
 }
 
@@ -2608,10 +2627,6 @@ ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
 	if (_session) {
 		int ret;
 
-		if (name.length() == 0) {
-			name = _session->snap_name();
-		}
-
 		if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
 			return ret;
 		}
@@ -2672,11 +2687,37 @@ ARDOUR_UI::transport_rec_enable_blink (bool onoff)
 	}
 }
 
+bool
+ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
+{
+	string name;
+
+	prompter.get_result (name);
+
+	if (name.length()) {
+		int failed = _session->save_template (name);
+
+		if (failed == -2) { /* file already exists. */
+			bool overwrite = overwrite_file_dialog (prompter,
+								_("Confirm Template Overwrite"),
+								_("A template already exists with that name. Do you want to overwrite it?"));
+
+			if (overwrite) {
+				_session->save_template (name, true);
+			}
+			else {
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
 void
 ARDOUR_UI::save_template ()
 {
 	ArdourPrompter prompter (true);
-	string name;
 
 	if (!check_audioengine(*editor)) {
 		return;
@@ -2688,17 +2729,17 @@ ARDOUR_UI::save_template ()
 	prompter.set_initial_text(_session->name() + _("-template"));
 	prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
 
-	switch (prompter.run()) {
-	case RESPONSE_ACCEPT:
-		prompter.get_result (name);
+	bool finished = false;
+	while (!finished) {
+		switch (prompter.run()) {
+		case RESPONSE_ACCEPT:
+			finished = process_save_template_prompter (prompter);
+			break;
 
-		if (name.length()) {
-			_session->save_template (name);
+		default:
+			finished = true;
+			break;
 		}
-		break;
-
-	default:
-		break;
 	}
 }
 
@@ -2799,13 +2840,47 @@ void
 ARDOUR_UI::load_from_application_api (const std::string& path)
 {
 	ARDOUR_COMMAND_LINE::session_name = path;
+	/* Cancel SessionDialog if it's visible to make OSX delegates work.
+	 *
+	 * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
+	 * race-condition:
+	 *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
+	 *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
+	 *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
+	 *    -> SessionDialog is not displayed
+	 */
 
+	if (_session_dialog) {
+		std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
+		std::string session_path = path;
+		if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
+			session_path = Glib::path_get_dirname (session_path);
+		}
+		// signal the existing dialog in ARDOUR_UI::get_session_parameters()
+		_session_dialog->set_provided_session (session_name, session_path);
+		_session_dialog->response (RESPONSE_NONE);
+		_session_dialog->hide();
+		return;
+	}
+
+	int rv;
 	if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
 		/* /path/to/foo => /path/to/foo, foo */
-		load_session (path, basename_nosuffix (path));
+		rv = load_session (path, basename_nosuffix (path));
 	} else {
 		/* /path/to/foo/foo.ardour => /path/to/foo, foo */
-		load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
+		rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
+	}
+
+	// if load_session fails -> pop up SessionDialog.
+	if (rv) {
+		ARDOUR_COMMAND_LINE::session_name = "";
+
+		if (get_session_parameters (true, false)) {
+			exit (1);
+		}
+
+		goto_editor_window ();
 	}
 }
 
@@ -2861,6 +2936,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
 
 	SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
 
+	_session_dialog = &session_dialog;
 	while (ret != 0) {
 
 		if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
@@ -2894,6 +2970,10 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
 			switch (session_dialog.run()) {
 			case RESPONSE_ACCEPT:
 				break;
+			case RESPONSE_NONE:
+				/* this is used for async * app->ShouldLoad(). */
+				continue; // while loop
+				break;
 			default:
 				if (quit_on_cancel) {
 					// JE - Currently (July 2014) this section can only get reached if the
@@ -3039,6 +3119,8 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
 		}
 	}
 
+	_session_dialog = NULL;
+
 	return ret;
 }
 
@@ -3206,7 +3288,10 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
 	fst_stop_threading();
 #endif
 
-	flush_pending ();
+	{
+		Timers::TimerSuspender t;
+		flush_pending ();
+	}
 
 #ifdef WINDOWS_VST_SUPPORT
 	fst_start_threading();
@@ -3289,13 +3374,24 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name,
 void
 ARDOUR_UI::launch_chat ()
 {
+	MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
+
+	dialog.set_title (_("About the Chat"));
+	dialog.set_secondary_text (_("When you're inside the chat just ask your question and wait for an answer. The chat is occupied by real people with real lives so many of them are passively online and might not read your question before minutes or hours later.\nSo please be patient and wait for an answer.\n\nYou should just leave the chat window open and check back regularly until someone has answered your question."));
+
+	switch (dialog.run()) {
+	case RESPONSE_OK:
 #ifdef __APPLE__
-	open_uri("http://webchat.freenode.net/?channels=ardour-osx");
+		open_uri("http://webchat.freenode.net/?channels=ardour-osx");
 #elif defined PLATFORM_WINDOWS
-	open_uri("http://webchat.freenode.net/?channels=ardour-windows");
+		open_uri("http://webchat.freenode.net/?channels=ardour-windows");
 #else
-	open_uri("http://webchat.freenode.net/?channels=ardour");
+		open_uri("http://webchat.freenode.net/?channels=ardour");
 #endif
+		break;
+	default:
+		break;
+	}
 }
 
 void
@@ -3313,7 +3409,7 @@ ARDOUR_UI::launch_reference ()
 void
 ARDOUR_UI::launch_tracker ()
 {
-	PBD::open_uri ("http://tracker.ardour.org/bug_report_page.php");
+	PBD::open_uri ("http://tracker.ardour.org");
 }
 
 void
@@ -3704,6 +3800,20 @@ ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
 }
 
 void
+ARDOUR_UI::start_duplicate_routes ()
+{
+	if (!duplicate_routes_dialog) {
+		duplicate_routes_dialog = new DuplicateRouteDialog;
+	}
+
+	if (duplicate_routes_dialog->restart (_session)) {
+		return;
+	}
+
+	duplicate_routes_dialog->present ();
+}
+
+void
 ARDOUR_UI::add_route (Gtk::Window* /* ignored */)
 {
 	int count;
@@ -4443,7 +4553,7 @@ what you would like to do.\n"), PROGRAM_NAME));
 int
 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
 {
- 	HBox* hbox = new HBox();
+	HBox* hbox = new HBox();
 	Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
 	ArdourDialog dialog (_("Sample Rate Mismatch"), true);
 	Label  message (string_compose (_("\
@@ -4576,7 +4686,7 @@ ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOU
 }
 
 void
-ARDOUR_UI::TransportControllable::set_value (double val)
+ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
 {
 	if (val < 0.5) {
 		/* do nothing: these are radio-style actions */
@@ -4702,6 +4812,7 @@ ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
 	dialog.present ();
 
 	dialog.run ();
+
 	return dialog.get_which ();
 }
 
@@ -4841,14 +4952,14 @@ ARDOUR_UI::transport_numpad_event (int num)
 		_pending_locate_num = _pending_locate_num*10 + num;
 	} else {
 		switch (num) {
-			case 0:  toggle_roll(false, false); 		break;
-			case 1:  transport_rewind(1); 				break;
-			case 2:  transport_forward(1); 				break;
-			case 3:  transport_record(true); 			break;
+			case 0:  toggle_roll(false, false);		break;
+			case 1:  transport_rewind(1);				break;
+			case 2:  transport_forward(1);				break;
+			case 3:  transport_record(true);			break;
 			case 4:  toggle_session_auto_loop();		break;
-			case 5:  transport_record(false); toggle_session_auto_loop(); 	break;
-			case 6:  toggle_punch(); 					break;
-			case 7:  toggle_click(); 				break;
+			case 5:  transport_record(false); toggle_session_auto_loop();	break;
+			case 6:  toggle_punch();					break;
+			case 7:  toggle_click();				break;
 			case 8:  toggle_auto_return();			break;
 			case 9:  toggle_follow_edits();		break;
 		}
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 1c00d98..d08dd9a 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -112,8 +112,10 @@ class ArdourKeyboard;
 class AudioClock;
 class ButtonJoiner;
 class ConnectionEditor;
+class DuplicateRouteDialog;
 class MainClock;
 class Mixer_UI;
+class ArdourPrompter;
 class PublicEditor;
 class SaveAsDialog;
 class SessionDialog;
@@ -200,6 +202,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 	void new_midi_tracer_window ();
 	void toggle_editing_space();
 	void toggle_mixer_space();
+	void toggle_mixer_list();
+	void toggle_monitor_section_visibility ();
 	void toggle_keep_tearoffs();
 
 	static PublicEditor* _instance;
@@ -247,6 +251,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
         void add_routes_part_two ();
         void add_routes_thread ();
 
+	void start_duplicate_routes ();
+
 	void add_video (Gtk::Window* float_window);
 	void remove_video ();
 	void start_video_server_menu (Gtk::Window* float_window);
@@ -353,6 +359,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 	void setup_clock ();
 
 	static ARDOUR_UI *theArdourUI;
+	SessionDialog *_session_dialog;
 
         int starting ();
 
@@ -423,7 +430,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 	    };
 
 	    TransportControllable (std::string name, ARDOUR_UI&, ToggleType);
-	    void set_value (double);
+	    void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
 	    double get_value (void) const;
 
 	    ARDOUR_UI& ui;
@@ -555,6 +562,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 
 	void open_session ();
 	void open_recent_session ();
+	bool process_save_template_prompter (ArdourPrompter& prompter);
 	void save_template ();
 
 	void edit_metadata ();
@@ -598,6 +606,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 
 	guint32  last_key_press_time;
 
+	bool process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it);
 	void snapshot_session (bool switch_to_it);
 
 	SaveAsDialog* save_as_dialog;
@@ -782,7 +791,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
 
         int do_audio_midi_setup (uint32_t);
 	void audioengine_became_silent ();
+
+	DuplicateRouteDialog* duplicate_routes_dialog;
 };
 
 #endif /* __ardour_gui_h__ */
-
diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc
index d8a1f21..3e8fde5 100644
--- a/gtk2_ardour/ardour_ui2.cc
+++ b/gtk2_ardour/ardour_ui2.cc
@@ -134,11 +134,11 @@ ARDOUR_UI::setup_tooltips ()
 	set_tip (auto_loop_button, _("Play loop range"));
 	set_tip (midi_panic_button, _("MIDI Panic\nSend note off and reset controller messages on all MIDI channels"));
 	set_tip (auto_return_button, _("Return to last playback start when stopped"));
-	set_tip (follow_edits_button, _("Playhead follows Range Selections and Edits"));
+	set_tip (follow_edits_button, _("Playhead follows range selections and edits"));
 	set_tip (auto_input_button, _("Be sensible about input monitoring"));
 	set_tip (click_button, _("Enable/Disable audio click"));
 	set_tip (solo_alert_button, _("When active, something is soloed.\nClick to de-solo everything"));
-	set_tip (auditioning_alert_button, _("When active, auditioning is taking place\nClick to stop the audition"));
+	set_tip (auditioning_alert_button, _("When active, auditioning is taking place.\nClick to stop the audition"));
 	set_tip (feedback_alert_button, _("When active, there is a feedback loop."));
 	set_tip (primary_clock, _("<b>Primary Clock</b> right-click to set display mode. Click to edit, click+drag a digit or mouse-over+scroll wheel to modify.\nText edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: confirm; postfix the edit with '+' or '-' to enter delta times.\n"));
 	set_tip (secondary_clock, _("<b>Secondary Clock</b> right-click to set display mode. Click to edit, click+drag a digit or mouse-over+scroll wheel to modify.\nText edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: confirm; postfix the edit with '+' or '-' to enter delta times.\n"));
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index f41c06a..859a167 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -586,3 +586,25 @@ ARDOUR_UI::toggle_mixer_space()
 		}
 	}
 }
+
+void
+ARDOUR_UI::toggle_mixer_list()
+{
+	Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMixerList");
+
+	if (act) {
+		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+			mixer->show_mixer_list (tact->get_active());
+	}
+}
+
+void
+ARDOUR_UI::toggle_monitor_section_visibility ()
+{
+	Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
+
+	if (act) {
+		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+			mixer->show_monitor_section (tact->get_active());
+	}
+}
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index e4379fe..cbf2c04 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -132,6 +132,11 @@ ARDOUR_UI::install_actions ()
 	ActionManager::session_sensitive_actions.push_back (act);
 	ActionManager::write_sensitive_actions.push_back (act);
 
+	act = ActionManager::register_action (main_actions, X_("duplicate-routes"), _("Duplicate Tracks/Busses..."),
+	                                      sigc::mem_fun(*this, &ARDOUR_UI::start_duplicate_routes));
+	ActionManager::session_sensitive_actions.push_back (act);
+	ActionManager::write_sensitive_actions.push_back (act);
+	ActionManager::track_selection_sensitive_actions.push_back (act);
 
 	act = ActionManager::register_action (main_actions, X_("cancel-solo"), _("Cancel Solo"), sigc::mem_fun(*this, &ARDOUR_UI::cancel_solo));
 	ActionManager::session_sensitive_actions.push_back (act);
@@ -144,7 +149,7 @@ ARDOUR_UI::install_actions ()
 	act = ActionManager::register_action (main_actions, X_("CloseVideo"), _("Remove Video"),
 					      sigc::mem_fun (*this, &ARDOUR_UI::remove_video));
 	act->set_sensitive (false);
-	act = ActionManager::register_action (main_actions, X_("ExportVideo"), _("Export To Video File"),
+	act = ActionManager::register_action (main_actions, X_("ExportVideo"), _("Export to Video File"),
 			hide_return (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::export_video), false)));
 	ActionManager::session_sensitive_actions.push_back (act);
 
@@ -176,7 +181,7 @@ ARDOUR_UI::install_actions ()
 	act = ActionManager::register_action (main_actions, X_("ImportMetadata"), _("Import Metadata..."),  sigc::mem_fun(*this, &ARDOUR_UI::import_metadata));
 	ActionManager::session_sensitive_actions.push_back (act);
 
-	act = ActionManager::register_action (main_actions, X_("ExportAudio"), _("Export To Audio File(s)..."),  sigc::mem_fun (*editor, &PublicEditor::export_audio));
+	act = ActionManager::register_action (main_actions, X_("ExportAudio"), _("Export to Audio File(s)..."),  sigc::mem_fun (*editor, &PublicEditor::export_audio));
 	ActionManager::session_sensitive_actions.push_back (act);
 
 	act = ActionManager::register_action (main_actions, X_("StemExport"), _("Stem export..."),  sigc::mem_fun (*editor, &PublicEditor::stem_export));
@@ -210,6 +215,12 @@ ARDOUR_UI::install_actions ()
 	act = ActionManager::register_toggle_action (common_actions, X_("KeepTearoffs"), _("Show Toolbars"), mem_fun (*this, &ARDOUR_UI::toggle_keep_tearoffs));
 	ActionManager::session_sensitive_actions.push_back (act);
 
+	act = ActionManager::register_toggle_action (common_actions, X_("ToggleMixerList"), _("Toggle Mixer List"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_mixer_list));
+	ActionManager::session_sensitive_actions.push_back (act);
+
+	act = ActionManager::register_toggle_action (common_actions, X_("ToggleMonitorSection"), _("Toggle Monitor Section Visibility"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_monitor_section_visibility));
+	act->set_sensitive (false);
+
 if (Profile->get_mixbus())
 	ActionManager::register_action (common_actions, X_("show-ui-prefs"), _("Show more UI preferences"), sigc::mem_fun (*this, &ARDOUR_UI::show_ui_prefs));
 
@@ -221,16 +232,16 @@ if (Profile->get_mixbus())
 
 	act = ActionManager::register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window));
 	ActionManager::session_sensitive_actions.push_back (act);
-	ActionManager::register_action (common_actions, X_("Chat"), _("Chat"),  sigc::mem_fun(*this, &ARDOUR_UI::launch_chat));
+	ActionManager::register_action (common_actions, X_("chat"), _("Chat"),  sigc::mem_fun(*this, &ARDOUR_UI::launch_chat));
 	/** TRANSLATORS: This is `Manual' in the sense of an instruction book that tells a user how to use Ardour */
-	ActionManager::register_action (common_actions, X_("Manual"), S_("Help|Manual"),  mem_fun(*this, &ARDOUR_UI::launch_manual));
-	ActionManager::register_action (common_actions, X_("Reference"), _("Reference"),  mem_fun(*this, &ARDOUR_UI::launch_reference));
-	ActionManager::register_action (common_actions, X_("Tracker"), _("Report A Bug"), mem_fun(*this, &ARDOUR_UI::launch_tracker));
-	ActionManager::register_action (common_actions, X_("Cheat_Sheet"), _("Cheat Sheet"), mem_fun(*this, &ARDOUR_UI::launch_cheat_sheet));
-	ActionManager::register_action (common_actions, X_("Website"), _("Ardour Website"), mem_fun(*this, &ARDOUR_UI::launch_website));
-	ActionManager::register_action (common_actions, X_("Website_Dev"), _("Ardour Development"), mem_fun(*this, &ARDOUR_UI::launch_website_dev));
-	ActionManager::register_action (common_actions, X_("Forums"), _("User Forums"), mem_fun(*this, &ARDOUR_UI::launch_forums));
-	ActionManager::register_action (common_actions, X_("Howto_Report"), _("How to report a bug"), mem_fun(*this, &ARDOUR_UI::launch_howto_report));
+	ActionManager::register_action (common_actions, X_("manual"), S_("Help|Manual"),  mem_fun(*this, &ARDOUR_UI::launch_manual));
+	ActionManager::register_action (common_actions, X_("reference"), S_("Manual|Reference"),  mem_fun(*this, &ARDOUR_UI::launch_reference));
+	ActionManager::register_action (common_actions, X_("tracker"), _("Report a Bug"), mem_fun(*this, &ARDOUR_UI::launch_tracker));
+	ActionManager::register_action (common_actions, X_("cheat-sheet"), _("Cheat Sheet"), mem_fun(*this, &ARDOUR_UI::launch_cheat_sheet));
+	ActionManager::register_action (common_actions, X_("website"), _("Ardour Website"), mem_fun(*this, &ARDOUR_UI::launch_website));
+	ActionManager::register_action (common_actions, X_("website-dev"), _("Ardour Development"), mem_fun(*this, &ARDOUR_UI::launch_website_dev));
+	ActionManager::register_action (common_actions, X_("forums"), _("User Forums"), mem_fun(*this, &ARDOUR_UI::launch_forums));
+	ActionManager::register_action (common_actions, X_("howto-report"), _("How to Report a Bug"), mem_fun(*this, &ARDOUR_UI::launch_howto_report));
 
 	act = ActionManager::register_action (common_actions, X_("Save"), _("Save"),  sigc::hide_return (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""), false)));
 	ActionManager::session_sensitive_actions.push_back (act);
@@ -272,11 +283,11 @@ if (Profile->get_mixbus())
 	   - otherwise do nothing
 	*/
 
-	act = ActionManager::register_action (transport_actions, X_("TransitionToRoll"), _("Transition To Roll"), sigc::bind (sigc::mem_fun (*editor, &PublicEditor::transition_to_rolling), true));
+	act = ActionManager::register_action (transport_actions, X_("TransitionToRoll"), _("Transition to Roll"), sigc::bind (sigc::mem_fun (*editor, &PublicEditor::transition_to_rolling), true));
 	ActionManager::session_sensitive_actions.push_back (act);
 	ActionManager::transport_sensitive_actions.push_back (act);
 
-	act = ActionManager::register_action (transport_actions, X_("TransitionToReverse"), _("Transition To Reverse"), sigc::bind (sigc::mem_fun (*editor, &PublicEditor::transition_to_rolling), false));
+	act = ActionManager::register_action (transport_actions, X_("TransitionToReverse"), _("Transition to Reverse"), sigc::bind (sigc::mem_fun (*editor, &PublicEditor::transition_to_rolling), false));
 	ActionManager::session_sensitive_actions.push_back (act);
 	ActionManager::transport_sensitive_actions.push_back (act);
 
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index 8aec13a..0284670 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -315,12 +315,20 @@ ARDOUR_UI::parameter_changed (std::string p)
 
 		if (!_session->config.get_external_sync()) {
 			sync_button.set_text (_("Internal"));
+			auto_loop_button.set_sensitive (true);
 			ActionManager::get_action ("Transport", "ToggleAutoPlay")->set_sensitive (true);
 			ActionManager::get_action ("Transport", "ToggleAutoReturn")->set_sensitive (true);
 			ActionManager::get_action ("Transport", "ToggleFollowEdits")->set_sensitive (true);
 		} else {
 			sync_button.set_text (sync_source_to_string (Config->get_sync_source(), true));
-			/* XXX need to make auto-play is off as well as insensitive */
+			if (_session && _session->locations()->auto_loop_location()) {
+				// disable looping with external sync.
+				// This is not necessary because session-transport ignores the loop-state,
+				// but makes it clear to the user that it's disabled.
+				_session->request_play_loop (false, false);
+			}
+			auto_loop_button.set_sensitive (false);
+			/* XXX we need to make sure that auto-play is off as well as insensitive */
 			ActionManager::get_action ("Transport", "ToggleAutoPlay")->set_sensitive (false);
 			ActionManager::get_action ("Transport", "ToggleAutoReturn")->set_sensitive (false);
 			ActionManager::get_action ("Transport", "ToggleFollowEdits")->set_sensitive (false);
diff --git a/gtk2_ardour/ardour_window.cc b/gtk2_ardour/ardour_window.cc
index 1cb4202..029f5f1 100644
--- a/gtk2_ardour/ardour_window.cc
+++ b/gtk2_ardour/ardour_window.cc
@@ -39,14 +39,15 @@ ArdourWindow::ArdourWindow (string title)
 {
 	set_title (title);
 	init ();
-	set_position (Gtk::WIN_POS_CENTER);
+	set_position (Gtk::WIN_POS_MOUSE);
 }
 
-ArdourWindow::ArdourWindow (Gtk::Window& parent, string /*title*/)
+ArdourWindow::ArdourWindow (Gtk::Window& parent, string title)
 	: Window ()
 	, VisibilityTracker (*((Gtk::Window*)this))
 {
 	init ();
+	set_title (title);
 	set_transient_for (parent);
 	set_position (Gtk::WIN_POS_CENTER_ON_PARENT);
 }
diff --git a/gtk2_ardour/arhell b/gtk2_ardour/arhell
new file mode 100755
index 0000000..e2ed45c
--- /dev/null
+++ b/gtk2_ardour/arhell
@@ -0,0 +1,12 @@
+#!/bin/sh
+#HELGRIND_OPTIONS="$VALGRIND_OPTIONS --free-is-write=yes"
+#HELGRIND_OPTIONS="$VALGRIND_OPTIONS --history-level=approx"
+HELGRIND_OPTIONS="$VALGRIND_OPTIONS --log-file=/tmp/ardour-%p.log"
+
+TOP=`dirname "$0"`/..
+. $TOP/build/gtk2_ardour/ardev_common_waf.sh
+export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE
+exec valgrind --tool=helgrind \
+	--error-limit=no --num-callers=50 \
+	$HELGRIND_OPTIONS \
+	$TOP/$EXECUTABLE --novst "$@"
diff --git a/gtk2_ardour/armass b/gtk2_ardour/armass
index 7177d42..3a21a04 100755
--- a/gtk2_ardour/armass
+++ b/gtk2_ardour/armass
@@ -1,11 +1,11 @@
 #!/bin/sh
+MASSIF_OPTIONS="$MASSIF_OPTIONS --time-unit=ms"
 
 TOP=`dirname "$0"`/..
 . $TOP/build/gtk2_ardour/ardev_common_waf.sh
-LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
 export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE
-exec valgrind \
-	--tool=massif \
+exec valgrind --tool=massif \
+	$MASSIF_OPTIONS \
 	$TOP/$EXECUTABLE --novst "$@"
 
 # analyse output with
diff --git a/gtk2_ardour/au_pluginui.mm b/gtk2_ardour/au_pluginui.mm
index 116e63c..af174f9 100644
--- a/gtk2_ardour/au_pluginui.mm
+++ b/gtk2_ardour/au_pluginui.mm
@@ -18,8 +18,8 @@
 #include "au_pluginui.h"
 #include "gui_thread.h"
 
-#include "appleutility/CAAudioUnit.h"
-#include "appleutility/CAComponent.h"
+#include "CAAudioUnit.h"
+#include "CAComponent.h"
 
 #import <AudioUnit/AUCocoaUIView.h>
 #import <CoreAudioKit/AUGenericView.h>
@@ -31,6 +31,11 @@
 #include "public_editor.h"
 #include "i18n.h"
 
+#ifdef COREAUDIO105
+#define ArdourCloseComponent CloseComponent
+#else
+#define ArdourCloseComponent AudioComponentInstanceDispose
+#endif
 using namespace ARDOUR;
 using namespace Gtk;
 using namespace Gtkmm2ext;
@@ -235,11 +240,13 @@ AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
 
 	low_box.signal_realize().connect (mem_fun (this, &AUPluginUI::lower_box_realized));
 	low_box.signal_visibility_notify_event ().connect (mem_fun (this, &AUPluginUI::lower_box_visibility_notify));
-	low_box.signal_size_request ().connect (mem_fun (this, &AUPluginUI::lower_box_size_request));
-	low_box.signal_size_allocate ().connect (mem_fun (this, &AUPluginUI::lower_box_size_allocate));
-	low_box.signal_map ().connect (mem_fun (this, &AUPluginUI::lower_box_map));
-	low_box.signal_unmap ().connect (mem_fun (this, &AUPluginUI::lower_box_unmap));
-	//low_box.signal_expose_event ().connect (mem_fun (this, &AUPluginUI::lower_box_expose));
+	if (au_view) {
+		low_box.signal_size_request ().connect (mem_fun (this, &AUPluginUI::lower_box_size_request));
+		low_box.signal_size_allocate ().connect (mem_fun (this, &AUPluginUI::lower_box_size_allocate));
+		low_box.signal_map ().connect (mem_fun (this, &AUPluginUI::lower_box_map));
+		low_box.signal_unmap ().connect (mem_fun (this, &AUPluginUI::lower_box_unmap));
+		low_box.signal_expose_event ().connect (mem_fun (this, &AUPluginUI::lower_box_expose));
+	}
 }
 
 AUPluginUI::~AUPluginUI ()
@@ -261,7 +268,7 @@ AUPluginUI::~AUPluginUI ()
 #endif
 
 	if (editView) {
-		CloseComponent (editView);
+		ArdourCloseComponent (editView);
 	}
 
 	if (au_view) {
@@ -502,14 +509,14 @@ AUPluginUI::create_carbon_view ()
 
 	if ((err = CreateNewWindow(kUtilityWindowClass, attr, &r, &carbon_window)) != noErr) {
 		error << string_compose (_("AUPluginUI: cannot create carbon window (err: %1)"), err) << endmsg;
-	        CloseComponent (editView);
+	        ArdourCloseComponent (editView);
 		return -1;
 	}
 
 	if ((err = GetRootControl(carbon_window, &root_control)) != noErr) {
 		error << string_compose (_("AUPlugin: cannot get root control of carbon window (err: %1)"), err) << endmsg;
 		DisposeWindow (carbon_window);
-	        CloseComponent (editView);
+	        ArdourCloseComponent (editView);
 		return -1;
 	}
 
@@ -520,7 +527,7 @@ AUPluginUI::create_carbon_view ()
 	if ((err = AudioUnitCarbonViewCreate (editView, *au->get_au(), carbon_window, root_control, &location, &size, &viewPane)) != noErr) {
 		error << string_compose (_("AUPluginUI: cannot create carbon plugin view (err: %1)"), err) << endmsg;
 		DisposeWindow (carbon_window);
-	        CloseComponent (editView);
+	        ArdourCloseComponent (editView);
 		return -1;
 	}
 
@@ -534,8 +541,8 @@ AUPluginUI::create_carbon_view ()
 	req_width = (int) (size.x + 0.5);
 	req_height = (int) (size.y + 0.5);
 
-	SizeWindow (carbon_window, prefwidth, req_height,  true);
-	low_box.set_size_request (prefwidth, req_height); // ??
+	SizeWindow (carbon_window, req_width, req_height,  true);
+	low_box.set_size_request (req_width, req_height);
 
 	return 0;
 #else
@@ -591,13 +598,6 @@ AUPluginUI::parent_carbon_window ()
 		return -1;
 	}
 
-	Gtk::Container* toplevel = get_toplevel();
-
-	if (!toplevel || !toplevel->is_toplevel()) {
-		error << _("AUPluginUI: no top level window!") << endmsg;
-		return -1;
-	}
-
 	/* figure out where the cocoa parent window is in carbon-coordinate space, which
 	   differs from both cocoa-coordinate space and GTK-coordinate space
 	*/
@@ -808,10 +808,17 @@ AUPluginUI::lower_box_size_allocate (Gtk::Allocation& allocation)
 gboolean
 AUPluginUI::lower_box_expose (GdkEventExpose* event)
 {
+#if 0 // AU view magically redraws by itself
 	[au_view drawRect:NSMakeRect(event->area.x,
 			event->area.y,
 			event->area.width,
 			event->area.height)];
+#endif
+	/* hack to keep ardour responsive
+	 * some UIs (e.g Addictive Drums) completely hog the CPU
+	 */
+	ARDOUR::GUIIdle();
+
 	return true;
 }
 
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
index cf55f63..d7fb376 100644
--- a/gtk2_ardour/audio_clock.cc
+++ b/gtk2_ardour/audio_clock.cc
@@ -2121,7 +2121,7 @@ AudioClock::build_ops_menu ()
 
 	if (editable && !_off && !is_duration && !_follows_playhead) {
 		ops_items.push_back (SeparatorElem());
-		ops_items.push_back (MenuElem (_("Set From Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead)));
+		ops_items.push_back (MenuElem (_("Set from Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead)));
 		ops_items.push_back (MenuElem (_("Locate to This Time"), sigc::mem_fun(*this, &AudioClock::locate)));
 	}
 	ops_items.push_back (SeparatorElem());
diff --git a/gtk2_ardour/audio_region_editor.cc b/gtk2_ardour/audio_region_editor.cc
index 4aa8075..3446f58 100644
--- a/gtk2_ardour/audio_region_editor.cc
+++ b/gtk2_ardour/audio_region_editor.cc
@@ -52,7 +52,9 @@ AudioRegionEditor::AudioRegionEditor (Session* s, boost::shared_ptr<AudioRegion>
 	: RegionEditor (s, r)
 	, _audio_region (r)
 	, gain_adjustment(accurate_coefficient_to_dB(_audio_region->scale_amplitude()), -40.0, +40.0, 0.1, 1.0, 0)
-#ifndef PLATFORM_WINDOWS
+#ifdef PLATFORM_WINDOWS
+	, m_peak_sem ("peak_semaphore", 0)
+#else
 	, _peak_channel (false)
 #endif
 {
@@ -137,7 +139,7 @@ void
 AudioRegionEditor::signal_peak_thread ()
 {
 #ifdef PLATFORM_WINDOWS
-	m_peak_sem.post ();
+	m_peak_sem.signal ();
 #else
 	_peak_channel.deliver ('c');
 #endif
diff --git a/gtk2_ardour/audio_region_editor.h b/gtk2_ardour/audio_region_editor.h
index 3fdecc1..dd726bd 100644
--- a/gtk2_ardour/audio_region_editor.h
+++ b/gtk2_ardour/audio_region_editor.h
@@ -37,7 +37,7 @@
 
 #include "pbd/signals.h"
 #ifdef PLATFORM_WINDOWS
-#include "pbd/glib_semaphore.h"
+#include "pbd/semutils.h"
 #else
 #include "pbd/crossthread.h"
 #endif
@@ -84,7 +84,7 @@ class AudioRegionEditor : public RegionEditor
 	PBD::Signal1<void, double> PeakAmplitudeFound;
 	PBD::ScopedConnection _peak_amplitude_connection;
 #ifdef PLATFORM_WINDOWS
-	PBD::GlibSemaphore m_peak_sem;
+	PBD::Semaphore m_peak_sem;
 #else
 	CrossThreadChannel _peak_channel;
 #endif
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 706611a..148f99f 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -1309,18 +1309,34 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
 		return;
 	}
 
-	double x, y;
+	uint32_t before_p, after_p;
+	double mx = ev->button.x;
+	double my = ev->button.y;
 
-	/* don't create points that can't be seen */
+	item->canvas_to_item (mx, my);
 
-	update_envelope_visibility ();
+	framecnt_t const frame_within_region = (framecnt_t) floor (mx * samples_per_pixel);
+
+	if (!gain_line->control_points_adjacent (frame_within_region, before_p, after_p)) {
+		/* no adjacent points */
+		return;
+	}
+
+	/*y is in item frame */
+	double const bx = gain_line->nth (before_p)->get_x();
+	double const ax = gain_line->nth (after_p)->get_x();
+	double const click_ratio = (ax - mx) / (ax - bx);
 
-	x = ev->button.x;
-	y = ev->button.y;
+	double y = ((gain_line->nth (before_p)->get_y() * click_ratio) + (gain_line->nth (after_p)->get_y() * (1 - click_ratio)));
 
-	item->canvas_to_item (x, y);
+	/* don't create points that can't be seen */
 
-	framepos_t fx = trackview.editor().pixel_to_sample (x);
+	update_envelope_visibility ();
+
+	framepos_t rpos = region ()->position ();
+	framepos_t fx = trackview.editor().pixel_to_sample (mx) + rpos;
+	trackview.editor ().snap_to_with_modifier (fx, ev);
+	fx -= rpos;
 
 	if (fx > _region->length()) {
 		return;
@@ -1328,31 +1344,44 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
 
 	/* compute vertical fractional position */
 
-	y = 1.0 - (y / (_height - NAME_HIGHLIGHT_SIZE));
+	y = 1.0 - (y / (gain_line->height()));
 
 	/* map using gain line */
 
-	gain_line->view_to_model_coord (x, y);
+	gain_line->view_to_model_coord (mx, y);
 
 	/* XXX STATEFUL: can't convert to stateful diff until we
 	   can represent automation data with it.
 	*/
 
-	trackview.editor().begin_reversible_command (_("add gain control point"));
 	XMLNode &before = audio_region()->envelope()->get_state();
+	MementoCommand<AudioRegion>* region_memento = 0;
 
 	if (!audio_region()->envelope_active()) {
 		XMLNode &region_before = audio_region()->get_state();
 		audio_region()->set_envelope_active(true);
 		XMLNode &region_after = audio_region()->get_state();
-		trackview.session()->add_command (new MementoCommand<AudioRegion>(*(audio_region().get()), &region_before, &region_after));
+		region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), &region_before, &region_after);
 	}
 
-	audio_region()->envelope()->editor_add (fx, y, with_guard_points);
+	if (audio_region()->envelope()->editor_add (fx, y, with_guard_points)) {
+		XMLNode &after = audio_region()->envelope()->get_state();
+		std::list<Selectable*> results;
+
+		trackview.editor().begin_reversible_command (_("add gain control point"));
+
+		if (region_memento) {
+			trackview.session()->add_command (region_memento);
+		}
 
-	XMLNode &after = audio_region()->envelope()->get_state();
-	trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
-	trackview.editor().commit_reversible_command ();
+		trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
+
+		gain_line->get_selectables (fx + region ()->position (), fx + region ()->position (), 0.0, 1.0, results);
+		trackview.editor ().get_selection ().set (results);
+
+		trackview.editor ().commit_reversible_command ();
+		trackview.session ()->set_dirty ();
+	}
 }
 
 void
@@ -1369,7 +1398,7 @@ AudioRegionView::add_ghost (TimeAxisView& tv)
 	assert(rtv);
 
 	double unit_position = _region->position () / samples_per_pixel;
-	AudioGhostRegion* ghost = new AudioGhostRegion (tv, trackview, unit_position);
+	AudioGhostRegion* ghost = new AudioGhostRegion (*this, tv, trackview, unit_position);
 	uint32_t nchans;
 
 	nchans = rtv->track()->n_channels().n_audio();
diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc
index a20ae54..3ae1b21 100644
--- a/gtk2_ardour/automation_controller.cc
+++ b/gtk2_ardour/automation_controller.cc
@@ -40,6 +40,8 @@
 using namespace ARDOUR;
 using namespace Gtk;
 
+using PBD::Controllable;
+
 AutomationBarController::AutomationBarController (
 		boost::shared_ptr<Automatable>       printer,
 		boost::shared_ptr<AutomationControl> ac,
@@ -86,7 +88,6 @@ AutomationController::AutomationController(boost::shared_ptr<Automatable>
 		but->set_controllable(ac);
 		but->signal_clicked.connect(
 			sigc::mem_fun(*this, &AutomationController::toggled));
-
 		_widget = but;
 	} else {
 		AutomationBarController* bar = manage(new AutomationBarController(_printer, ac, adj));
@@ -154,7 +155,7 @@ void
 AutomationController::value_adjusted ()
 {
 	if (!_ignore_change) {
-		_controllable->set_value (_controllable->interface_to_internal(_adjustment->get_value()));
+		_controllable->set_value (_controllable->interface_to_internal(_adjustment->get_value()), Controllable::NoGroup);
 	}
 
 	/* A bar controller will automatically follow the adjustment, but for a
@@ -197,22 +198,27 @@ void
 AutomationController::toggled ()
 {
 	ArdourButton* but = dynamic_cast<ArdourButton*>(_widget);
+	const AutoState as = _controllable->automation_state ();
+	const double where = _controllable->session ().audible_frame ();
+	const bool to_list = _controllable->list () && _controllable->session().transport_rolling () && (as == Touch || as == Write);
+
 	if (but) {
-		if (_controllable->session().transport_rolling()) {
-			if (_controllable->automation_state() == Touch) {
-				_controllable->set_automation_state(Write);
-			}
-			if (_controllable->list()) {
-				_controllable->list()->set_in_write_pass(true, true, _controllable->session().audible_frame());
+		if (to_list) {
+			if (as == Touch && _controllable->list ()->in_new_write_pass ()) {
+				_controllable->alist ()->start_write_pass (where);
 			}
+			_controllable->list ()->set_in_write_pass (true, false, where);
 		}
-		const bool was_active = _controllable->get_value() >= 0.5;
-		if (was_active && but->get_active()) {
-			_adjustment->set_value(0.0);
-			but->set_active(false);
-		} else if (!was_active && !but->get_active()) {
-			_adjustment->set_value(1.0);
-			but->set_active(true);
+		/* set to opposite value.*/
+		_controllable->set_double (but->get_active () ? 0.0 : 1.0, where, to_list);
+
+		const bool active = _controllable->get_double (to_list, where) >= 0.5;
+		if (active && !but->get_active ()) {
+			_adjustment->set_value (1.0);
+			but->set_active (true);
+		} else if (!active && but->get_active ()) {
+			_adjustment->set_value (0.0);
+			but->set_active (false);
 		}
 	}
 }
@@ -244,7 +250,7 @@ AutomationController::run_note_select_dialog()
 		const double value = ((_controllable->desc().unit == ARDOUR::ParameterDescriptor::HZ)
 		                      ? midi_note_to_hz(dialog->note_number())
 		                      : dialog->note_number());
-		_controllable->set_value(clamp(value, desc.lower, desc.upper));
+		_controllable->set_value(clamp(value, desc.lower, desc.upper), Controllable::NoGroup);
 	}
 	delete dialog;
 }
@@ -259,7 +265,7 @@ AutomationController::set_freq_beats(double beats)
 	const double                       bpm     = tempo.beats_per_minute();
 	const double                       bps     = bpm / 60.0;
 	const double                       freq    = bps / beats;
-	_controllable->set_value(clamp(freq, desc.lower, desc.upper));
+	_controllable->set_value(clamp(freq, desc.lower, desc.upper), Controllable::NoGroup);
 }
 
 void
@@ -267,7 +273,7 @@ AutomationController::set_ratio(double ratio)
 {
 	const ARDOUR::ParameterDescriptor& desc  = _controllable->desc();
 	const double                       value = _controllable->get_value() * ratio;
-	_controllable->set_value(clamp(value, desc.lower, desc.upper));
+	_controllable->set_value(clamp(value, desc.lower, desc.upper), Controllable::NoGroup);
 }
 
 bool
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
index cb59e6d..2094d43 100644
--- a/gtk2_ardour/automation_line.cc
+++ b/gtk2_ardour/automation_line.cc
@@ -694,7 +694,6 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool
 	}
 
 	/* clamp y */
-
 	for (list<ControlPoint*>::iterator i = _drag_points.begin(); i != _drag_points.end(); ++i) {
 		double const y = ((_height - (*i)->get_y()) / _height) + dy;
 		if (y < 0) {
@@ -730,13 +729,13 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool
 			line->set_steps (line_points, is_stepped());
 		}
 	}
-
+	double const result_frac = _last_drag_fraction + dy;
 	_drag_distance += dx;
 	_drag_x += dx;
-	_last_drag_fraction = fraction;
+	_last_drag_fraction = result_frac;
 	did_push = with_push;
 
-	return pair<double, float> (_drag_x + dx, _last_drag_fraction + dy);
+	return pair<double, float> (_drag_x + dx, result_frac);
 }
 
 /** Should be called to indicate the end of a drag */
@@ -882,6 +881,7 @@ AutomationLine::remove_point (ControlPoint& cp)
 	trackview.editor().begin_reversible_command (_("remove control point"));
 	XMLNode &before = alist->get_state();
 
+	trackview.editor ().get_selection ().clear_points ();
 	alist->erase (cp.model());
 
 	trackview.editor().session()->add_command(
@@ -1226,7 +1226,7 @@ AutomationLine::model_to_view_coord_y (double& y) const
 	if (   alist->parameter().type() == GainAutomation
 	    || alist->parameter().type() == EnvelopeAutomation
 	    || (_desc.logarithmic && _desc.lower == 0. && _desc.upper > _desc.lower)) {
-		y = gain_to_slider_position_with_max (y, Config->get_max_gain());
+		y = gain_to_slider_position_with_max (y, _desc.upper);
 	} else if (alist->parameter().type() == TrimAutomation
 	           || (_desc.logarithmic && _desc.lower * _desc.upper > 0 && _desc.upper > _desc.lower)) {
 		const double lower_db = accurate_coefficient_to_dB (_desc.lower);
diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc
index 5450815..f1f9d68 100644
--- a/gtk2_ardour/automation_region_view.cc
+++ b/gtk2_ardour/automation_region_view.cc
@@ -187,17 +187,18 @@ AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double
 	double when_d = when;
 	_line->view_to_model_coord (when_d, y);
 
-	view->editor().begin_reversible_command (_("add automation event"));
 	XMLNode& before = _line->the_list()->get_state();
 
-	_line->the_list()->editor_add (when_d, y, with_guard_points);
+	if (_line->the_list()->editor_add (when_d, y, with_guard_points)) {
+		view->editor().begin_reversible_command (_("add automation event"));
 
-	XMLNode& after = _line->the_list()->get_state();
+		XMLNode& after = _line->the_list()->get_state();
 
-	view->session()->add_command (new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after));
-	view->editor().commit_reversible_command ();
+		view->session()->add_command (new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after));
+		view->editor().commit_reversible_command ();
 
-	view->session()->set_dirty ();
+		view->session()->set_dirty ();
+	}
 }
 
 bool
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 1c79593..cb2a3b4 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -628,28 +628,31 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
 
 	double x = 0;
 
-	_canvas_display->canvas_to_item (x, y);
+	_line->grab_item().canvas_to_item (x, y);
 
 	/* compute vertical fractional position */
 
-	y = 1.0 - (y / height);
+	y = 1.0 - (y / _line->height());
 
 	/* map using line */
 
 	_line->view_to_model_coord (x, y);
 
-
 	_editor.snap_to_with_modifier (when, event);
 
-	_editor.begin_reversible_command (_("add automation event"));
 	XMLNode& before = list->get_state();
+	std::list<Selectable*> results;
+	if (list->editor_add (when, y, with_guard_points)) {
+		XMLNode& after = list->get_state();
+		_editor.begin_reversible_command (_("add automation event"));
+		_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
 
-	list->editor_add (when, y, with_guard_points);
+		_line->get_selectables (when, when, 0.0, 1.0, results);
+		_editor.get_selection ().set (results);
 
-	XMLNode& after = list->get_state();
-	_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
-	_editor.commit_reversible_command ();
-	_session->set_dirty ();
+		_editor.commit_reversible_command ();
+		_session->set_dirty ();
+	}
 }
 
 bool
diff --git a/gtk2_ardour/bundle_env_cocoa.cc b/gtk2_ardour/bundle_env_cocoa.cc
index cd939ea..df951b8 100644
--- a/gtk2_ardour/bundle_env_cocoa.cc
+++ b/gtk2_ardour/bundle_env_cocoa.cc
@@ -105,10 +105,10 @@ fixup_bundle_environment (int, char* [], string & localedir)
 	g_setenv ("SUIL_MODULE_DIR", (bundle_dir + "/lib").c_str(), 1);
 	g_setenv ("PATH", (bundle_dir + "/MacOS:" + std::string(g_getenv ("PATH"))).c_str(), 1);
 
-	/* unset GTK_RC_FILES so that we only load the RC files that we define
+	/* unset GTK2_RC_FILES so that we only load the RC files that we define
 	 */
 
-	g_unsetenv ("GTK_RC_FILES");
+	g_unsetenv ("GTK2_RC_FILES");
 	g_setenv ("CHARSETALIASDIR", bundle_dir.c_str(), 1);
 	g_setenv ("FONTCONFIG_FILE", Glib::build_filename (bundle_dir, "Resources/fonts.conf").c_str(), 1);
 }
diff --git a/gtk2_ardour/bundle_env_linux.cc b/gtk2_ardour/bundle_env_linux.cc
index 259421b..2586ad5 100644
--- a/gtk2_ardour/bundle_env_linux.cc
+++ b/gtk2_ardour/bundle_env_linux.cc
@@ -59,6 +59,12 @@ fixup_bundle_environment (int /*argc*/, char* argv[], string & localedir)
 
 	std::string path;
 	std::string dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
+#if defined WINDOWS_VST_SUPPORT
+	// argv[0] will be "wine"
+	if (g_getenv ("INSTALL_DIR")) {
+		dir_path = g_getenv ("INSTALL_DIR");
+	}
+#endif
 
 #ifdef ENABLE_NLS
 	if (!ARDOUR::translations_are_enabled ()) {
@@ -88,10 +94,10 @@ fixup_bundle_environment (int /*argc*/, char* argv[], string & localedir)
 	g_setenv ("SUIL_MODULE_DIR", (dir_path + "/lib").c_str(), 1);
 	g_setenv ("PATH", (dir_path + "/bin:" + std::string(g_getenv ("PATH"))).c_str(), 1);
 
-	/* unset GTK_RC_FILES so that we only load the RC files that we define
+	/* unset GTK2_RC_FILES so that we only load the RC files that we define
 	 */
 
-	g_unsetenv ("GTK_RC_FILES");
+	g_unsetenv ("GTK2_RC_FILES");
 
 	/* Tell fontconfig where to find fonts.conf. Use the system version
 	   if it exists, otherwise use the stuff we included in the bundle
diff --git a/gtk2_ardour/bundle_env_mingw.cc b/gtk2_ardour/bundle_env_mingw.cc
index 7c54314..c2547be 100644
--- a/gtk2_ardour/bundle_env_mingw.cc
+++ b/gtk2_ardour/bundle_env_mingw.cc
@@ -50,8 +50,8 @@ fixup_bundle_environment (int, char* [], string & localedir)
 	// setting a FONTCONFIG_FILE won't hurt either see bundle_env_msvc.cc
 	// (pangocairo prefers the windows gdi backend unless PANGOCAIRO_BACKEND=fc is set)
 
-	// Unset GTK_RC_FILES so that only ardour specific files are loaded
-	Glib::unsetenv ("GTK_RC_FILES");
+	// Unset GTK2_RC_FILES so that only ardour specific files are loaded
+	Glib::unsetenv ("GTK2_RC_FILES");
 
 	std::string path;
 
diff --git a/gtk2_ardour/bundle_env_msvc.cc b/gtk2_ardour/bundle_env_msvc.cc
index 1987b03..864f9d8 100644
--- a/gtk2_ardour/bundle_env_msvc.cc
+++ b/gtk2_ardour/bundle_env_msvc.cc
@@ -467,8 +467,8 @@ fixup_bundle_environment (int argc, char* argv[], string & localedir)
 	Glib::setenv ("GTK_PATH", path, true);
 
 
-	// Unset GTK_RC_FILES so that we only load the RC files that we define
-	Glib::unsetenv ("GTK_RC_FILES");
+	// Unset GTK2_RC_FILES so that we only load the RC files that we define
+	Glib::unsetenv ("GTK2_RC_FILES");
 
 
 	// and set a '$HOME' environment variable. This variable changes the value returned
diff --git a/gtk2_ardour/clearlooks.rc.in b/gtk2_ardour/clearlooks.rc.in
index 5c51ace..e2a0463 100644
--- a/gtk2_ardour/clearlooks.rc.in
+++ b/gtk2_ardour/clearlooks.rc.in
@@ -985,11 +985,6 @@ style "ardour_button" ="default_button"
 	ythickness = 1
 }
 
-style "padded_button" = "default_button"
-{
-	xthickness = 8
-}
-
 style "tooltip" = "medium_text"
 {
 	fg[NORMAL] = @fg_tooltip
@@ -1032,8 +1027,6 @@ class "GtkCheckButton" style:highest "ardour_button"
 class "GtkArrow" style:highest "tearoff_arrow"
 class "GtkProgressBar" style:highest "ardour_progressbars"
 
-
-widget "*PaddedButton" style:highest "padded_button"
 widget "*VerboseCanvasCursor" style:highest "verbose_canvas_cursor"
 widget "*MarkerText" style:highest "marker_text"
 widget "*ArdourContextMenu*" style:highest "default_menu"
diff --git a/gtk2_ardour/dark.colors b/gtk2_ardour/dark.colors
index 500e5a3..2cdc39d 100644
--- a/gtk2_ardour/dark.colors
+++ b/gtk2_ardour/dark.colors
@@ -228,6 +228,9 @@
     <ColorAlias name="marker drag line" alias="color 44"/>
     <ColorAlias name="marker label" alias="color 4"/>
     <ColorAlias name="marker track" alias="color 31"/>
+    <ColorAlias name="master monitor section button normal: fill active" alias="color 42"/>
+    <ColorAlias name="master monitor section button active: fill"        alias="color 40"/>
+    <ColorAlias name="master monitor section button active: fill active" alias="color 54"/>
     <ColorAlias name="measure line bar" alias="color 13"/>
     <ColorAlias name="measure line beat" alias="color 33"/>
     <ColorAlias name="meter background bottom" alias="color 46"/>
@@ -287,33 +290,23 @@
     <ColorAlias name="mixer strip name button: led active" alias="color 8"/>
     <ColorAlias name="monitor button: fill active" alias="color 68"/>
     <ColorAlias name="monitor button: led active" alias="color 9"/>
-    <ColorAlias name="monitor knob" alias="color 60"/>
-    <ColorAlias name="monitor knob: arc end" alias="color 70"/>
-    <ColorAlias name="monitor knob: arc start" alias="color 16"/>
-    <ColorAlias name="monitor section cut: fill" alias="color 71"/>
-    <ColorAlias name="monitor section cut: fill active" alias="color 8"/>
-    <ColorAlias name="monitor section cut: led active" alias="color 37"/>
-    <ColorAlias name="monitor section dim: fill" alias="color 71"/>
-    <ColorAlias name="monitor section dim: fill active" alias="color 72"/>
-    <ColorAlias name="monitor section dim: led active" alias="color 37"/>
-    <ColorAlias name="monitor section invert: fill" alias="color 71"/>
-    <ColorAlias name="monitor section invert: fill active" alias="color 35"/>
-    <ColorAlias name="monitor section invert: led active" alias="color 37"/>
+    <ColorAlias name="monitor section knob" alias="color 60"/>
+    <ColorAlias name="monitor section knob: arc end" alias="color 70"/>
+    <ColorAlias name="monitor section knob: arc start" alias="color 16"/>
     <ColorAlias name="monitor section mono: fill" alias="color 71"/>
     <ColorAlias name="monitor section mono: fill active" alias="color 73"/>
     <ColorAlias name="monitor section mono: led active" alias="color 37"/>
+    <ColorAlias name="monitor section dim: fill" alias="color 71"/>
+    <ColorAlias name="monitor section dim: fill active" alias="color 72"/>
+    <ColorAlias name="monitor section dim: led active" alias="color 37"/>
     <ColorAlias name="monitor section solo model: fill" alias="color 71"/>
     <ColorAlias name="monitor section solo model: fill active" alias="color 42"/>
     <ColorAlias name="monitor section solo model: led active" alias="color 8"/>
-    <ColorAlias name="monitor section solo: fill" alias="color 71"/>
-    <ColorAlias name="monitor section solo: fill active" alias="color 12"/>
-    <ColorAlias name="monitor section solo: led active" alias="color 8"/>
-    <ColorAlias name="monitor solo exclusive: fill" alias="color 71"/>
-    <ColorAlias name="monitor solo exclusive: fill active" alias="color 20"/>
-    <ColorAlias name="monitor solo exclusive: led active" alias="color 8"/>
-    <ColorAlias name="monitor solo override: fill" alias="color 71"/>
-    <ColorAlias name="monitor solo override: fill active" alias="color 42"/>
-    <ColorAlias name="monitor solo override: led active" alias="color 8"/>
+    <ColorAlias name="monitor section solo option: fill" alias="color 71"/>
+    <ColorAlias name="monitor section solo option: fill active" alias="color 42"/>
+    <ColorAlias name="monitor section solo option: led active" alias="color 8"/>
+    <ColorAlias name="monitor section processors toggle: fill active" alias="color 42"/>
+    <ColorAlias name="monitor section processors present: fill" alias="color 20"/>
     <ColorAlias name="mono panner bg" alias="color 67"/>
     <ColorAlias name="mono panner fill" alias="color 74"/>
     <ColorAlias name="mono panner outline" alias="color 70"/>
@@ -338,6 +331,8 @@
     <ColorAlias name="piano roll white" alias="color 45"/>
     <ColorAlias name="play head" alias="color 9"/>
     <ColorAlias name="plugin bypass button: led active" alias="color 8"/>
+    <ColorAlias name="pluginlist hide button: led active" alias="color 14"/>
+    <ColorAlias name="pluginlist filter button: fill active" alias="color 14"/>
     <ColorAlias name="processor automation line" alias="color 77"/>
     <ColorAlias name="processor control button: fill" alias="color 29"/>
     <ColorAlias name="processor control button: fill active" alias="color 46"/>
@@ -470,7 +465,6 @@
     <ColorAlias name="trim knob: arc end" alias="color 81"/>
     <ColorAlias name="trim knob: arc start" alias="color 82"/>
     <ColorAlias name="verbose canvas cursor" alias="color 32"/>
-    <ColorAlias name="vestigial frame" alias="color 4"/>
     <ColorAlias name="video timeline bar" alias="color 46"/>
     <ColorAlias name="waveform fill" alias="color 13"/>
     <ColorAlias name="waveform outline" alias="color 4"/>
diff --git a/gtk2_ardour/duplicate_routes_dialog.cc b/gtk2_ardour/duplicate_routes_dialog.cc
new file mode 100644
index 0000000..b69d17c
--- /dev/null
+++ b/gtk2_ardour/duplicate_routes_dialog.cc
@@ -0,0 +1,181 @@
+/*
+    Copyright (C) 2015 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "gtkmm/stock.h"
+
+#include "ardour/route.h"
+#include "ardour/session.h"
+
+#include "editor.h"
+#include "duplicate_routes_dialog.h"
+#include "selection.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+
+DuplicateRouteDialog::DuplicateRouteDialog ()
+	: ArdourDialog (_("Duplicate Tracks & Busses"), false, false)
+	, copy_playlists_button (playlist_button_group, _("Copy playlists"))
+	, new_playlists_button (playlist_button_group, _("Create new (empty) playlists"))
+	, share_playlists_button (playlist_button_group, _("Share playlists"))
+	, count_adjustment (1.0, 1.0, 999, 1.0, 10.0)
+	, count_spinner (count_adjustment)
+	, count_label (_("Duplicate each track/bus this number of times:"))
+{
+	count_box.pack_start (count_label, false, false);
+	count_box.pack_start (count_spinner, false, false, 5);
+	get_vbox()->pack_start (count_box, false, false, 10);
+
+	playlist_button_box.pack_start (copy_playlists_button, false, false);
+	playlist_button_box.pack_start (new_playlists_button, false, false);
+	playlist_button_box.pack_start (share_playlists_button, false, false);
+	playlist_button_box.show_all ();
+
+	get_vbox()->show_all ();
+
+	add_button (Stock::CANCEL, RESPONSE_CANCEL);
+	add_button (Stock::OK, RESPONSE_OK);
+}
+
+int
+DuplicateRouteDialog::restart (Session* s)
+{
+	if (!s) {
+		return -1;
+	}
+
+	set_session (s);
+
+	TrackSelection& tracks  (PublicEditor::instance().get_selection().tracks);
+	uint32_t ntracks = 0;
+	uint32_t nbusses = 0;
+
+	for (TrackSelection::iterator t = tracks.begin(); t != tracks.end(); ++t) {
+
+		RouteUI* rui = dynamic_cast<RouteUI*> (*t);
+
+		if (!rui) {
+			/* some other type of timeaxis view, not a route */
+			continue;
+		}
+
+		boost::shared_ptr<Route> r (rui->route());
+
+		if (boost::dynamic_pointer_cast<Track> (r)) {
+			ntracks++;
+		} else {
+			if (!r->is_master() && !r->is_monitor()) {
+				nbusses++;
+			}
+		}
+	}
+
+	if (ntracks == 0 && nbusses == 0) {
+		std::cerr << "You can't do this\n";
+		return -1;
+	}
+
+	/* XXX grrr. Gtk Boxes do not shrink when children are removed,
+	   which is what we really want to happen here.
+	*/
+
+	if (playlist_button_box.get_parent()) {
+		get_vbox()->remove (playlist_button_box);
+	}
+
+	if (ntracks > 0) {
+		get_vbox()->pack_end (playlist_button_box, false, false);
+	}
+
+	return 0;
+}
+
+uint32_t
+DuplicateRouteDialog::count() const
+{
+	return count_adjustment.get_value ();
+}
+
+ARDOUR::PlaylistDisposition
+DuplicateRouteDialog::playlist_disposition() const
+{
+	if (new_playlists_button.get_active()) {
+		return ARDOUR::NewPlaylist;
+	} else if (copy_playlists_button.get_active()) {
+		return ARDOUR::CopyPlaylist;
+	}
+
+	return ARDOUR::SharePlaylist;
+}
+
+void
+DuplicateRouteDialog::on_response (int response)
+{
+	hide ();
+
+	if (response != RESPONSE_OK) {
+		return;
+	}
+
+	ARDOUR::PlaylistDisposition playlist_action = playlist_disposition ();
+	uint32_t cnt = count ();
+
+	/* Copy the track selection because it will/may change as we add new ones */
+	TrackSelection tracks  (PublicEditor::instance().get_selection().tracks);
+	int err = 0;
+
+	for (TrackSelection::iterator t = tracks.begin(); t != tracks.end(); ++t) {
+
+		RouteUI* rui = dynamic_cast<RouteUI*> (*t);
+
+		if (!rui) {
+			/* some other type of timeaxis view, not a route */
+			continue;
+		}
+
+		if (rui->route()->is_master() || rui->route()->is_monitor()) {
+			/* no option to duplicate these */
+			continue;
+		}
+
+		XMLNode& state (rui->route()->get_state());
+		RouteList rl = _session->new_route_from_template (cnt, state, std::string(), playlist_action);
+
+		/* normally the state node would be added to a parent, and
+		 * ownership would transfer. Because we don't do that here,
+		 * we need to delete the node ourselves.
+		 */
+
+		delete &state;
+
+		if (rl.empty()) {
+			err++;
+			break;
+		}
+	}
+
+	if (err) {
+		MessageDialog msg (_("1 or more tracks/busses could not be duplicated"),
+		                     true, MESSAGE_ERROR, BUTTONS_OK, true);
+		msg.set_position (WIN_POS_MOUSE);
+		msg.run ();
+	}
+}
diff --git a/gtk2_ardour/duplicate_routes_dialog.h b/gtk2_ardour/duplicate_routes_dialog.h
new file mode 100644
index 0000000..531ce9c
--- /dev/null
+++ b/gtk2_ardour/duplicate_routes_dialog.h
@@ -0,0 +1,64 @@
+/*
+    Copyright (C) 2015 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __gtk_ardour_duplicate_route_dialog_h__
+#define __gtk_ardour_duplicate_route_dialog_h__
+
+#include <gtkmm/entry.h>
+#include <gtkmm/box.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/adjustment.h>
+#include <gtkmm/spinbutton.h>
+
+#include "ardour/types.h"
+
+#include "ardour_dialog.h"
+
+namespace ARDOUR {
+class Session;
+}
+
+class Editor;
+
+class DuplicateRouteDialog : public ArdourDialog
+{
+  public:
+	DuplicateRouteDialog ();
+
+	int restart (ARDOUR::Session*);
+
+  private:
+	Gtk::Entry name_template_entry;
+	Gtk::VBox playlist_button_box;
+	Gtk::RadioButtonGroup playlist_button_group;
+	Gtk::RadioButton copy_playlists_button;
+	Gtk::RadioButton new_playlists_button;
+	Gtk::RadioButton share_playlists_button;
+	Gtk::Adjustment count_adjustment;
+	Gtk::SpinButton count_spinner;
+	Gtk::HBox count_box;
+	Gtk::Label count_label;
+
+	void on_response (int);
+
+	uint32_t count() const;
+	ARDOUR::PlaylistDisposition playlist_disposition() const;
+};
+
+#endif /* __gtk_ardour_duplicate_route_dialog_h__ */
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 9ed6935..a77fafe 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -822,6 +822,10 @@ Editor::~Editor()
 	delete _snapshots;
 	delete _locations;
 	delete _playlist_selector;
+
+	for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
+		delete *i;
+	}
 }
 
 XMLNode*
@@ -1890,14 +1894,13 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
 
 	edit_items.push_back (SeparatorElem());
 	edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
-	edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
 	edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
 
 	edit_items.push_back (SeparatorElem());
 	edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
-	edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
+	edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
 	edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
-	edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
+	edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
 	edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
 	if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
 		edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
@@ -1916,8 +1919,8 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
 	MenuList& play_items = play_menu->items();
 	play_menu->set_name ("ArdourContextMenu");
 
-	play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
-	play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
+	play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
+	play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
 	play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
 	play_items.push_back (SeparatorElem());
 	play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
@@ -1998,8 +2001,8 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
 	MenuList& play_items = play_menu->items();
 	play_menu->set_name ("ArdourContextMenu");
 
-	play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
-	play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
+	play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
+	play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
 	edit_items.push_back (MenuElem (_("Play"), *play_menu));
 
 	/* Selection */
@@ -3233,7 +3236,7 @@ Editor::build_snap_type_menu ()
 void
 Editor::setup_tooltips ()
 {
-	set_tooltip (smart_mode_button, _("Smart Mode (add Range functions to Grab mode)"));
+	set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
 	set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
 	set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
 	set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
@@ -3248,13 +3251,13 @@ Editor::setup_tooltips ()
 	set_tooltip (zoom_out_button, _("Zoom Out"));
 	set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
 	set_tooltip (zoom_out_full_button, _("Zoom to Session"));
-	set_tooltip (zoom_focus_selector, _("Zoom focus"));
+	set_tooltip (zoom_focus_selector, _("Zoom Focus"));
 	set_tooltip (tav_expand_button, _("Expand Tracks"));
 	set_tooltip (tav_shrink_button, _("Shrink Tracks"));
 	set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
 	set_tooltip (snap_type_selector, _("Snap/Grid Units"));
 	set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
-	set_tooltip (edit_point_selector, _("Edit point"));
+	set_tooltip (edit_point_selector, _("Edit Point"));
 	set_tooltip (edit_mode_selector, _("Edit Mode"));
 	set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
 }
@@ -3534,8 +3537,10 @@ Editor::history_changed ()
 	if (redo_action && _session) {
 		if (_session->redo_depth() == 0) {
 			label = _("Redo");
+			redo_action->set_sensitive (false);
 		} else {
 			label = string_compose(_("Redo (%1)"), _session->next_redo());
+			redo_action->set_sensitive (true);
 		}
 		redo_action->property_label() = label;
 	}
@@ -4154,19 +4159,34 @@ Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
 
 	label.show ();
 
+	dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
 	dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
-	dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
+	Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
+	dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
 	dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
 
+	// by default gtk uses the left most button
+	keep->grab_focus ();
+
 	switch (dialog.run ()) {
+	case RESPONSE_NO:
+		/* keep this and all remaining ones */
+		return -2;
+		break;
+
+	case RESPONSE_YES:
+		/* delete this and all others */
+		return 2;
+		break;
+
 	case RESPONSE_ACCEPT:
 		/* delete the playlist */
-		return 0;
+		return 1;
 		break;
 
 	case RESPONSE_REJECT:
 		/* keep the playlist */
-		return 1;
+		return 0;
 		break;
 
 	default:
@@ -5072,6 +5092,7 @@ Editor::first_idle ()
 	MessageDialog* dialog = 0;
 
 	if (track_views.size() > 1) {
+		Timers::TimerSuspender t;
 		dialog = new MessageDialog (
 			*this,
 			string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
@@ -5697,7 +5718,7 @@ Editor::super_rapid_screen_update ()
 
 		} else {
 
-			if (!_dragging_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
+			if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
 				framepos_t const frame = playhead_cursor->current_frame ();
 				double target = ((double)frame - (double)current_page_samples()/3.0);
 				if (target <= 0.0) {
@@ -5951,20 +5972,41 @@ Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
 
 	MidiRegionView&       mrv = note->region_view();
 	const RegionSelection rs  = get_regions_from_selection_and_entered ();
+	const uint32_t sel_size = mrv.selection_size ();
 
 	MenuList& items = _note_context_menu.items();
 	items.clear();
 
-	items.push_back(MenuElem(_("Delete"),
-	                         sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
+	if (sel_size > 0) {
+		items.push_back(MenuElem(_("Delete"),
+					 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
+	}
+
 	items.push_back(MenuElem(_("Edit..."),
-	                         sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
+				 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
+	if (sel_size != 1) {
+		items.back().set_sensitive (false);
+	}
+
+	items.push_back(MenuElem(_("Transpose..."),
+	                         sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
+
+
 	items.push_back(MenuElem(_("Legatize"),
-	                         sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
+				 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
+	if (sel_size < 2) {
+		items.back().set_sensitive (false);
+	}
+
 	items.push_back(MenuElem(_("Quantize..."),
 	                         sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
+
 	items.push_back(MenuElem(_("Remove Overlap"),
-	                         sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
+				 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
+	if (sel_size < 2) {
+		items.back().set_sensitive (false);
+	}
+
 	items.push_back(MenuElem(_("Transform..."),
 	                         sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
 
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index f558355..77156cb 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -67,20 +67,21 @@ namespace Gtkmm2ext {
 }
 
 namespace ARDOUR {
-	class RouteGroup;
-	class Playlist;
 	class AudioPlaylist;
 	class AudioRegion;
-	class Region;
-	class Location;
-	class TempoSection;
-	class Session;
-	class Filter;
+	class AudioTrack;
 	class ChanCount;
+	class Filter;
+	class Location;
 	class MidiOperator;
-	class Track;
+	class MidiRegion;
 	class MidiTrack;
-	class AudioTrack;
+	class Playlist;
+	class Region;
+	class RouteGroup;
+	class Session;
+	class TempoSection;
+	class Track;
 }
 
 namespace LADSPA {
@@ -113,6 +114,7 @@ class GroupedButtons;
 class GUIObjectState;
 class ArdourMarker;
 class MidiRegionView;
+class MidiExportDialog;
 class MixerStrip;
 class MouseCursors;
 class NoteBase;
@@ -282,6 +284,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 	void export_range ();
 	void export_region ();
 
+	bool process_midi_export_dialog (MidiExportDialog& dialog, boost::shared_ptr<ARDOUR::MidiRegion> midi_region);
+
 	void add_transport_frame (Gtk::Container&);
 	void add_toplevel_menu (Gtk::Container&);
 	Gtk::HBox& get_status_bar_packer()  { return status_bar_hpacker; }
@@ -1258,6 +1262,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 	void legatize_regions (const RegionSelection& rs, bool shrink_only);
 	void transform_region ();
 	void transform_regions (const RegionSelection& rs);
+	void transpose_region ();
+	void transpose_regions (const RegionSelection& rs);
 	void insert_patch_change (bool from_context);
 	void fork_region ();
 
@@ -2029,8 +2035,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 	int pitch_shift (RegionSelection&, float cents);
 	void pitch_shift_region ();
 
-	void transpose_region ();
-
 	/* editor-mixer strip */
 
 	MixerStrip *current_mixer_strip;
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index c8e52d8..82ca08c 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -263,8 +263,8 @@ Editor::register_actions ()
 
 	reg_sens (editor_actions, "nudge-playhead-forward", _("Nudge Playhead Forward"), sigc::bind (sigc::mem_fun(*this, &Editor::nudge_forward), false, true));
 	reg_sens (editor_actions, "nudge-playhead-backward", _("Nudge Playhead Backward"), sigc::bind (sigc::mem_fun(*this, &Editor::nudge_backward), false, true));
-	reg_sens (editor_actions, "playhead-forward-to-grid", _("Playhead To Next Grid"), sigc::mem_fun(*this, &Editor::playhead_forward_to_grid));
-	reg_sens (editor_actions, "playhead-backward-to-grid", _("Playhead To Previous Grid"), sigc::mem_fun(*this, &Editor::playhead_backward_to_grid));
+	reg_sens (editor_actions, "playhead-forward-to-grid", _("Playhead to Next Grid"), sigc::mem_fun(*this, &Editor::playhead_forward_to_grid));
+	reg_sens (editor_actions, "playhead-backward-to-grid", _("Playhead to Previous Grid"), sigc::mem_fun(*this, &Editor::playhead_backward_to_grid));
 
 	reg_sens (editor_actions, "temporal-zoom-out", _("Zoom Out"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_step), true));
 	reg_sens (editor_actions, "temporal-zoom-in", _("Zoom In"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_step), false));
@@ -308,7 +308,7 @@ Editor::register_actions ()
 
 	/* this is a duplicated action so that the main menu can use a different label */
 	reg_sens (editor_actions, "main-menu-play-selected-regions", _("Play Selected Regions"), sigc::mem_fun (*this, &Editor::play_selected_region));
-	reg_sens (editor_actions, "play-from-edit-point", _("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point));
+	reg_sens (editor_actions, "play-from-edit-point", _("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point));
 	reg_sens (editor_actions, "play-from-edit-point-and-return", _("Play from Edit Point and Return"), sigc::mem_fun(*this, &Editor::play_from_edit_point_and_return));
 
 	reg_sens (editor_actions, "play-edit-range", _("Play Edit Range"), sigc::mem_fun(*this, &Editor::play_edit_range));
@@ -706,7 +706,7 @@ Editor::register_actions ()
 	act = reg_sens (editor_actions, X_("addExternalAudioToRegionList"), _("Import to Region List..."), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
 	ActionManager::write_sensitive_actions.push_back (act);
 
-	act = ActionManager::register_action (editor_actions, X_("importFromSession"), _("Import From Session"), sigc::mem_fun(*this, &Editor::session_import_dialog));
+	act = ActionManager::register_action (editor_actions, X_("importFromSession"), _("Import from Session"), sigc::mem_fun(*this, &Editor::session_import_dialog));
 	ActionManager::write_sensitive_actions.push_back (act);
 
 
@@ -1897,7 +1897,7 @@ Editor::register_region_actions ()
 		);
 
 	/* Snap selected regions to the grid */
-	reg_sens (_region_actions, "snap-regions-to-grid", _("Snap Position To Grid"), sigc::mem_fun (*this, &Editor::snap_regions_to_grid));
+	reg_sens (_region_actions, "snap-regions-to-grid", _("Snap Position to Grid"), sigc::mem_fun (*this, &Editor::snap_regions_to_grid));
 
 	/* Close gaps in selected regions */
 	reg_sens (_region_actions, "close-region-gaps", _("Close Gaps"), sigc::mem_fun (*this, &Editor::close_region_gaps));
@@ -1998,7 +1998,7 @@ Editor::register_region_actions ()
 	reg_sens (
 		_region_actions,
 		"insert-region-from-region-list",
-		_("Insert Region From Region List"),
+		_("Insert Region from Region List"),
 		sigc::bind (sigc::mem_fun (*this, &Editor::insert_region_list_selection), 1)
 		);
 
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index 36c9e34..233a3fb 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -698,6 +698,7 @@ Editor::autoscroll_canvas ()
 		ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
 		ev.x = d.x;
 		ev.y = d.y;
+		ev.state = mask;
 
 		motion_handler (0, (GdkEvent*) &ev, true);
 
@@ -738,6 +739,7 @@ Editor::autoscroll_canvas ()
 		ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
 		ev.x = d.x;
 		ev.y = d.y;
+		ev.state = mask;
 
 		motion_handler (0, (GdkEvent*) &ev, true);
 
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index 5a8abad..77cfde0 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -64,10 +64,6 @@ using Gtkmm2ext::Keyboard;
 bool
 Editor::track_canvas_scroll (GdkEventScroll* ev)
 {
-	if (Keyboard::some_magic_widget_has_focus()) {
-		return false;
-	}
-
 	framepos_t xdelta;
 	int direction = ev->direction;
 
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index d5466a1..12cea26 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -82,7 +82,10 @@ double ControlPointDrag::_zero_gain_fraction = -1.0;
 DragManager::DragManager (Editor* e)
 	: _editor (e)
 	, _ending (false)
+	, _current_pointer_x (0.0)
+	, _current_pointer_y (0.0)
 	, _current_pointer_frame (0)
+	, _old_follow_playhead (false)
 {
 }
 
@@ -215,15 +218,21 @@ DragManager::have_item (ArdourCanvas::Item* i) const
 
 Drag::Drag (Editor* e, ArdourCanvas::Item* i, bool trackview_only)
 	: _editor (e)
+	, _drags (0)
 	, _item (i)
 	, _pointer_frame_offset (0)
 	, _x_constrained (false)
 	, _y_constrained (false)
+	, _was_rolling (false)
 	, _trackview_only (trackview_only)
 	, _move_threshold_passed (false)
 	, _starting_point_passed (false)
 	, _initially_vertical (false)
 	, _was_double_click (false)
+	, _grab_x (0.0)
+	, _grab_y (0.0)
+	, _last_pointer_x (0.0)
+	, _last_pointer_y (0.0)
 	, _raw_grab_frame (0)
 	, _grab_frame (0)
 	, _last_pointer_frame (0)
@@ -455,7 +464,7 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
 
 				_last_pointer_x = _drags->current_pointer_x ();
 				_last_pointer_y = current_pointer_y ();
-				_last_pointer_frame = adjusted_current_frame (event);
+				_last_pointer_frame = adjusted_current_frame (event, false);
 			}
 
 			return true;
@@ -501,7 +510,7 @@ Drag::show_verbose_cursor_text (string const & text)
 }
 
 boost::shared_ptr<Region>
-Drag::add_midi_region (MidiTimeAxisView* view)
+Drag::add_midi_region (MidiTimeAxisView* view, bool commit)
 {
 	if (_editor->session()) {
 		const TempoMap& map (_editor->session()->tempo_map());
@@ -511,7 +520,7 @@ Drag::add_midi_region (MidiTimeAxisView* view)
 		   might be wrong.
 		*/
 		framecnt_t len = m.frames_per_bar (map.tempo_at (pos), _editor->session()->frame_rate());
-		return view->add_region (grab_frame(), len, true);
+		return view->add_region (grab_frame(), len, commit);
 	}
 
 	return boost::shared_ptr<Region>();
@@ -636,7 +645,7 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
 	/* compute the amount of pointer motion in frames, and where
 	   the region would be if we moved it by that much.
 	*/
-	*pending_region_position = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
+	*pending_region_position = adjusted_frame (_drags->current_pointer_frame (), event, false);
 
 	framepos_t sync_frame;
 	framecnt_t sync_offset;
@@ -648,11 +657,12 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
 	 */
 	if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
 
-		sync_frame = *pending_region_position + (sync_dir * sync_offset);
+		framecnt_t const sd = snap_delta (event->button.state);
+		sync_frame = *pending_region_position + (sync_dir * sync_offset) + sd;
 
 		_editor->snap_to_with_modifier (sync_frame, event);
 
-		*pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - snap_delta (event->button.state);
+		*pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - sd;
 
 	} else {
 		*pending_region_position = _last_frame_position;
@@ -1829,6 +1839,7 @@ RegionMotionDrag::aborted (bool)
 RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b, bool c)
 	: RegionMotionDrag (e, i, p, v, b)
 	, _copy (c)
+	, _new_region_view (0)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New RegionMoveDrag\n");
 
@@ -2293,13 +2304,14 @@ void
 RegionCreateDrag::motion (GdkEvent* event, bool first_move)
 {
 	if (first_move) {
-		_region = add_midi_region (_view);
+		_editor->begin_reversible_command (_("create region"));
+		_region = add_midi_region (_view, false);
 		_view->playlist()->freeze ();
 	} else {
 		if (_region) {
 			framepos_t const f = adjusted_current_frame (event);
 			if (f < grab_frame()) {
-				_region->set_position (f);
+				_region->set_initial_position (f);
 			}
 
 			/* Don't use a zero-length region, and subtract 1 frame from the snapped length
@@ -2319,9 +2331,10 @@ void
 RegionCreateDrag::finished (GdkEvent*, bool movement_occurred)
 {
 	if (!movement_occurred) {
-		add_midi_region (_view);
+		add_midi_region (_view, true);
 	} else {
 		_view->playlist()->thaw ();
+		_editor->commit_reversible_command();
 	}
 }
 
@@ -2340,6 +2353,7 @@ NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
 	, region (0)
 	, relative (false)
 	, at_front (true)
+	, _was_selected (false)
 	, _snap_delta (0)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New NoteResizeDrag\n");
@@ -2381,10 +2395,27 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
 		/* has to be relative, may make no sense otherwise */
 		relative = true;
 	}
-	/* select this note; if it is already selected, preserve the existing selection,
-	   otherwise make this note the only one selected.
-	*/
-	region->note_selected (cnote, cnote->selected ());
+
+	if (!(_was_selected = cnote->selected())) {
+
+		/* tertiary-click means extend selection - we'll do that on button release,
+		   so don't add it here, because otherwise we make it hard to figure
+		   out the "extend-to" range.
+		*/
+
+		bool extend = Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier);
+
+		if (!extend) {
+			bool add = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+
+			if (add) {
+				region->note_selected (cnote, true);
+			} else {
+				_editor->get_selection().clear_points();
+				region->unique_select (cnote);
+			}
+		}
+	}
 }
 
 void
@@ -2442,6 +2473,46 @@ void
 NoteResizeDrag::finished (GdkEvent* event, bool movement_occurred)
 {
 	if (!movement_occurred) {
+		/* no motion - select note */
+		NoteBase* cnote = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
+		if (_editor->current_mouse_mode() == Editing::MouseContent ||
+		    _editor->current_mouse_mode() == Editing::MouseDraw) {
+
+			bool changed = false;
+
+			if (_was_selected) {
+				bool add = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+				if (add) {
+					region->note_deselected (cnote);
+					changed = true;
+				} else {
+					_editor->get_selection().clear_points();
+					region->unique_select (cnote);
+					changed = true;
+				}
+			} else {
+				bool extend = Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier);
+				bool add = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+
+				if (!extend && !add && region->selection_size() > 1) {
+					_editor->get_selection().clear_points();
+					region->unique_select (cnote);
+					changed = true;
+				} else if (extend) {
+					region->note_selected (cnote, true, true);
+					changed = true;
+				} else {
+					/* it was added during button press */
+					changed = true;
+				}
+			}
+
+			if (changed) {
+				_editor->begin_reversible_selection_op(X_("Resize Select Note Release"));
+				_editor->commit_reversible_selection_op();
+			}
+		}
+
 		return;
 	}
 
@@ -2669,6 +2740,7 @@ VideoTimeLineDrag::aborted (bool)
 
 TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool preserve_fade_anchor)
 	: RegionDrag (e, i, p, v)
+	, _operation (StartTrim)
 	, _preserve_fade_anchor (preserve_fade_anchor)
 	, _jump_position_when_done (false)
 {
@@ -2726,9 +2798,6 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
 	switch (_operation) {
 	case StartTrim:
 		show_verbose_cursor_time (region_start);
-		for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
-			i->view->trim_front_starting ();
-		}
 		break;
 	case EndTrim:
 		show_verbose_cursor_duration (region_start, region_end);
@@ -2786,6 +2855,10 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
 			rv->enable_display (false);
 			rv->region()->playlist()->clear_owned_changes ();
 
+			if (_operation == StartTrim) {
+				rv->trim_front_starting ();
+			}
+
 			AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (rv);
 
 			if (arv) {
@@ -2989,14 +3062,12 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
 
 	} else {
 		/* no mouse movement */
-		_editor->point_trim (event, adjusted_current_frame (event));
+		if (adjusted_current_frame (event) != adjusted_frame (_drags->current_pointer_frame(), event, false)) {
+			_editor->point_trim (event, adjusted_current_frame (event));
+		}
 	}
 
 	for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
-		if (_operation == StartTrim) {
-			i->view->trim_front_ending ();
-		}
-
 		i->view->region()->resume_property_changes ();
 	}
 }
@@ -3047,6 +3118,7 @@ TrimDrag::setup_pointer_frame_offset ()
 MeterMarkerDrag::MeterMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
 	: Drag (e, i),
 	  _copy (c)
+	, before_state (0)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New MeterMarkerDrag\n");
 	_marker = reinterpret_cast<MeterMarker*> (_item->get_data ("marker"));
@@ -3134,7 +3206,7 @@ MeterMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 	Timecode::BBT_Time when;
 
 	TempoMap& map (_editor->session()->tempo_map());
-	map.bbt_time (last_pointer_frame(), when);
+	map.bbt_time (_marker->position(), when);
 
 	if (_copy == true) {
 		_editor->begin_reversible_command (_("copy meter mark"));
@@ -3176,8 +3248,9 @@ MeterMarkerDrag::aborted (bool moved)
 }
 
 TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
-	: Drag (e, i),
-	  _copy (c)
+	: Drag (e, i)
+	, _copy (c)
+	, before_state (0)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n");
 
@@ -3232,6 +3305,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
 		swap_grab (&_marker->the_item(), 0, GDK_CURRENT_TIME);
 
 		if (!_copy) {
+			_editor->begin_reversible_command (_("move tempo mark"));
 			TempoMap& map (_editor->session()->tempo_map());
 			/* get current state */
 			before_state = &map.get_state();
@@ -3262,7 +3336,7 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 	motion (event, false);
 
 	TempoMap& map (_editor->session()->tempo_map());
-	framepos_t beat_time = map.round_to_beat (last_pointer_frame(), RoundNearest);
+	framepos_t beat_time = map.round_to_beat (_marker->position(), RoundNearest);
 	Timecode::BBT_Time when;
 
 	map.bbt_time (beat_time, when);
@@ -3276,7 +3350,6 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 		_editor->commit_reversible_command ();
 
 	} else {
-		_editor->begin_reversible_command (_("move tempo mark"));
 		/* we removed it before, so add it back now */
 		map.add_tempo (_marker->tempo(), when);
 		XMLNode &after = map.get_state();
@@ -3307,6 +3380,7 @@ CursorDrag::CursorDrag (Editor* e, EditorCursor& c, bool s)
 	: Drag (e, &c.track_canvas_item(), false)
 	, _cursor (c)
 	, _stop (s)
+	, _grab_zoom (0.0)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New CursorDrag\n");
 }
@@ -3685,6 +3759,7 @@ FadeOutDrag::aborted (bool)
 
 MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i)
 	: Drag (e, i)
+	, _selection_changed (false)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New MarkerDrag\n");
 
@@ -3729,6 +3804,7 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 	} else {
 		show_verbose_cursor_time (location->end());
 	}
+	setup_snap_delta (is_start ? location->start() : location->end());
 
 	Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
 
@@ -3739,6 +3815,7 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 	case Selection::Set:
 		if (!_editor->selection->selected (_marker)) {
 			_editor->selection->set (_marker);
+			_selection_changed = true;
 		}
 		break;
 	case Selection::Extend:
@@ -3768,11 +3845,14 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 		}
 		if (!to_add.empty()) {
 			_editor->selection->add (to_add);
+			_selection_changed = true;
 		}
 		break;
 	}
 	case Selection::Add:
 		_editor->selection->add (_marker);
+		_selection_changed = true;
+
 		break;
 	}
 
@@ -3826,8 +3906,9 @@ MarkerDrag::motion (GdkEvent* event, bool)
 	bool move_both = false;
 	Location *real_location;
 	Location *copy_location = 0;
+	framecnt_t const sd = snap_delta (event->button.state);
 
-	framepos_t const newframe = adjusted_current_frame (event);
+	framecnt_t const newframe = adjusted_frame (_drags->current_pointer_frame () + sd, event, true) - sd;
 	framepos_t next = newframe;
 
 	if (Keyboard::modifier_state_contains (event->button.state, ArdourKeyboard::push_points_modifier ())) {
@@ -3920,7 +4001,7 @@ MarkerDrag::motion (GdkEvent* event, bool)
 				} else 	if (new_start < copy_location->end()) {
 					copy_location->set_start (new_start);
 				} else if (newframe > 0) {
-					_editor->snap_to (next, RoundUpAlways, true);
+					//_editor->snap_to (next, RoundUpAlways, true);
 					copy_location->set_end (next);
 					copy_location->set_start (newframe);
 				}
@@ -3933,7 +4014,7 @@ MarkerDrag::motion (GdkEvent* event, bool)
 				} else if (new_end > copy_location->start()) {
 					copy_location->set_end (new_end);
 				} else if (newframe > 0) {
-					_editor->snap_to (next, RoundDownAlways, true);
+					//_editor->snap_to (next, RoundDownAlways, true);
 					copy_location->set_start (next);
 					copy_location->set_end (newframe);
 				}
@@ -3977,17 +4058,19 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 		*/
 
 		Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
-
 		switch (op) {
 		case Selection::Set:
 			if (_editor->selection->selected (_marker) && _editor->selection->markers.size() > 1) {
 				_editor->selection->set (_marker);
+				_selection_changed = true;
 			}
 			break;
 
 		case Selection::Toggle:
 			/* we toggle on the button release, click only */
 			_editor->selection->toggle (_marker);
+			_selection_changed = true;
+
 			break;
 
 		case Selection::Extend:
@@ -3995,6 +4078,11 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 			break;
 		}
 
+		if (_selection_changed) {
+			_editor->begin_reversible_selection_op(X_("Select Marker Release"));
+			_editor->commit_reversible_selection_op();
+		}
+
 		return;
 	}
 
@@ -4068,10 +4156,13 @@ MarkerDrag::update_item (Location*)
 }
 
 ControlPointDrag::ControlPointDrag (Editor* e, ArdourCanvas::Item* i)
-	: Drag (e, i),
-	  _cumulative_x_drag (0)
-	, _cumulative_y_drag (0)
+	: Drag (e, i)
+	, _fixed_grab_x (0.0)
+	, _fixed_grab_y (0.0)
+	, _cumulative_x_drag (0.0)
+	, _cumulative_y_drag (0.0)
 	, _pushing (false)
+	, _final_index (0)
 {
 	if (_zero_gain_fraction < 0.0) {
 		_zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain());
@@ -4112,10 +4203,12 @@ ControlPointDrag::motion (GdkEvent* event, bool first_motion)
 {
 	double dx = _drags->current_pointer_x() - last_pointer_x();
 	double dy = current_pointer_y() - last_pointer_y();
+	bool need_snap = true;
 
-	if (event->button.state & ArdourKeyboard::fine_adjust_modifier ()) {
+	if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::fine_adjust_modifier ())) {
 		dx *= 0.1;
 		dy *= 0.1;
+		need_snap = false;
 	}
 
 	/* coordinate in pixels relative to the start of the region (for region-based automation)
@@ -4137,18 +4230,18 @@ ControlPointDrag::motion (GdkEvent* event, bool first_motion)
 	_cumulative_x_drag = cx - _fixed_grab_x;
 	_cumulative_y_drag = cy - _fixed_grab_y;
 
+	cx = max (0.0, cx);
+	cy = max (0.0, cy);
+	cy = min ((double) _point->line().height(), cy);
+
 	// make sure we hit zero when passing through
 	if ((cy < zero_gain_y && (cy - dy) > zero_gain_y) || (cy > zero_gain_y && (cy - dy) < zero_gain_y)) {
 		cy = zero_gain_y;
 	}
 
-	cx = max (0.0, cx);
-	cy = max (0.0, cy);
-	cy = min ((double) _point->line().height(), cy);
-
 	framepos_t cx_frames = _editor->pixel_to_sample (cx) + snap_delta (event->button.state);
 
-	if (!_x_constrained) {
+	if (!_x_constrained && need_snap) {
 		_editor->snap_to_with_modifier (cx_frames, event);
 	}
 
@@ -4158,13 +4251,14 @@ ControlPointDrag::motion (GdkEvent* event, bool first_motion)
 	float const fraction = 1.0 - (cy / _point->line().height());
 
 	if (first_motion) {
+		float const initial_fraction = 1.0 - (_fixed_grab_y / _point->line().height());
 		_editor->begin_reversible_command (_("automation event move"));
-		_point->line().start_drag_single (_point, _fixed_grab_x, fraction);
+		_point->line().start_drag_single (_point, _fixed_grab_x, initial_fraction);
 	}
+	pair<double, float> result;
+	result = _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
 
-	_point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
-
-	show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
+	show_verbose_cursor_text (_point->line().get_verbose_cursor_string (result.second));
 }
 
 void
@@ -4178,7 +4272,6 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred)
 		}
 
 	} else {
-		motion (event, false);
 		_point->line().end_drag (_pushing, _final_index);
 		_editor->commit_reversible_command ();
 	}
@@ -4205,6 +4298,8 @@ ControlPointDrag::active (Editing::MouseMode m)
 LineDrag::LineDrag (Editor* e, ArdourCanvas::Item* i)
 	: Drag (e, i)
 	, _line (0)
+	, _fixed_grab_x (0.0)
+	, _fixed_grab_y (0.0)
 	, _cumulative_y_drag (0)
 	, _before (0)
 	, _after (0)
@@ -4224,12 +4319,12 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 	   origin, and ditto for y.
 	*/
 
-	double cx = event->button.x;
-	double cy = event->button.y;
+	double mx = event->button.x;
+	double my = event->button.y;
 
-	_line->parent_group().canvas_to_item (cx, cy);
+	_line->grab_item().canvas_to_item (mx, my);
 
-	framecnt_t const frame_within_region = (framecnt_t) floor (cx * _editor->samples_per_pixel);
+	framecnt_t const frame_within_region = (framecnt_t) floor (mx * _editor->samples_per_pixel);
 
 	if (!_line->control_points_adjacent (frame_within_region, _before, _after)) {
 		/* no adjacent points */
@@ -4238,9 +4333,14 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
 
 	Drag::start_grab (event, _editor->cursors()->fader);
 
-	/* store grab start in parent frame */
+	/* store grab start in item frame */
+	double const bx = _line->nth (_before)->get_x();
+	double const ax = _line->nth (_after)->get_x();
+	double const click_ratio = (ax - mx) / (ax - bx);
+
+	double const cy = ((_line->nth (_before)->get_y() * click_ratio) + (_line->nth (_after)->get_y() * (1 - click_ratio)));
 
-	_fixed_grab_x = cx;
+	_fixed_grab_x = mx;
 	_fixed_grab_y = cy;
 
 	double fraction = 1.0 - (cy / _line->height());
@@ -4253,7 +4353,7 @@ LineDrag::motion (GdkEvent* event, bool first_move)
 {
 	double dy = current_pointer_y() - last_pointer_y();
 
-	if (event->button.state & ArdourKeyboard::fine_adjust_modifier ()) {
+	if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::fine_adjust_modifier ())) {
 		dy *= 0.1;
 	}
 
@@ -4268,14 +4368,17 @@ LineDrag::motion (GdkEvent* event, bool first_move)
 	uint32_t ignored;
 
 	if (first_move) {
+		float const initial_fraction = 1.0 - (_fixed_grab_y / _line->height());
+
 		_editor->begin_reversible_command (_("automation range move"));
-		_line->start_drag_line (_before, _after, fraction);
+		_line->start_drag_line (_before, _after, initial_fraction);
 	}
 
 	/* we are ignoring x position for this drag, so we can just pass in anything */
-	_line->drag_motion (0, fraction, true, false, ignored);
+	pair<double, float> result;
 
-	show_verbose_cursor_text (_line->get_verbose_cursor_string (fraction));
+	result = _line->drag_motion (0, fraction, true, false, ignored);
+	show_verbose_cursor_text (_line->get_verbose_cursor_string (result.second));
 }
 
 void
@@ -4291,14 +4394,19 @@ LineDrag::finished (GdkEvent* event, bool movement_occured)
 		AutomationTimeAxisView* atv;
 
 		if ((atv = dynamic_cast<AutomationTimeAxisView*>(_editor->clicked_axisview)) != 0) {
-			framepos_t where = _editor->canvas_event_sample (event, 0, 0);
+			framepos_t where = grab_frame ();
+
+			double cx = 0;
+			double cy = _fixed_grab_y;
 
-			atv->add_automation_event (event, where, event->button.y, false);
+			_line->grab_item().item_to_canvas (cx, cy);
+
+			atv->add_automation_event (event, where, cy, false);
 		} else if (dynamic_cast<AudioTimeAxisView*>(_editor->clicked_axisview) != 0) {
 			AudioRegionView* arv;
 
 			if ((arv = dynamic_cast<AudioRegionView*>(_editor->clicked_regionview)) != 0) {
-				arv->add_gain_point_event (arv->get_canvas_group (), event, false);
+				arv->add_gain_point_event (&arv->get_gain_line()->grab_item(), event, false);
 			}
 		}
 	}
@@ -4313,7 +4421,11 @@ LineDrag::aborted (bool)
 FeatureLineDrag::FeatureLineDrag (Editor* e, ArdourCanvas::Item* i)
 	: Drag (e, i),
 	  _line (0),
-	  _cumulative_x_drag (0)
+	  _arv (0),
+	  _region_view_grab_x (0.0),
+	  _cumulative_x_drag (0),
+	  _before (0.0),
+	  _max_x (0)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New FeatureLineDrag\n");
 }
@@ -4534,7 +4646,7 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred)
 			/* MIDI track */
 			if (_editor->selection->empty() && _editor->mouse_mode == MouseDraw) {
 				/* nothing selected */
-				add_midi_region (mtv);
+				add_midi_region (mtv, true);
 				do_deselect = false;
 			}
 		}
@@ -4954,7 +5066,7 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
 		if (s) {
 			if (s->get_play_range() && s->transport_rolling()) {
 				s->request_play_range (&_editor->selection->time, true);
-			} else {
+			} else if (!s->config.get_external_sync()) {
 				if (UIConfiguration::instance().get_follow_edits() && !s->transport_rolling()) {
 					if (_operation == SelectionEndTrim)
 						_editor->maybe_locate_with_edit_preroll( _editor->get_selection().time.end_frame());
@@ -5266,6 +5378,7 @@ NoteDrag::NoteDrag (Editor* e, ArdourCanvas::Item* i)
 	: Drag (e, i)
 	, _cumulative_dx (0)
 	, _cumulative_dy (0)
+	, _was_selected (false)
 {
 	DEBUG_TRACE (DEBUG::Drags, "New NoteDrag\n");
 
@@ -5296,11 +5409,9 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
 			if (add) {
 				_region->note_selected (_primary, true);
 			} else {
+				_editor->get_selection().clear_points();
 				_region->unique_select (_primary);
 			}
-
-			_editor->begin_reversible_selection_op(X_("Select Note Press"));
-			_editor->commit_reversible_selection_op();
 		}
 	}
 }
@@ -5343,7 +5454,8 @@ NoteDrag::total_dx (const guint state) const
 
 	frameoffset_t ret;
 	if (snap) {
-		ret =  _region->snap_frame_to_frame (st - rp) + rp - n - snap_delta (state);
+		bool const ensure_snap = _editor->snap_mode () != SnapMagnetic;
+		ret =  _region->snap_frame_to_frame (st - rp, ensure_snap) + rp - n - snap_delta (state);
 	} else {
 		ret = st - n - snap_delta (state);
 	}
@@ -5416,12 +5528,17 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
 				if (add) {
 					_region->note_deselected (_primary);
 					changed = true;
+				} else {
+					_editor->get_selection().clear_points();
+					_region->unique_select (_primary);
+					changed = true;
 				}
 			} else {
 				bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
 				bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
 
 				if (!extend && !add && _region->selection_size() > 1) {
+					_editor->get_selection().clear_points();
 					_region->unique_select (_primary);
 					changed = true;
 				} else if (extend) {
@@ -5429,6 +5546,8 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
 					changed = true;
 				} else {
 					/* it was added during button press */
+					changed = true;
+
 				}
 			}
 
@@ -5557,108 +5676,123 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
 			}
 		}
 
-	} else {
+	}
 
-		for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
+	if (_nothing_to_drag) {
+		return;
+	}
+}
 
-			framecnt_t const half = (i->start + i->end) / 2;
+void
+AutomationRangeDrag::motion (GdkEvent*, bool first_move)
+{
+	if (_nothing_to_drag && !first_move) {
+		return;
+	}
 
-			/* find the line that this audio range starts in */
-			list<Line>::iterator j = _lines.begin();
-			while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
-				++j;
-			}
+	if (first_move) {
+		_editor->begin_reversible_command (_("automation range move"));
+
+		if (!_ranges.empty()) {
+
+			for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
 
-			if (j != _lines.end()) {
-				boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
+				framecnt_t const half = (i->start + i->end) / 2;
+
+				/* find the line that this audio range starts in */
+				list<Line>::iterator j = _lines.begin();
+				while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
+					++j;
+				}
+
+				if (j != _lines.end()) {
+					boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
 
 				/* j is the line that this audio range starts in; fade into it;
 				   64 samples length plucked out of thin air.
 				*/
 
-				framepos_t a = i->start + 64;
-				if (a > half) {
-					a = half;
-				}
+					framepos_t a = i->start + 64;
+					if (a > half) {
+						a = half;
+					}
 
-				double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ());
-				double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ());
+					double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ());
+					double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ());
 
-				the_list->editor_add (p, value (the_list, p), false);
-				the_list->editor_add (q, value (the_list, q), false);
-			}
+					XMLNode &before = the_list->get_state();
+					bool const add_p = the_list->editor_add (p, value (the_list, p), false);
+					bool const add_q = the_list->editor_add (q, value (the_list, q), false);
 
-			/* same thing for the end */
+					if (add_p || add_q) {
+						_editor->session()->add_command (
+							new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state()));
+					}
+				}
 
-			j = _lines.begin();
-			while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
-				++j;
-			}
+				/* same thing for the end */
 
-			if (j != _lines.end()) {
-				boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
+				j = _lines.begin();
+				while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
+					++j;
+				}
 
-				/* j is the line that this audio range starts in; fade out of it;
-				   64 samples length plucked out of thin air.
-				*/
+				if (j != _lines.end()) {
+					boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
 
-				framepos_t b = i->end - 64;
-				if (b < half) {
-					b = half;
-				}
+					/* j is the line that this audio range starts in; fade out of it;
+					   64 samples length plucked out of thin air.
+					*/
 
-				double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ());
-				double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ());
+					framepos_t b = i->end - 64;
+					if (b < half) {
+						b = half;
+					}
+
+					double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ());
+					double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ());
+
+					XMLNode &before = the_list->get_state();
+					bool const add_p = the_list->editor_add (p, value (the_list, p), false);
+					bool const add_q = the_list->editor_add (q, value (the_list, q), false);
 
-				the_list->editor_add (p, value (the_list, p), false);
-				the_list->editor_add (q, value (the_list, q), false);
+					if (add_p || add_q) {
+						_editor->session()->add_command (
+							new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state()));
+					}
+				}
 			}
-		}
 
-		_nothing_to_drag = true;
+			_nothing_to_drag = true;
 
-		/* Find all the points that should be dragged and put them in the relevant
-		   points lists in the Line structs.
-		*/
+			/* Find all the points that should be dragged and put them in the relevant
+			   points lists in the Line structs.
+			*/
 
-		for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
+			for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
 
-			uint32_t const N = i->line->npoints ();
-			for (uint32_t j = 0; j < N; ++j) {
+				uint32_t const N = i->line->npoints ();
+				for (uint32_t j = 0; j < N; ++j) {
 
-				/* here's a control point on this line */
-				ControlPoint* p = i->line->nth (j);
-				double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b ();
+					/* here's a control point on this line */
+					ControlPoint* p = i->line->nth (j);
+					double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b ();
 
-				/* see if it's inside a range */
-				list<AudioRange>::const_iterator k = _ranges.begin ();
-				while (k != _ranges.end() && (k->start >= w || k->end <= w)) {
-					++k;
-				}
+					/* see if it's inside a range */
+					list<AudioRange>::const_iterator k = _ranges.begin ();
+					while (k != _ranges.end() && (k->start >= w || k->end <= w)) {
+						++k;
+					}
 
-				if (k != _ranges.end()) {
-					/* dragging this point */
-					_nothing_to_drag = false;
-					i->points.push_back (p);
+					if (k != _ranges.end()) {
+						/* dragging this point */
+						_nothing_to_drag = false;
+						i->points.push_back (p);
+					}
 				}
 			}
 		}
-	}
-
-	if (_nothing_to_drag) {
-		return;
-	}
-}
 
-void
-AutomationRangeDrag::motion (GdkEvent*, bool first_move)
-{
-	if (_nothing_to_drag) {
-		return;
-	}
-
-	if (first_move) {
-		_editor->begin_reversible_command (_("automation range move"));
 		for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
 			i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state);
 		}
@@ -5667,9 +5801,10 @@ AutomationRangeDrag::motion (GdkEvent*, bool first_move)
 	for (list<Line>::iterator l = _lines.begin(); l != _lines.end(); ++l) {
 		float const f = y_fraction (l->line, current_pointer_y());
 		/* we are ignoring x position for this drag, so we can just pass in anything */
+		pair<double, float> result;
 		uint32_t ignored;
-		l->line->drag_motion (0, f, true, false, ignored);
-		show_verbose_cursor_text (l->line->get_verbose_cursor_relative_string (l->original_fraction, f));
+		result = l->line->drag_motion (0, f, true, false, ignored);
+		show_verbose_cursor_text (l->line->get_verbose_cursor_relative_string (l->original_fraction, result.second));
 	}
 }
 
diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h
index 2d4ad30..cd1b0c2 100644
--- a/gtk2_ardour/editor_drag.h
+++ b/gtk2_ardour/editor_drag.h
@@ -246,7 +246,7 @@ protected:
 	/* sets snap delta from unsnapped pos */
 	void setup_snap_delta (framepos_t pos);
 
-	boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*);
+	boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit);
 
 	void show_verbose_cursor_time (framepos_t);
 	void show_verbose_cursor_duration (framepos_t, framepos_t, double xoffset = 0);
@@ -533,6 +533,7 @@ private:
 	MidiRegionView*     region;
 	bool                relative;
 	bool                at_front;
+	bool                _was_selected;
 	double              _snap_delta;
 };
 
@@ -556,7 +557,7 @@ class NoteDrag : public Drag
 	NoteBase* _primary;
 	double _cumulative_dx;
 	double _cumulative_dy;
-	bool _was_selected;
+	bool   _was_selected;
 	double _note_height;
 };
 
@@ -824,7 +825,7 @@ private:
 	void update_item (ARDOUR::Location *);
 
 	ArdourMarker* _marker; ///< marker being dragged
-
+	bool _selection_changed;
         struct CopiedLocationMarkerInfo {
 	    ARDOUR::Location* location;
 	    std::vector<ArdourMarker*> markers;
diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc
index 57baf2c..2bd607f 100644
--- a/gtk2_ardour/editor_export_audio.cc
+++ b/gtk2_ardour/editor_export_audio.cc
@@ -51,6 +51,7 @@
 #include "public_editor.h"
 #include "selection.h"
 #include "time_axis_view.h"
+#include "utils.h"
 
 #include "i18n.h"
 
@@ -103,6 +104,32 @@ Editor::export_range ()
 	}
 }
 
+bool
+Editor::process_midi_export_dialog (MidiExportDialog& dialog, boost::shared_ptr<MidiRegion> midi_region)
+{
+	string path = dialog.get_path ();
+
+	if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
+		bool overwrite = ARDOUR_UI_UTILS::overwrite_file_dialog (dialog,
+									 _("Confirm MIDI File Overwrite"),
+									 _("A file with the same name already exists. Do you want to overwrite it?"));
+
+		if (!overwrite) {
+			return false;
+		}
+
+		/* force ::g_unlink because the backend code will
+		   go wrong if it tries to open an existing
+		   file for writing.
+		*/
+		::g_unlink (path.c_str());
+	}
+
+	(void) midi_region->clone (path);
+
+	return true;
+}
+
 /** Export the first selected region */
 void
 Editor::export_region ()
@@ -128,51 +155,18 @@ Editor::export_region ()
 
 		MidiExportDialog dialog (*this, midi_region);
 		dialog.set_session (_session);
-		int ret = dialog.run ();
-		switch (ret) {
-		case Gtk::RESPONSE_ACCEPT:
-			break;
-		default:
-			return;
-		}
-
-		dialog.hide ();
-
-		string path = dialog.get_path ();
-
-		if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
-
-			MessageDialog checker (_("File Exists!"),
-					       true,
-					       Gtk::MESSAGE_WARNING,
-					       Gtk::BUTTONS_NONE);
-
-			checker.set_title (_("File Exists!"));
 
-			checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
-			checker.add_button (_("Overwrite Existing File"), RESPONSE_ACCEPT);
-			checker.set_default_response (RESPONSE_CANCEL);
-
-			checker.set_wmclass (X_("midi_export_file_exists"), PROGRAM_NAME);
-			checker.set_position (Gtk::WIN_POS_MOUSE);
-
-			ret = checker.run ();
-
-			switch (ret) {
+		bool finished = false;
+		while (!finished) {
+			switch (dialog.run ()) {
 			case Gtk::RESPONSE_ACCEPT:
-				/* force ::g_unlink because the backend code will
-				   go wrong if it tries to open an existing
-				   file for writing.
-				*/
-				::g_unlink (path.c_str());
+				finished = process_midi_export_dialog (dialog, midi_region);
 				break;
 			default:
+				finished = true;
 				return;
 			}
-
 		}
-
-		(void) midi_region->clone (path);
 	}
 }
 
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 094afc2..7740cb9 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -399,8 +399,9 @@ Editor::step_mouse_mode (bool next)
 }
 
 void
-Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemType item_type)
+Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
 {
+
  	/* in object/audition/timefx/gain-automation mode,
 	   any button press sets the selection if the object
 	   can be selected. this is a bit of hack, because
@@ -457,7 +458,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
 
 			/* almost no selection action on modified button-2 or button-3 events */
 
-			if (item_type != RegionItem && event->button.button != 2) {
+			if ((item_type != RegionItem && event->button.button != 2)
+			    /* for selection of control points prior to delete (shift-right click) */
+			    && !(item_type == ControlPointItem && event->button.button == 3 && event->type == GDK_BUTTON_PRESS)) {
 				return;
 			}
 		}
@@ -472,6 +475,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
 
 	switch (item_type) {
 	case RegionItem:
+		if (eff_mouse_mode == MouseDraw) {
+			break;
+		}
 		if (press) {
 			if (eff_mouse_mode != MouseRange) {
 				_mouse_changed_selection = set_selected_regionview_from_click (press, op);
@@ -515,7 +521,94 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
 		/* for object/track exclusivity, we don't call set_selected_track_as_side_effect (op); */
 
 		if (eff_mouse_mode != MouseRange) {
-			_mouse_changed_selection |= set_selected_control_point_from_click (press, op);
+			if (event->button.button != 3) {
+				_mouse_changed_selection |= set_selected_control_point_from_click (press, op);
+			} else {
+				_mouse_changed_selection |= set_selected_control_point_from_click (press, Selection::Set);
+			}
+		}
+		break;
+
+	case GainLineItem:
+		if (eff_mouse_mode != MouseRange) {
+			AutomationLine* argl = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
+
+			std::list<Selectable*> selectables;
+			uint32_t before, after;
+			framecnt_t const  where = (framecnt_t) floor (event->button.x * samples_per_pixel) - clicked_regionview->region ()->position ();
+
+			if (!argl || !argl->control_points_adjacent (where, before, after)) {
+				break;
+			}
+
+			selectables.push_back (argl->nth (before));
+			selectables.push_back (argl->nth (after));
+
+			switch (op) {
+			case Selection::Set:
+				if (press) {
+					selection->set (selectables);
+					_mouse_changed_selection = true;
+				}
+				break;
+			case Selection::Add:
+				if (press) {
+					selection->add (selectables);
+					_mouse_changed_selection = true;
+				}
+				break;
+			case Selection::Toggle:
+				if (press) {
+					selection->toggle (selectables);
+					_mouse_changed_selection = true;
+				}
+				break;
+
+			case Selection::Extend:
+				/* XXX */
+				break;
+			}
+		}
+		break;
+
+	case AutomationLineItem:
+		if (eff_mouse_mode != MouseRange) {
+			AutomationLine* al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
+			std::list<Selectable*> selectables;
+			uint32_t before, after;
+			framecnt_t const  where = (framecnt_t) floor (event->button.x * samples_per_pixel);
+
+			if (!al || !al->control_points_adjacent (where, before, after)) {
+				break;
+			}
+
+			selectables.push_back (al->nth (before));
+			selectables.push_back (al->nth (after));
+
+			switch (op) {
+			case Selection::Set:
+				if (press) {
+					selection->set (selectables);
+					_mouse_changed_selection = true;
+				}
+				break;
+			case Selection::Add:
+				if (press) {
+					selection->add (selectables);
+					_mouse_changed_selection = true;
+				}
+				break;
+			case Selection::Toggle:
+				if (press) {
+					selection->toggle (selectables);
+					_mouse_changed_selection = true;
+				}
+				break;
+
+			case Selection::Extend:
+				/* XXX */
+				break;
+			}
 		}
 		break;
 
@@ -532,7 +625,23 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
 		break;
 
 	case AutomationTrackItem:
-		set_selected_track_as_side_effect (op);
+		if (eff_mouse_mode != MouseDraw && op == Selection::Set) {
+			set_selected_track_as_side_effect (op);
+		}
+		break;
+
+	case NoteItem:
+		if (press && event->button.button == 3) {
+			NoteBase* cnote = reinterpret_cast<NoteBase*> (item->get_data ("notebase"));
+			assert (cnote);
+			if (cnote->region_view().selection_size() == 0 || !cnote->selected()) {
+				selection->clear_points();
+				cnote->region_view().unique_select (cnote);
+				/* we won't get the release, so store the selection change now */
+				begin_reversible_selection_op (X_("Button 3 Note Selection"));
+				commit_reversible_selection_op ();
+			}
+		}
 		break;
 
 	default:
@@ -1138,7 +1247,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
 	}
 
 	//not rolling, range mode click + join_play_range :  locate the PH here
-	if ( !_drags->active () && _session && !_session->transport_rolling() && ( effective_mouse_mode() == MouseRange ) && UIConfiguration::instance().get_follow_edits() ) {
+	if ( !_drags->active () && _session && !_session->transport_rolling() && ( effective_mouse_mode() == MouseRange ) && UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync() ) {
 		framepos_t where = canvas_event_sample (event);
 		snap_to(where);
 		_session->request_locate (where, false);
@@ -1590,7 +1699,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 
 	switch (item_type) {
 	case ControlPointItem:
-		if (mouse_mode == MouseDraw || mouse_mode == MouseObject) {
+		if (mouse_mode == MouseDraw || mouse_mode == MouseObject || mouse_mode == MouseContent) {
 			cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
 			cp->show ();
 
@@ -2099,7 +2208,7 @@ Editor::point_trim (GdkEvent* event, framepos_t new_bound)
 
 		break;
 	case 2:
-		begin_reversible_command (_("End point trim"));
+		begin_reversible_command (_("end point trim"));
 
 		if (selection->selected (rv)) {
 
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 4e744ab..cb67f1f 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -57,6 +57,7 @@
 #include "ardour/session_playlists.h"
 #include "ardour/strip_silence.h"
 #include "ardour/transient_detector.h"
+#include "ardour/transpose.h"
 
 #include "canvas/canvas.h"
 
@@ -95,6 +96,7 @@
 #include "streamview.h"
 #include "strip_silence_dialog.h"
 #include "time_axis_view.h"
+#include "timers.h"
 #include "transpose_dialog.h"
 #include "transform_dialog.h"
 #include "ui_config.h"
@@ -2530,14 +2532,14 @@ Editor::play_selection ()
 framepos_t
 Editor::get_preroll ()
 {
-	return 1.0 /*Config->get_edit_preroll_seconds()*/ * _session->frame_rate();
+	return Config->get_preroll_seconds() * _session->frame_rate();
 }
 
 
 void
 Editor::maybe_locate_with_edit_preroll ( framepos_t location )
 {
-	if ( _session->transport_rolling() || !UIConfiguration::instance().get_follow_edits() || _ignore_follow_edits )
+	if ( _session->transport_rolling() || !UIConfiguration::instance().get_follow_edits() || _ignore_follow_edits || _session->config.get_external_sync() )
 		return;
 
 	location -= get_preroll();
@@ -3254,41 +3256,48 @@ Editor::crop_region_to (framepos_t start, framepos_t end)
 		return;
 	}
 
-	framepos_t the_start;
-	framepos_t the_end;
-	framepos_t cnt;
+	framepos_t pos;
+	framepos_t new_start;
+	framepos_t new_end;
+	framecnt_t new_length;
 	bool in_command = false;
 
 	for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
 
-		boost::shared_ptr<Region> region;
+		/* Only the top regions at start and end have to be cropped */
+		boost::shared_ptr<Region> region_at_start = (*i)->top_region_at(start);
+		boost::shared_ptr<Region> region_at_end = (*i)->top_region_at(end);
 
-		the_start = start;
+		vector<boost::shared_ptr<Region> > regions;
 
-		if ((region = (*i)->top_region_at(the_start)) == 0) {
-			continue;
+		if (region_at_start != 0) {
+			regions.push_back (region_at_start);
+		}
+		if (region_at_end != 0) {
+			regions.push_back (region_at_end);
 		}
 
-		/* now adjust lengths to that we do the right thing
-		   if the selection extends beyond the region
-		*/
+		/* now adjust lengths */
+		for (vector<boost::shared_ptr<Region> >::iterator i = regions.begin(); i != regions.end(); ++i) {
 
-		the_start = max (the_start, (framepos_t) region->position());
-		if (max_framepos - the_start < region->length()) {
-			the_end = the_start + region->length() - 1;
-		} else {
-			the_end = max_framepos;
-		}
-		the_end = min (end, the_end);
-		cnt = the_end - the_start + 1;
+			pos = (*i)->position();
+			new_start = max (start, pos);
+			if (max_framepos - pos > (*i)->length()) {
+				new_end = pos + (*i)->length() - 1;
+			} else {
+				new_end = max_framepos;
+			}
+			new_end = min (end, new_end);
+			new_length = new_end - new_start + 1;
 
-		if(!in_command) {
-			begin_reversible_command (_("trim to selection"));
-			in_command = true;
+			if(!in_command) {
+				begin_reversible_command (_("trim to selection"));
+				in_command = true;
+			}
+			(*i)->clear_changes ();
+			(*i)->trim_to (new_start, new_length);
+			_session->add_command (new StatefulDiffCommand (*i));
 		}
-		region->clear_changes ();
-		region->trim_to (the_start, cnt);
-		_session->add_command (new StatefulDiffCommand (region));
 	}
 
 	if (in_command) {
@@ -3299,117 +3308,49 @@ Editor::crop_region_to (framepos_t start, framepos_t end)
 void
 Editor::region_fill_track ()
 {
-	RegionSelection rs = get_regions_from_selection_and_entered ();
-
-	if (!_session || rs.empty()) {
-		return;
-	}
+	boost::shared_ptr<Playlist> playlist;
+	RegionSelection regions = get_regions_from_selection_and_entered ();
+	RegionSelection foo;
 
 	framepos_t const end = _session->current_end_frame ();
-	RegionSelection foo;
-	bool in_command = false;
 
-	for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+	if (regions.empty () || regions.end_frame () + 1 >= end) {
+		return;
+	}
 
-		boost::shared_ptr<Region> region ((*i)->region());
+	framepos_t const start_frame = regions.start ();
+	framepos_t const end_frame = regions.end_frame ();
+	framecnt_t const gap = end_frame - start_frame + 1;
 
-		boost::shared_ptr<Playlist> pl = region->playlist();
+	begin_reversible_command (Operations::region_fill);
 
-		if (end <= region->last_frame()) {
-			continue;
-		}
+	selection->clear_regions ();
 
-		double times = (double) (end - region->last_frame()) / (double) region->length();
+	for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
 
-		if (times == 0) {
-			continue;
-		}
+		boost::shared_ptr<Region> r ((*i)->region());
 
-		if (!in_command) {
-			begin_reversible_command (Operations::region_fill);
-			in_command = true;
-		}
 		TimeAxisView& tv = (*i)->get_time_axis_view();
 		RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&tv);
 		latest_regionviews.clear ();
 		sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view));
 
-		pl->clear_changes ();
-		pl->add_region (RegionFactory::create (region, true), region->last_frame(), times);
-		_session->add_command (new StatefulDiffCommand (pl));
+		framepos_t const position = end_frame + (r->first_frame() - start_frame + 1);
+ 		playlist = (*i)->region()->playlist();
+		playlist->clear_changes ();
+		playlist->duplicate_until (r, position, gap, end);
+		_session->add_command(new StatefulDiffCommand (playlist));
 
 		c.disconnect ();
 
 		foo.insert (foo.end(), latest_regionviews.begin(), latest_regionviews.end());
 	}
 
-	if (in_command) {
-		if (!foo.empty()) {
-			selection->set (foo);
-		}
-		commit_reversible_command ();
-	}
-}
-
-void
-Editor::region_fill_selection ()
-{
-	if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) {
-		return;
-	}
-
-	if (selection->time.empty()) {
-		return;
-	}
-
-	boost::shared_ptr<Region> region = _regions->get_single_selection ();
-	if (region == 0) {
-		return;
-	}
-
-	framepos_t start = selection->time[clicked_selection].start;
-	framepos_t end = selection->time[clicked_selection].end;
-
-	boost::shared_ptr<Playlist> playlist;
-
-	if (selection->tracks.empty()) {
-		return;
-	}
-
-	framepos_t selection_length = end - start;
-	float times = (float)selection_length / region->length();
-	bool in_command = false;
-
-	TrackViewList ts = selection->tracks.filter_to_unique_playlists ();
-	RegionSelection foo;
-
-	for (TrackViewList::iterator i = ts.begin(); i != ts.end(); ++i) {
-
-		if ((playlist = (*i)->playlist()) == 0) {
-			continue;
-		}
-
-		if (!in_command) {
-			begin_reversible_command (Operations::fill_selection);
-			in_command = true;
-		}
-		RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
-		latest_regionviews.clear ();
-		sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view));
-
-		playlist->clear_changes ();
-		playlist->add_region (RegionFactory::create (region, true), start, times);
-		_session->add_command (new StatefulDiffCommand (playlist));
-		c.disconnect ();
-		foo.insert (foo.end(), latest_regionviews.begin(), latest_regionviews.end());
+	if (!foo.empty()) {
+		selection->set (foo);
 	}
 
-	if (in_command) {
-		if (!foo.empty()) {
-			selection->set (foo);
-		}
-		commit_reversible_command ();
-	}
+	commit_reversible_command ();
 }
 
 void
@@ -4099,6 +4040,7 @@ Editor::cut_copy (CutCopyOp op)
 		Location* loc = find_location_from_marker (entered_marker, ignored);
 
 		if (_session && loc) {
+			entered_marker = NULL;
 			Glib::signal_idle().connect (sigc::bind (sigc::mem_fun(*this, &Editor::really_remove_marker), loc));
 		}
 
@@ -4773,7 +4715,7 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
 
 	framepos_t const start_frame = regions.start ();
 	framepos_t const end_frame = regions.end_frame ();
-	framecnt_t const gap = end_frame - start_frame;
+	framecnt_t const gap = end_frame - start_frame + 1;
 
 	begin_reversible_command (Operations::duplicate_region);
 
@@ -4788,7 +4730,7 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
 		latest_regionviews.clear ();
 		sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view));
 
-		framepos_t const position = end_frame + (r->first_frame() - start_frame);
+		framepos_t const position = end_frame + (r->first_frame() - start_frame + 1);
  		playlist = (*i)->region()->playlist();
 		playlist->clear_changes ();
 		playlist->duplicate (r, position, gap, times);
@@ -4839,7 +4781,7 @@ Editor::duplicate_selection (float times)
 		} else {
 			end = selection->time.end_frame();
 		}
-		playlist->duplicate (*ri, end, times);
+		playlist->duplicate (*ri, end + 1, times);
 
 		if (!in_command) {
 			begin_reversible_command (_("duplicate selection"));
@@ -5341,19 +5283,43 @@ Editor::transform_regions (const RegionSelection& rs)
 		return;
 	}
 
-	TransformDialog* td = new TransformDialog();
+	TransformDialog td;
 
-	td->present();
-	const int r = td->run();
-	td->hide();
+	td.present();
+	const int r = td.run();
+	td.hide();
 
 	if (r == Gtk::RESPONSE_OK) {
-		Transform transform(td->get());
+		Transform transform(td.get());
 		apply_midi_note_edit_op(transform, rs);
 	}
 }
 
 void
+Editor::transpose_region ()
+{
+	if (_session) {
+		transpose_regions(get_regions_from_selection_and_entered ());
+	}
+}
+
+void
+Editor::transpose_regions (const RegionSelection& rs)
+{
+	if (rs.n_midi_regions() == 0) {
+		return;
+	}
+
+	TransposeDialog d;
+	int const r = d.run ();
+
+	if (r == RESPONSE_ACCEPT) {
+		Transpose transpose(d.semitones ());
+		apply_midi_note_edit_op (transpose, rs);
+	}
+}
+
+void
 Editor::insert_patch_change (bool from_context)
 {
 	RegionSelection rs = get_regions_from_selection_and_entered ();
@@ -6097,7 +6063,7 @@ Editor::set_playhead_cursor ()
 		}
 	}
 
-	if (UIConfiguration::instance().get_follow_edits()) {
+	if (UIConfiguration::instance().get_follow_edits() && (!_session || !_session->config.get_external_sync())) {
 		cancel_time_selection();
 	}
 }
@@ -6426,30 +6392,6 @@ Editor::pitch_shift_region ()
 }
 
 void
-Editor::transpose_region ()
-{
-	RegionSelection rs = get_regions_from_selection_and_entered ();
-
-	list<MidiRegionView*> midi_region_views;
-	for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
-		MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (*i);
-		if (mrv) {
-			midi_region_views.push_back (mrv);
-		}
-	}
-
-	TransposeDialog d;
-	int const r = d.run ();
-	if (r != RESPONSE_ACCEPT) {
-		return;
-	}
-
-	for (list<MidiRegionView*>::iterator i = midi_region_views.begin(); i != midi_region_views.end(); ++i) {
-		(*i)->midi_region()->transpose (d.semitones ());
-	}
-}
-
-void
 Editor::set_tempo_from_region ()
 {
 	RegionSelection rs = get_regions_from_selection_and_entered ();
@@ -7886,6 +7828,7 @@ Editor::bring_in_callback (Gtk::Label* label, uint32_t n, uint32_t total, string
 void
 Editor::update_bring_in_message (Gtk::Label* label, uint32_t n, uint32_t total, string name)
 {
+	Timers::TimerSuspender t;
 	label->set_text (string_compose ("Copying %1, %2 of %3", name, n, total));
 	Gtkmm2ext::UI::instance()->flush_pending ();
 }
@@ -7906,6 +7849,7 @@ Editor::bring_all_sources_into_session ()
 	 * files
 	 */
 
+	Timers::TimerSuspender t;
 	Gtkmm2ext::UI::instance()->flush_pending ();
 
 	cerr << " Do it\n";
diff --git a/gtk2_ardour/editor_regions.cc b/gtk2_ardour/editor_regions.cc
index 0968c40..d23648a 100644
--- a/gtk2_ardour/editor_regions.cc
+++ b/gtk2_ardour/editor_regions.cc
@@ -188,6 +188,7 @@ EditorRegions::EditorRegions (Editor* e)
 
 	_display.get_selection()->set_mode (SELECTION_MULTIPLE);
 	_display.add_object_drag (_columns.region.index(), "regions");
+	_display.set_drag_column (_columns.name.index());
 
 	/* setup DnD handling */
 
diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc
index a10f523..588b900 100644
--- a/gtk2_ardour/editor_routes.cc
+++ b/gtk2_ardour/editor_routes.cc
@@ -490,7 +490,7 @@ EditorRoutes::build_menu ()
 	items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
 	items.push_back (MenuElem (_("Show All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_miditracks)));
 	items.push_back (MenuElem (_("Hide All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_miditracks)));
-	items.push_back (MenuElem (_("Only Show Tracks With Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
+	items.push_back (MenuElem (_("Only Show Tracks with Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
 }
 
 void
diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc
index ccd0399..ae646a5 100644
--- a/gtk2_ardour/editor_rulers.cc
+++ b/gtk2_ardour/editor_rulers.cc
@@ -212,15 +212,14 @@ Editor::popup_ruler_menu (framepos_t where, ItemType t)
 		ruler_items.push_back (MenuElem (_("New location marker"), sigc::bind ( sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, false)));
 		ruler_items.push_back (MenuElem (_("Clear all locations"), sigc::mem_fun(*this, &Editor::clear_markers)));
 		ruler_items.push_back (MenuElem (_("Unhide locations"), sigc::mem_fun(*this, &Editor::unhide_markers)));
-		ruler_items.push_back (SeparatorElem ());
 		break;
+
 	case RangeMarkerBarItem:
 		ruler_items.push_back (MenuElem (_("New range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_range), where)));
 		ruler_items.push_back (MenuElem (_("Clear all ranges"), sigc::mem_fun(*this, &Editor::clear_ranges)));
 		ruler_items.push_back (MenuElem (_("Unhide ranges"), sigc::mem_fun(*this, &Editor::unhide_ranges)));
-		ruler_items.push_back (SeparatorElem ());
-
 		break;
+
 	case TransportMarkerBarItem:
 		ruler_items.push_back (MenuElem (_("New Loop range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_loop), where)));
 		ruler_items.push_back (MenuElem (_("New Punch range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_punch), where)));
@@ -231,7 +230,6 @@ Editor::popup_ruler_menu (framepos_t where, ItemType t)
 		ruler_items.push_back (MenuElem (_("New CD track marker"), sigc::bind ( sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, true)));
 		break;
 
-
 	case TempoBarItem:
 		ruler_items.push_back (MenuElem (_("New Tempo"), sigc::bind ( sigc::mem_fun(*this, &Editor::mouse_add_new_tempo_event), where)));
 		break;
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 85ec795..afddfad 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -192,17 +192,10 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
 		group = clicked_routeview->route()->route_group();
 	}
 
-	bool had_tracks = !selection->tracks.empty();
-	RouteGroup& arg (_session->all_route_group());
-
 	switch (op) {
 	case Selection::Toggle:
 		if (selection->selected (clicked_axisview)) {
-			if (arg.is_select() && arg.is_active()) {
-				for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-					selection->remove(*i);
-				}
-			} else if (group && group->is_active()) {
+			if (group && group->is_active()) {
 				for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
 					if ((*i)->route_group() == group) {
 						selection->remove(*i);
@@ -212,11 +205,7 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
 				selection->remove (clicked_axisview);
 			}
 		} else {
-			if (arg.is_select() && arg.is_active()) {
-				for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-					selection->add(*i);
-				}
-			} else if (group && group->is_active()) {
+			if (group && group->is_active()) {
 				for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
 					if ((*i)->route_group() == group) {
 						selection->add(*i);
@@ -229,14 +218,7 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
 		break;
 
 	case Selection::Add:
-		if (!had_tracks && arg.is_select() && arg.is_active()) {
-			/* nothing was selected already, and all group is active etc. so use
-			   all tracks.
-			*/
-			for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-				selection->add(*i);
-			}
-		} else if (group && group->is_active()) {
+		if (group && group->is_active()) {
 			for (TrackViewList::iterator i  = track_views.begin(); i != track_views.end (); ++i) {
 				if ((*i)->route_group() == group) {
 					selection->add(*i);
@@ -249,14 +231,7 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
 
 	case Selection::Set:
 		selection->clear();
-		if (!had_tracks && arg.is_select() && arg.is_active()) {
-			/* nothing was selected already, and all group is active etc. so use
-			   all tracks.
-			*/
-			for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-				selection->add(*i);
-			}
-		} else if (group && group->is_active()) {
+		if (group && group->is_active()) {
 			for (TrackViewList::iterator i  = track_views.begin(); i != track_views.end (); ++i) {
 				if ((*i)->route_group() == group) {
 					selection->add(*i);
@@ -327,15 +302,27 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation
 	if (!clicked_control_point) {
 		return false;
 	}
+
 	bool ret = false;
 
 	switch (op) {
 	case Selection::Set:
-		if (press) {
+		if (!selection->selected (clicked_control_point)) {
 			selection->set (clicked_control_point);
 			ret = true;
+		} else {
+			/* clicked on an already selected point */
+			if (press) {
+				break;
+			} else {
+				if (selection->points.size() > 1) {
+					selection->set (clicked_control_point);
+					ret = true;
+				}
+			}
 		}
 		break;
+
 	case Selection::Add:
 		if (press) {
 			selection->add (clicked_control_point);
@@ -1241,6 +1228,7 @@ Editor::sensitize_the_right_region_actions ()
 		_region_actions->get_action("quantize-region")->set_sensitive (false);
 		_region_actions->get_action("legatize-region")->set_sensitive (false);
 		_region_actions->get_action("remove-overlap")->set_sensitive (false);
+		_region_actions->get_action("transform-region")->set_sensitive (false);
 		_region_actions->get_action("fork-region")->set_sensitive (false);
 		_region_actions->get_action("insert-patch-change-context")->set_sensitive (false);
 		_region_actions->get_action("insert-patch-change")->set_sensitive (false);
diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
index 5e7d4f5..ef19aa8 100644
--- a/gtk2_ardour/engine_dialog.cc
+++ b/gtk2_ardour/engine_dialog.cc
@@ -321,6 +321,8 @@ EngineControl::connect_changed_signals ()
 	    sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
 	buffer_size_combo_connection = buffer_size_combo.signal_changed ().connect (
 	    sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
+	nperiods_combo_connection = nperiods_combo.signal_changed ().connect (
+	    sigc::mem_fun (*this, &EngineControl::nperiods_changed));
 	device_combo_connection = device_combo.signal_changed ().connect (
 	    sigc::mem_fun (*this, &EngineControl::device_changed));
 	midi_option_combo_connection = midi_option_combo.signal_changed ().connect (
@@ -350,6 +352,7 @@ EngineControl::block_changed_signals ()
 		driver_combo_connection.block ();
 		sample_rate_combo_connection.block ();
 		buffer_size_combo_connection.block ();
+		nperiods_combo_connection.block ();
 		device_combo_connection.block ();
 		input_device_combo_connection.block ();
 		output_device_combo_connection.block ();
@@ -370,6 +373,7 @@ EngineControl::unblock_changed_signals ()
 		driver_combo_connection.unblock ();
 		sample_rate_combo_connection.unblock ();
 		buffer_size_combo_connection.unblock ();
+		nperiods_combo_connection.unblock ();
 		device_combo_connection.unblock ();
 		input_device_combo_connection.unblock ();
 		output_device_combo_connection.unblock ();
@@ -421,9 +425,9 @@ EngineControl::start_engine ()
 }
 
 bool
-EngineControl::stop_engine ()
+EngineControl::stop_engine (bool for_latency)
 {
-	if (ARDOUR::AudioEngine::instance()->stop()) {
+	if (ARDOUR::AudioEngine::instance()->stop(for_latency)) {
 		MessageDialog msg(*this,
 		                  ARDOUR::AudioEngine::instance()->get_last_backend_error());
 		msg.run();
@@ -572,9 +576,18 @@ EngineControl::build_full_control_notebook ()
 	buffer_size_duration_label.set_alignment (0.0); /* left-align */
 	basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
 
-	/* button spans 2 rows */
+	int ctrl_btn_span = 1;
+	if (backend->can_set_period_size ()) {
+		row++;
+		label = manage (left_aligned_label (_("Periods:")));
+		basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
+		basic_packer.attach (nperiods_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
+		++ctrl_btn_span;
+	}
+
+	/* button spans 2 or 3 rows */
 
-	basic_packer.attach (control_app_button, 3, 4, row-1, row+1, xopt, xopt);
+	basic_packer.attach (control_app_button, 3, 4, row - ctrl_btn_span, row + 1, xopt, xopt);
 	row++;
 
 	input_channels.set_name ("InputChannels");
@@ -831,6 +844,16 @@ EngineControl::update_sensitivity ()
 		valid = false;
 	}
 
+	if (get_popdown_string_count (nperiods_combo) > 0) {
+		if (!ARDOUR::AudioEngine::instance()->running()) {
+			nperiods_combo.set_sensitive (true);
+		} else {
+			nperiods_combo.set_sensitive (false);
+		}
+	} else {
+		nperiods_combo.set_sensitive (false);
+	}
+
 	if (_have_control) {
 		start_stop_button.set_sensitive(true);
 		start_stop_button.show();
@@ -1021,6 +1044,15 @@ EngineControl::backend_changed ()
 		set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
 	}
 
+	if (_have_control && !ignore_changes) {
+		// set driver & devices
+		State state = get_matching_state (backend_combo.get_active_text());
+		if (state) {
+			PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
+			set_current_state (state);
+		}
+	}
+
 	if (!ignore_changes) {
 		maybe_display_saved_state ();
 	}
@@ -1270,6 +1302,8 @@ EngineControl::driver_changed ()
 	backend->set_driver (driver_combo.get_active_text());
 	list_devices ();
 
+	// TODO load LRU device(s) for backend + driver combo
+
 	if (!ignore_changes) {
 		maybe_display_saved_state ();
 	}
@@ -1432,6 +1466,31 @@ EngineControl::set_buffersize_popdown_strings ()
 }
 
 void
+EngineControl::set_nperiods_popdown_strings ()
+{
+	DEBUG_ECONTROL ("set_nperiods_popdown_strings");
+	boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
+	vector<uint32_t> np;
+	vector<string> s;
+
+	if (backend->can_set_period_size()) {
+		np = backend->available_period_sizes (get_driver());
+	}
+
+	for (vector<uint32_t>::const_iterator x = np.begin(); x != np.end(); ++x) {
+		s.push_back (nperiods_as_string (*x));
+	}
+
+	set_popdown_strings (nperiods_combo, s);
+
+	if (!s.empty()) {
+		set_active_text_if_present (nperiods_combo, nperiods_as_string (backend->period_size())); // XXX 
+	}
+
+	update_sensitivity ();
+}
+
+void
 EngineControl::device_changed ()
 {
 	SignalBlocker blocker (*this, "device_changed");
@@ -1479,6 +1538,7 @@ EngineControl::device_changed ()
 
 		set_samplerate_popdown_strings ();
 		set_buffersize_popdown_strings ();
+		set_nperiods_popdown_strings ();
 
 		/* TODO set min + max channel counts here */
 
@@ -1517,6 +1577,15 @@ EngineControl::bufsize_as_string (uint32_t sz)
 	return buf;
 }
 
+string
+EngineControl::nperiods_as_string (uint32_t np)
+{
+	char buf[8];
+	snprintf (buf, sizeof (buf), "%u", np);
+	return buf;
+}
+
+
 void
 EngineControl::sample_rate_changed ()
 {
@@ -1537,6 +1606,13 @@ EngineControl::buffer_size_changed ()
 }
 
 void
+EngineControl::nperiods_changed ()
+{
+	DEBUG_ECONTROL ("nperiods_changed");
+	show_buffer_duration ();
+}
+
+void
 EngineControl::show_buffer_duration ()
 {
 	DEBUG_ECONTROL ("show_buffer_duration");
@@ -1548,17 +1624,12 @@ EngineControl::show_buffer_duration ()
 	uint32_t samples = atoi (bs_text); /* will ignore trailing text */
 	uint32_t rate = get_rate();
 
-	/* Developers: note the hard-coding of a double buffered model
-	   in the (2 * samples) computation of latency. we always start
-	   the audiobackend in this configuration.
-	 */
-	/* note to jack1 developers: ardour also always starts the engine
-	 * in async mode (no jack2 --sync option) which adds an extra cycle
-	 * of latency with jack2 (and *3 would be correct)
-	 * The value can also be wrong if jackd is started externally..
+	/* Except for ALSA and Dummy backends, we don't know the number of periods
+	 * per cycle and settings.
 	 *
-	 * At the time of writing the ALSA backend always uses double-buffering *2,
-	 * The Dummy backend *1, and who knows what ASIO really does :)
+	 * jack1 vs jack2 have different default latencies since jack2 start
+	 * in async-mode unless --sync is given which adds an extra cycle
+	 * of latency. The value is not known if jackd is started externally..
 	 *
 	 * So just display the period size, that's also what
 	 * ARDOUR_UI::update_sample_rate() does for the status bar.
@@ -1616,6 +1687,17 @@ EngineControl::parameter_changed ()
 }
 
 EngineControl::State
+EngineControl::get_matching_state (const string& backend)
+{
+	for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
+		if ((*i)->backend == backend) {
+			return (*i);
+		}
+	}
+	return State();
+}
+
+EngineControl::State
 EngineControl::get_matching_state (
 		const string& backend,
 		const string& driver,
@@ -1684,6 +1766,19 @@ bool EngineControl::equivalent_states (const EngineControl::State& state1,
 	return false;
 }
 
+bool
+EngineControl::state_sort_cmp (const State &a, const State &b) {
+	if (a->active) {
+		return true;
+	}
+	else if (b->active) {
+		return false;
+	}
+	else {
+		return a->lru < b->lru;
+	}
+}
+
 EngineControl::State
 EngineControl::save_state ()
 {
@@ -1692,6 +1787,7 @@ EngineControl::save_state ()
 	if (!_have_control) {
 		state = get_matching_state (backend_combo.get_active_text(), string(), string());
 		if (state) {
+			state->lru = time (NULL) ;
 			return state;
 		}
 		state.reset(new StateStruct);
@@ -1711,6 +1807,8 @@ EngineControl::save_state ()
 
 	states.push_back (state);
 
+	states.sort (state_sort_cmp);
+
 	return state;
 }
 
@@ -1724,12 +1822,14 @@ EngineControl::store_state (State state)
 	state->output_device = get_output_device_name ();
 	state->sample_rate = get_rate ();
 	state->buffer_size = get_buffer_size ();
+	state->n_periods = get_nperiods ();
 	state->input_latency = get_input_latency ();
 	state->output_latency = get_output_latency ();
 	state->input_channels = get_input_channels ();
 	state->output_channels = get_output_channels ();
 	state->midi_option = get_midi_option ();
 	state->midi_devices = _midi_devices;
+	state->lru = time (NULL) ;
 }
 
 void
@@ -1749,6 +1849,8 @@ EngineControl::maybe_display_saved_state ()
 			sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
 		}
 		set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
+
+		set_active_text_if_present (nperiods_combo, nperiods_as_string (state->n_periods));
 		/* call this explicitly because we're ignoring changes to
 		   the controls at this point.
 		 */
@@ -1787,12 +1889,14 @@ EngineControl::get_state ()
 			node->add_property ("output-device", (*i)->output_device);
 			node->add_property ("sample-rate", (*i)->sample_rate);
 			node->add_property ("buffer-size", (*i)->buffer_size);
+			node->add_property ("n-periods", (*i)->n_periods);
 			node->add_property ("input-latency", (*i)->input_latency);
 			node->add_property ("output-latency", (*i)->output_latency);
 			node->add_property ("input-channels", (*i)->input_channels);
 			node->add_property ("output-channels", (*i)->output_channels);
 			node->add_property ("active", (*i)->active ? "yes" : "no");
 			node->add_property ("midi-option", (*i)->midi_option);
+			node->add_property ("lru", (*i)->active ? time (NULL) : (*i)->lru);
 
 			XMLNode* midi_devices = new XMLNode ("MIDIDevices");
 			for (std::vector<MidiDeviceSettings>::const_iterator p = (*i)->midi_devices.begin(); p != (*i)->midi_devices.end(); ++p) {
@@ -1903,6 +2007,13 @@ EngineControl::set_state (const XMLNode& root)
 			}
 			state->buffer_size = atoi (prop->value ());
 
+			if ((prop = grandchild->property ("n-periods")) == 0) {
+				// optional (new value in 4.5)
+				state->n_periods = 0;
+			} else {
+				state->n_periods = atoi (prop->value ());
+			}
+
 			if ((prop = grandchild->property ("input-latency")) == 0) {
 				continue;
 			}
@@ -1956,6 +2067,10 @@ EngineControl::set_state (const XMLNode& root)
 				}
 			}
 
+			if ((prop = grandchild->property ("lru"))) {
+				state->lru = atoi (prop->value ());
+			}
+
 #if 1
 			/* remove accumulated duplicates (due to bug in ealier version)
 			 * this can be removed again before release
@@ -1992,6 +2107,8 @@ EngineControl::set_state (const XMLNode& root)
 		}
 	}
 
+	states.sort (state_sort_cmp);
+
 	for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
 
 		if ((*i)->active) {
@@ -2091,6 +2208,7 @@ EngineControl::set_current_state (const State& state)
 	output_device_combo.set_active_text (state->output_device);
 	sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
 	set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
+	set_active_text_if_present (nperiods_combo, nperiods_as_string (state->n_periods));
 	input_latency.set_value (state->input_latency);
 	output_latency.set_value (state->output_latency);
 	midi_option_combo.set_active_text (state->midi_option);
@@ -2115,6 +2233,7 @@ EngineControl::push_state_to_backend (bool start)
 	bool change_device = false;
 	bool change_rate = false;
 	bool change_bufsize = false;
+	bool change_nperiods = false;
 	bool change_latency = false;
 	bool change_channels = false;
 	bool change_midi = false;
@@ -2159,6 +2278,11 @@ EngineControl::push_state_to_backend (bool start)
 				change_bufsize = true;
 			}
 
+			if (backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0
+					&& get_nperiods() != backend->period_size()) {
+				change_nperiods = true;
+			}
+
 			if (get_midi_option() != backend->midi_option()) {
 				change_midi = true;
 			}
@@ -2198,6 +2322,7 @@ EngineControl::push_state_to_backend (bool start)
 			change_channels = true;
 			change_latency = true;
 			change_midi = true;
+			change_nperiods = backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0;
 		}
 
 	} else {
@@ -2255,7 +2380,8 @@ EngineControl::push_state_to_backend (bool start)
 
 	/* determine if we need to stop the backend before changing parameters */
 
-	if (change_driver || change_device || change_channels || change_latency ||
+	if (change_driver || change_device || change_channels || change_nperiods ||
+			(change_latency && !backend->can_change_systemic_latency_when_running ()) ||
 			(change_rate && !backend->can_change_sample_rate_when_running()) ||
 			change_midi ||
 			(change_bufsize && !backend->can_change_buffer_size_when_running())) {
@@ -2264,25 +2390,6 @@ EngineControl::push_state_to_backend (bool start)
 		restart_required = false;
 	}
 
-	if (was_running) {
-
-		if (!change_driver && !change_device && !change_channels && !change_latency && !change_midi) {
-			/* no changes in any parameters that absolutely require a
-			 * restart, so check those that might be changeable without a
-			 * restart
-			 */
-
-			if (change_rate && !backend->can_change_sample_rate_when_running()) {
-				/* can't do this while running ... */
-				restart_required = true;
-			}
-
-			if (change_bufsize && !backend->can_change_buffer_size_when_running()) {
-				/* can't do this while running ... */
-				restart_required = true;
-			}
-		}
-	}
 
 	if (was_running) {
 		if (restart_required) {
@@ -2319,6 +2426,10 @@ EngineControl::push_state_to_backend (bool start)
 		error << string_compose (_("Cannot set buffer size to %1"), get_buffer_size()) << endmsg;
 		return -1;
 	}
+	if (change_nperiods && backend->set_peridod_size (get_nperiods())) {
+		error << string_compose (_("Cannot set periods to %1"), get_nperiods()) << endmsg;
+		return -1;
+	}
 
 	if (change_channels || get_input_channels() == 0 || get_output_channels() == 0) {
 		if (backend->set_input_channels (get_input_channels())) {
@@ -2353,6 +2464,10 @@ EngineControl::push_state_to_backend (bool start)
 				} else {
 					backend->set_midi_device_enabled ((*p)->name, false);
 				}
+				if (backend->can_change_systemic_latency_when_running ()) {
+					backend->set_systemic_midi_input_latency ((*p)->name, 0);
+					backend->set_systemic_midi_output_latency ((*p)->name, 0);
+				}
 				continue;
 			}
 			backend->set_midi_device_enabled ((*p)->name, (*p)->enabled);
@@ -2390,6 +2505,8 @@ EngineControl::post_push ()
 		store_state(state);
 	}
 
+	states.sort (state_sort_cmp);
+
 	/* all off */
 
 	for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
@@ -2440,6 +2557,13 @@ EngineControl::get_buffer_size () const
 	return samples;
 }
 
+uint32_t
+EngineControl::get_nperiods () const
+{
+	string txt = nperiods_combo.get_active_text ();
+	return atoi (txt.c_str());
+}
+
 string
 EngineControl::get_midi_option () const
 {
@@ -2602,8 +2726,7 @@ EngineControl::on_switch_page (GtkNotebookPage*, guint page_num)
 		/* latency tab */
 
 		if (ARDOUR::AudioEngine::instance()->running()) {
-			// TODO - mark as 'stopped for latency
-			stop_engine ();
+			stop_engine (true);
 		}
 
 		{
@@ -2874,6 +2997,10 @@ EngineControl::engine_running ()
 	set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
 	sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
 
+	if (backend->can_set_period_size ()) {
+		set_active_text_if_present (nperiods_combo, nperiods_as_string (backend->period_size()));
+	}
+
 	connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name()));
 	connect_disconnect_button.show();
 
diff --git a/gtk2_ardour/engine_dialog.h b/gtk2_ardour/engine_dialog.h
index 39ae276..d5c54d0 100644
--- a/gtk2_ardour/engine_dialog.h
+++ b/gtk2_ardour/engine_dialog.h
@@ -70,6 +70,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
     Gtk::ComboBoxText midi_option_combo;
     Gtk::ComboBoxText buffer_size_combo;
     Gtk::Label        buffer_size_duration_label;
+    Gtk::ComboBoxText nperiods_combo;
     Gtk::Adjustment input_latency_adjustment;
     Gtk::SpinButton input_latency;
     Gtk::Adjustment output_latency_adjustment;
@@ -128,6 +129,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
     void backend_changed ();
     void sample_rate_changed ();
     void buffer_size_changed ();
+    void nperiods_changed ();
     void parameter_changed ();
     void midi_option_changed ();
 
@@ -137,7 +139,8 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
 
 	void update_midi_options ();
 
-    std::string bufsize_as_string (uint32_t);
+	std::string bufsize_as_string (uint32_t);
+	std::string nperiods_as_string (uint32_t);
 
 	std::vector<float> get_default_sample_rates ();
 	std::vector<uint32_t> get_default_buffer_sizes ();
@@ -147,6 +150,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
 
     float get_rate() const;
     uint32_t get_buffer_size() const;
+    uint32_t get_nperiods() const;
     uint32_t get_input_channels() const;
     uint32_t get_output_channels() const;
     uint32_t get_input_latency() const;
@@ -170,6 +174,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
     bool set_output_device_popdown_strings ();
     void set_samplerate_popdown_strings ();
     void set_buffersize_popdown_strings ();
+    void set_nperiods_popdown_strings ();
     void list_devices ();
     void show_buffer_duration ();
 
@@ -210,6 +215,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
 	std::string output_device;
 	float sample_rate;
 	uint32_t buffer_size;
+	uint32_t n_periods;
 	uint32_t input_latency;
 	uint32_t output_latency;
 	uint32_t input_channels;
@@ -217,6 +223,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
 	bool active;
 	std::string midi_option;
 	std::vector<MidiDeviceSettings> midi_devices;
+	time_t lru;
 
 	StateStruct()
 		: sample_rate (48000)
@@ -225,15 +232,18 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
 		, output_latency (0)
 		, input_channels (0)
 		, output_channels (0)
-		, active (false) {}
+		, active (false)
+		, lru (0) {}
 
     };
 
     typedef boost::shared_ptr<StateStruct> State;
     typedef std::list<State> StateList;
+    static bool state_sort_cmp (const State &a, const State &b);
 
     StateList states;
 
+    State get_matching_state (const std::string& backend);
     State get_matching_state (const std::string& backend,
 			       const std::string& driver,
 			       const std::string& device);
@@ -280,6 +290,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
 	sigc::connection driver_combo_connection;
 	sigc::connection sample_rate_combo_connection;
 	sigc::connection buffer_size_combo_connection;
+	sigc::connection nperiods_combo_connection;
 	sigc::connection device_combo_connection;
 	sigc::connection input_device_combo_connection;
 	sigc::connection output_device_combo_connection;
@@ -300,7 +311,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
     void post_push ();
     void update_sensitivity ();
 	bool start_engine ();
-	bool stop_engine ();
+	bool stop_engine (bool for_latency = false);
 
     /* latency measurement */
     void latency_button_clicked ();
diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc
index 8d9c6ff..ad8873d 100644
--- a/gtk2_ardour/export_dialog.cc
+++ b/gtk2_ardour/export_dialog.cc
@@ -129,8 +129,6 @@ ExportDialog::init ()
 	export_button = add_button (_("Export"), RESPONSE_FAST);
 	set_default_response (RESPONSE_FAST);
 
-	list_files_button.set_name ("PaddedButton");
-
 	cancel_button->signal_clicked().connect (sigc::mem_fun (*this, &ExportDialog::close_dialog));
 	export_button->signal_clicked().connect (sigc::mem_fun (*this, &ExportDialog::do_export));
 
diff --git a/gtk2_ardour/export_filename_selector.cc b/gtk2_ardour/export_filename_selector.cc
index 831b75e..2eb6540 100644
--- a/gtk2_ardour/export_filename_selector.cc
+++ b/gtk2_ardour/export_filename_selector.cc
@@ -61,10 +61,6 @@ ExportFilenameSelector::ExportFilenameSelector () :
 
 	path_entry.set_activates_default ();
 
-	date_format_combo.set_name ("PaddedButton");
-	time_format_combo.set_name ("PaddedButton");
-	browse_button.set_name ("PaddedButton");
-
 	label_sizegroup = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
 	label_sizegroup->add_widget (label_label);
 	label_sizegroup->add_widget (path_label);
diff --git a/gtk2_ardour/export_format_selector.cc b/gtk2_ardour/export_format_selector.cc
index a2ba3f3..4074656 100644
--- a/gtk2_ardour/export_format_selector.cc
+++ b/gtk2_ardour/export_format_selector.cc
@@ -37,11 +37,6 @@ ExportFormatSelector::ExportFormatSelector () :
 	pack_start (remove_button, false, false, 3);
 	pack_start (new_button, false, false, 3);
 
-	format_combo.set_name ("PaddedButton");
-	edit_button.set_name ("PaddedButton");
-	remove_button.set_name ("PaddedButton");
-	new_button.set_name ("PaddedButton");
-
 	edit_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &ExportFormatSelector::open_edit_dialog), false)));
 	remove_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatSelector::remove_format), true));
 	new_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportFormatSelector::add_new_format));
diff --git a/gtk2_ardour/export_preset_selector.cc b/gtk2_ardour/export_preset_selector.cc
index 6adf5a4..3e3b0d0 100644
--- a/gtk2_ardour/export_preset_selector.cc
+++ b/gtk2_ardour/export_preset_selector.cc
@@ -41,11 +41,6 @@ ExportPresetSelector::ExportPresetSelector () :
 	pack_start (remove_button, false, false, 6);
 	pack_start (new_button, false, false, 0);
 
-	entry.set_name ("PaddedButton");
-	save_button.set_name ("PaddedButton");
-	remove_button.set_name ("PaddedButton");
-	new_button.set_name ("PaddedButton");
-
 	save_button.set_sensitive (false);
 	remove_button.set_sensitive (false);
 	new_button.set_sensitive (false);
diff --git a/gtk2_ardour/export_timespan_selector.cc b/gtk2_ardour/export_timespan_selector.cc
index 83f8a8f..9a294af 100644
--- a/gtk2_ardour/export_timespan_selector.cc
+++ b/gtk2_ardour/export_timespan_selector.cc
@@ -78,7 +78,6 @@ ExportTimespanSelector::ExportTimespanSelector (ARDOUR::Session * session, Profi
 
 	time_format_list = Gtk::ListStore::create (time_format_cols);
 	time_format_combo.set_model (time_format_list);
-	time_format_combo.set_name ("PaddedButton");
 
 	iter = time_format_list->append();
 	row = *iter;
diff --git a/gtk2_ardour/export_video_dialog.cc b/gtk2_ardour/export_video_dialog.cc
index a21a903..10ec8ac 100644
--- a/gtk2_ardour/export_video_dialog.cc
+++ b/gtk2_ardour/export_video_dialog.cc
@@ -112,7 +112,7 @@ ExportVideoDialog::ExportVideoDialog ()
 	/* check if ffmpeg can be found */
 	_transcoder = new TranscodeFfmpeg(X_(""));
 	if (!_transcoder->ffexec_ok()) {
-		l = manage (new Label (_("No ffprobe or ffmpeg executables could be found on this system. Video Export is not possible until you install those tools. See the Log window for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
+		l = manage (new Label (_("ffmpeg installation was not found. Video Export is not possible. See the Log window for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
 		l->set_line_wrap();
 		vbox->pack_start (*l, false, false, 8);
 		get_vbox()->pack_start (*vbox, false, false);
@@ -150,7 +150,6 @@ ExportVideoDialog::ExportVideoDialog ()
 	path_hbox->pack_start (*l, false, false, 2);
 	vbox->pack_start (*path_hbox, false, false, 2);
 
-	insnd_combo.set_name ("PaddedButton");
 	insnd_combo.append_text (string_compose (_("from the %1 session's start to the session's end"), PROGRAM_NAME));
 	outfn_path_entry.set_width_chars(38);
 
@@ -202,7 +201,6 @@ ExportVideoDialog::ExportVideoDialog ()
 	t->attach (debug_checkbox, 0, 4, ty, ty+1); ty++;
 #endif
 
-	preset_combo.set_name ("PaddedButton");
 	preset_combo.append_text("none");
 	preset_combo.append_text("dvd-mp2");
 	preset_combo.append_text("dvd-NTSC");
@@ -214,7 +212,6 @@ ExportVideoDialog::ExportVideoDialog ()
 	preset_combo.append_text("webm");
 	preset_combo.append_text("you-tube");
 
-	audio_codec_combo.set_name ("PaddedButton");
 	audio_codec_combo.append_text(_("(default for format)"));
 	audio_codec_combo.append_text("ac3");
 	audio_codec_combo.append_text("aac");
@@ -223,7 +220,6 @@ ExportVideoDialog::ExportVideoDialog ()
 	audio_codec_combo.append_text("mp2");
 	audio_codec_combo.append_text("pcm_s16le");
 
-	video_codec_combo.set_name ("PaddedButton");
 	video_codec_combo.append_text(_("(default for format)"));
 	video_codec_combo.append_text("flv");
 	video_codec_combo.append_text("libtheora");
@@ -234,7 +230,6 @@ ExportVideoDialog::ExportVideoDialog ()
 	video_codec_combo.append_text("vpx (webm)");
 	video_codec_combo.append_text("copy");
 
-	audio_bitrate_combo.set_name ("PaddedButton");
 	audio_bitrate_combo.append_text(_("(default)"));
 	audio_bitrate_combo.append_text("64k");
 	audio_bitrate_combo.append_text("128k");
@@ -242,12 +237,10 @@ ExportVideoDialog::ExportVideoDialog ()
 	audio_bitrate_combo.append_text("256k");
 	audio_bitrate_combo.append_text("320k");
 
-	audio_samplerate_combo.set_name ("PaddedButton");
 	audio_samplerate_combo.append_text("22050");
 	audio_samplerate_combo.append_text("44100");
 	audio_samplerate_combo.append_text("48000");
 
-	video_bitrate_combo.set_name ("PaddedButton");
 	video_bitrate_combo.append_text(_("(default)"));
 	video_bitrate_combo.append_text(_("(retain)"));
 	video_bitrate_combo.append_text("200k");
@@ -256,7 +249,6 @@ ExportVideoDialog::ExportVideoDialog ()
 	video_bitrate_combo.append_text("5000k");
 	video_bitrate_combo.append_text("8000k");
 
-	fps_combo.set_name ("PaddedButton");
 	fps_combo.append_text("23.976");
 	fps_combo.append_text("24");
 	fps_combo.append_text("24.976");
@@ -266,7 +258,6 @@ ExportVideoDialog::ExportVideoDialog ()
 	fps_combo.append_text("59.94");
 	fps_combo.append_text("60");
 
-	aspect_combo.set_name ("PaddedButton");
 	aspect_combo.append_text("4:3");
 	aspect_combo.append_text("16:9");
 
@@ -619,7 +610,7 @@ ExportVideoDialog::launch_export ()
 	_session->add_extra_xml (get_state());
 
 	std::string outfn = outfn_path_entry.get_text();
-	if (!confirm_video_outfn(outfn)) { return; }
+	if (!confirm_video_outfn(*this, outfn)) { return; }
 
 	vbox->hide();
 	cancel_button->hide();
diff --git a/gtk2_ardour/export_video_infobox.cc b/gtk2_ardour/export_video_infobox.cc
index a3e356d..15ecc1a 100644
--- a/gtk2_ardour/export_video_infobox.cc
+++ b/gtk2_ardour/export_video_infobox.cc
@@ -48,8 +48,8 @@ ExportVideoInfobox::ExportVideoInfobox (Session* s)
 	vbox->pack_start (*l, false, true);
 	l = manage (new Label (
 				string_compose(
-				_("Video encoding is a non-trivial task with many details.\n\nPlease see the manual at %1/video-timeline/operations/#export.\n\nOpen Manual in Browser? "),
-				Config->get_reference_manual_url()
+				_("%1 does not include commercial licenses for encoding audio/video. Visit mpegla.com for information about licensing various audio/video codecs.\n\nVideo encoding is a non-trivial task with many details.\n\nPlease see the manual at %2/video-timeline/operations/#export.\n\nOpen Manual in Browser? "),
+				PROGRAM_NAME, Config->get_reference_manual_url()
 				), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
 	l->set_size_request(700,-1);
 	l->set_line_wrap();
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
index 47b5f93..ef2de43 100644
--- a/gtk2_ardour/generic_pluginui.cc
+++ b/gtk2_ardour/generic_pluginui.cc
@@ -923,7 +923,7 @@ GenericPluginUI::control_port_toggled (ControlUI* cui)
 	} else {
 		cui->button->set_name ("PluginEditorButton");
 	}
-	insert->automation_control (cui->parameter())->set_value (active);
+	insert->automation_control (cui->parameter())->set_value (active, Controllable::NoGroup);
 	cui->ignore_change--;
 }
 
@@ -932,7 +932,7 @@ GenericPluginUI::control_combo_changed (ControlUI* cui)
 {
 	if (!cui->ignore_change && cui->scale_points) {
 		string value = cui->combo->get_active_text();
-		insert->automation_control (cui->parameter())->set_value ((*cui->scale_points)[value]);
+		insert->automation_control (cui->parameter())->set_value ((*cui->scale_points)[value], Controllable::NoGroup);
 	}
 }
 
diff --git a/gtk2_ardour/ghostregion.cc b/gtk2_ardour/ghostregion.cc
index 7c697a1..127ab64 100644
--- a/gtk2_ardour/ghostregion.cc
+++ b/gtk2_ardour/ghostregion.cc
@@ -30,6 +30,7 @@
 #include "ghostregion.h"
 #include "midi_streamview.h"
 #include "midi_time_axis.h"
+#include "region_view.h"
 #include "rgb_macros.h"
 #include "note.h"
 #include "hit.h"
@@ -40,11 +41,14 @@ using namespace Editing;
 using namespace ArdourCanvas;
 using namespace ARDOUR;
 
-PBD::Signal1<void,GhostRegion*> GhostRegion::CatchDeletion;
-
-GhostRegion::GhostRegion (ArdourCanvas::Container* parent, TimeAxisView& tv, TimeAxisView& source_tv, double initial_pos)
-	: trackview (tv)
-	, source_trackview (source_tv)
+GhostRegion::GhostRegion(RegionView& rv,
+                         ArdourCanvas::Container* parent,
+                         TimeAxisView& tv,
+                         TimeAxisView& source_tv,
+                         double initial_pos)
+    : parent_rv(rv)
+    , trackview(tv)
+    , source_trackview(source_tv)
 {
 	group = new ArdourCanvas::Container (parent);
 	CANVAS_DEBUG_NAME (group, "ghost region");
@@ -70,7 +74,8 @@ GhostRegion::GhostRegion (ArdourCanvas::Container* parent, TimeAxisView& tv, Tim
 
 GhostRegion::~GhostRegion ()
 {
-	CatchDeletion (this);
+	parent_rv.remove_ghost(this);
+	trackview.erase_ghost(this);
 	delete base_rect;
 	delete group;
 }
@@ -108,8 +113,11 @@ GhostRegion::is_automation_ghost()
 	return (dynamic_cast<AutomationTimeAxisView*>(&trackview)) != 0;
 }
 
-AudioGhostRegion::AudioGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos)
-	: GhostRegion(tv.ghost_group(), tv, source_tv, initial_unit_pos)
+AudioGhostRegion::AudioGhostRegion(RegionView& rv,
+                                   TimeAxisView& tv,
+                                   TimeAxisView& source_tv,
+                                   double initial_unit_pos)
+    : GhostRegion(rv, tv.ghost_group(), tv, source_tv, initial_unit_pos)
 {
 
 }
@@ -162,12 +170,16 @@ AudioGhostRegion::set_colors ()
 /** The general constructor; called when the destination timeaxisview doesn't have
  *  a midistreamview.
  *
+ *  @param rv The parent RegionView that is being ghosted.
  *  @param tv TimeAxisView that this ghost region is on.
  *  @param source_tv TimeAxisView that we are the ghost for.
  */
-MidiGhostRegion::MidiGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos)
-	: GhostRegion(tv.ghost_group(), tv, source_tv, initial_unit_pos)
-	, _optimization_iterator (events.end ())
+MidiGhostRegion::MidiGhostRegion(RegionView& rv,
+                                 TimeAxisView& tv,
+                                 TimeAxisView& source_tv,
+                                 double initial_unit_pos)
+    : GhostRegion(rv, tv.ghost_group(), tv, source_tv, initial_unit_pos)
+    , _optimization_iterator(events.end())
 {
 	base_rect->lower_to_bottom();
 	update_range ();
@@ -176,12 +188,20 @@ MidiGhostRegion::MidiGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, doub
 }
 
 /**
+ *  @param rv The parent RegionView being ghosted.
  *  @param msv MidiStreamView that this ghost region is on.
  *  @param source_tv TimeAxisView that we are the ghost for.
  */
-MidiGhostRegion::MidiGhostRegion(MidiStreamView& msv, TimeAxisView& source_tv, double initial_unit_pos)
-	: GhostRegion(msv.midi_underlay_group, msv.trackview(), source_tv, initial_unit_pos)
-	, _optimization_iterator (events.end ())
+MidiGhostRegion::MidiGhostRegion(RegionView& rv,
+                                 MidiStreamView& msv,
+                                 TimeAxisView& source_tv,
+                                 double initial_unit_pos)
+    : GhostRegion(rv,
+                  msv.midi_underlay_group,
+                  msv.trackview(),
+                  source_tv,
+                  initial_unit_pos)
+    , _optimization_iterator(events.end())
 {
 	base_rect->lower_to_bottom();
 	update_range ();
diff --git a/gtk2_ardour/ghostregion.h b/gtk2_ardour/ghostregion.h
index a62d8d5..8a4a828 100644
--- a/gtk2_ardour/ghostregion.h
+++ b/gtk2_ardour/ghostregion.h
@@ -32,11 +32,17 @@ class Note;
 class Hit;
 class MidiStreamView;
 class TimeAxisView;
+class RegionView;
 
 class GhostRegion : public sigc::trackable
 {
 public:
-	GhostRegion(ArdourCanvas::Container* parent, TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos);
+	GhostRegion(RegionView& rv,
+	            ArdourCanvas::Container* parent,
+	            TimeAxisView& tv,
+	            TimeAxisView& source_tv,
+	            double initial_unit_pos);
+
 	virtual ~GhostRegion();
 
 	virtual void set_samples_per_pixel (double) = 0;
@@ -48,19 +54,21 @@ public:
 	guint source_track_color(unsigned char alpha = 0xff);
 	bool is_automation_ghost();
 
+	RegionView& parent_rv;
 	/** TimeAxisView that is the AutomationTimeAxisView that we are on */
 	TimeAxisView& trackview;
 	/** TimeAxisView that we are a ghost for */
 	TimeAxisView& source_trackview;
 	ArdourCanvas::Container* group;
 	ArdourCanvas::Rectangle* base_rect;
-
-	static PBD::Signal1<void,GhostRegion*> CatchDeletion;
 };
 
 class AudioGhostRegion : public GhostRegion {
 public:
-	AudioGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos);
+	AudioGhostRegion(RegionView& rv,
+	                 TimeAxisView& tv,
+	                 TimeAxisView& source_tv,
+	                 double initial_unit_pos);
 
 	void set_samples_per_pixel (double);
 	void set_height();
@@ -80,8 +88,16 @@ public:
 	    ArdourCanvas::Item* item;
 	};
 
-	MidiGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos);
-	MidiGhostRegion(MidiStreamView& msv, TimeAxisView& source_tv, double initial_unit_pos);
+	MidiGhostRegion(RegionView& rv,
+	                TimeAxisView& tv,
+	                TimeAxisView& source_tv,
+	                double initial_unit_pos);
+
+	MidiGhostRegion(RegionView& rv,
+	                MidiStreamView& msv,
+	                TimeAxisView& source_tv,
+	                double initial_unit_pos);
+
 	~MidiGhostRegion();
 
 	MidiStreamView* midi_view();
diff --git a/gtk2_ardour/icons/faderport-small.png b/gtk2_ardour/icons/faderport-small.png
new file mode 100644
index 0000000..cc69d11
Binary files /dev/null and b/gtk2_ardour/icons/faderport-small.png differ
diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc
index ae47794..79f83a4 100644
--- a/gtk2_ardour/keyboard.cc
+++ b/gtk2_ardour/keyboard.cc
@@ -48,7 +48,11 @@ accel_map_changed (GtkAccelMap* /*map*/,
 	me->ui.setup_tooltips ();
 }
 
+#ifdef GTKOSX
+guint ArdourKeyboard::constraint_mod = Keyboard::PrimaryModifier;
+#else
 guint ArdourKeyboard::constraint_mod = Keyboard::SecondaryModifier;
+#endif
 guint ArdourKeyboard::trim_contents_mod = Keyboard::PrimaryModifier;
 guint ArdourKeyboard::trim_overlap_mod = Keyboard::TertiaryModifier;
 guint ArdourKeyboard::trim_anchored_mod = Keyboard::TertiaryModifier;
@@ -248,21 +252,21 @@ ArdourKeyboard::set_state (const XMLNode& node, int version)
 bool
 ArdourKeyboard::indicates_snap (guint state)
 {
-	const bool contains_s = Keyboard::modifier_state_contains (state, Keyboard::snap_modifier());
-	const bool contains_d = Keyboard::modifier_state_contains (state, Keyboard::snap_delta_modifier());
-	const bool equals_d = Keyboard::modifier_state_equals (state, Keyboard::snap_delta_modifier());
+	const bool contains_s = Keyboard::modifier_state_contains (state, Keyboard::snap_modifier ());
+	const bool contains_d = Keyboard::modifier_state_contains (state, Keyboard::snap_delta_modifier ());
+	const bool s_contains_d = Keyboard::modifier_state_contains (Keyboard::snap_modifier (), Keyboard::snap_delta_modifier ());
 
-	return  (contains_s && ((contains_d && !equals_d) || !contains_d));
+	return  (contains_s && ((contains_d && s_contains_d) || !contains_d));
 }
 
 bool
 ArdourKeyboard::indicates_snap_delta (guint state)
 {
-	const bool contains_d = Keyboard::modifier_state_contains (state, Keyboard::snap_delta_modifier());
-	const bool contains_s = Keyboard::modifier_state_contains (state, Keyboard::snap_modifier());
-	const bool equals_s = Keyboard::modifier_state_equals (state, Keyboard::snap_modifier());
+	const bool contains_d = Keyboard::modifier_state_contains (state, Keyboard::snap_delta_modifier ());
+	const bool contains_s = Keyboard::modifier_state_contains (state, Keyboard::snap_modifier ());
+	const bool d_contains_s = Keyboard::modifier_state_contains (Keyboard::snap_delta_modifier (), Keyboard::snap_modifier ());
 
-	return (contains_d && ((contains_s && !equals_s) || !contains_s));
+	return (contains_d && ((contains_s && d_contains_s) || !contains_s));
 }
 
 void
diff --git a/gtk2_ardour/level_meter.cc b/gtk2_ardour/level_meter.cc
index 81ec474..d9f3130 100644
--- a/gtk2_ardour/level_meter.cc
+++ b/gtk2_ardour/level_meter.cc
@@ -230,6 +230,7 @@ LevelMeterBase::hide_all_meters ()
 			(*i).packed = false;
 		}
 	}
+	visible_meter_count = 0;
 }
 
 void
diff --git a/gtk2_ardour/linux_vst_gui_support.cc b/gtk2_ardour/linux_vst_gui_support.cc
index e5722b2..37f046e 100644
--- a/gtk2_ardour/linux_vst_gui_support.cc
+++ b/gtk2_ardour/linux_vst_gui_support.cc
@@ -56,20 +56,19 @@ static VSTState * vstfx_first = NULL;
 
 const char magic[] = "VSTFX Plugin State v002";
 
-int  gui_thread_id = 0;
 static int gui_quit = 0;
 
 /*This will be our connection to X*/
 
-Display* LXVST_XDisplay = NULL;
+static Display* LXVST_XDisplay = NULL;
 
 /*The thread handle for the GUI event loop*/
 
-pthread_t LXVST_gui_event_thread;
+static pthread_t LXVST_gui_event_thread;
 
 /*Util functions to get the value of a property attached to an XWindow*/
 
-bool LXVST_xerror;
+static bool LXVST_xerror;
 
 int TempErrorHandler(Display *display, XErrorEvent *e)
 {
@@ -525,7 +524,7 @@ int vstfx_init (void* ptr)
 
 	/*Create the thread - use default attrs for now, don't think we need anything special*/
 
-	thread_create_result = pthread_create(&LXVST_gui_event_thread, NULL, gui_event_loop, NULL);
+	thread_create_result = pthread_create(&LXVST_gui_event_thread, &thread_attributes, gui_event_loop, NULL);
 
 	if(thread_create_result!=0)
 	{
@@ -534,6 +533,7 @@ int vstfx_init (void* ptr)
 		vstfx_error ("** ERROR ** VSTFX: Failed starting GUI event thread");
 
 		XCloseDisplay(LXVST_XDisplay);
+		gui_quit = 1;
 
 		return -1;
 	}
@@ -545,6 +545,9 @@ int vstfx_init (void* ptr)
 
 void vstfx_exit()
 {
+	if (gui_quit) {
+		return;
+	}
 	gui_quit = 1;
 
 	/*We need to pthread_join the gui_thread here so
diff --git a/gtk2_ardour/lv2_plugin_ui.cc b/gtk2_ardour/lv2_plugin_ui.cc
index 141f437..c9950fa 100644
--- a/gtk2_ardour/lv2_plugin_ui.cc
+++ b/gtk2_ardour/lv2_plugin_ui.cc
@@ -20,7 +20,9 @@
 #include "ardour/lv2_plugin.h"
 #include "ardour/session.h"
 #include "pbd/error.h"
+#include "pbd/stacktrace.h"
 
+#include "gui_thread.h"
 #include "lv2_plugin_ui.h"
 #include "timers.h"
 
@@ -53,8 +55,11 @@ LV2PluginUI::write_from_ui(void*       controller,
 		}
 
 		boost::shared_ptr<AutomationControl> ac = me->_controllables[port_index];
+
+		me->_updates.insert (port_index);
+
 		if (ac) {
-			ac->set_value(*(const float*)buffer);
+			ac->set_value(*(const float*)buffer, Controllable::NoGroup);
 		}
 	} else if (format == URIMap::instance().urids.atom_eventTransfer) {
 
@@ -120,34 +125,24 @@ LV2PluginUI::on_external_ui_closed(void* controller)
 }
 
 void
-LV2PluginUI::parameter_changed(uint32_t port_index, float val)
-{
-	PlugUIBase::parameter_changed(port_index, val);
-
-	if (val != _values[port_index]) {
-		parameter_update(port_index, val);
-	}
-}
-
-void
-LV2PluginUI::parameter_update(uint32_t port_index, float val)
+LV2PluginUI::control_changed (uint32_t port_index)
 {
-	if (!_inst) {
-		return;
+	/* Must run in GUI thread because we modify _updates with no lock */
+	if (_lv2->get_parameter (port_index) != _values_last_sent_to_ui[port_index]) {
+		/* current plugin parameter does not match last value received
+		   from GUI, so queue an update to push it to the GUI during
+		   our regular timeout.
+		*/
+		_updates.insert (port_index);
 	}
-
-	suil_instance_port_event((SuilInstance*)_inst, port_index, 4, 0, &val);
-	_values[port_index] = val;
 }
 
 bool
 LV2PluginUI::start_updating(GdkEventAny*)
 {
-	if (!_output_ports.empty()) {
-		_screen_update_connection.disconnect();
-		_screen_update_connection = Timers::super_rapid_connect
-		        (sigc::mem_fun(*this, &LV2PluginUI::output_update));
-	}
+	_screen_update_connection.disconnect();
+	_screen_update_connection = Timers::super_rapid_connect
+		(sigc::mem_fun(*this, &LV2PluginUI::output_update));
 	return false;
 }
 
@@ -155,11 +150,21 @@ bool
 LV2PluginUI::stop_updating(GdkEventAny*)
 {
 	//cout << "stop_updating" << endl;
+	_screen_update_connection.disconnect();
+	return false;
+}
 
-	if (!_output_ports.empty()) {
-		_screen_update_connection.disconnect();
+void
+LV2PluginUI::queue_port_update()
+{
+	const uint32_t num_ports = _lv2->num_ports();
+	for (uint32_t i = 0; i < num_ports; ++i) {
+		bool     ok;
+		uint32_t port = _lv2->nth_parameter(i, ok);
+		if (ok) {
+			_updates.insert (port);
+		}
 	}
-	return false;
 }
 
 void
@@ -183,13 +188,37 @@ LV2PluginUI::output_update()
 		}
 	}
 
-	/* FIXME only works with control output ports (which is all we support now anyway) */
+	if (!_inst) {
+		return;
+	}
+
+	/* output ports (values set by DSP) need propagating to GUI */
+
 	uint32_t nports = _output_ports.size();
 	for (uint32_t i = 0; i < nports; ++i) {
 		uint32_t index = _output_ports[i];
-		parameter_changed(index, _lv2->get_parameter(index));
+		float val = _lv2->get_parameter (index);
+
+		if (val != _values_last_sent_to_ui[index]) {
+			/* Send to GUI */
+			suil_instance_port_event ((SuilInstance*)_inst, index, 4, 0, &val);
+			/* Cache current value */
+			_values_last_sent_to_ui[index] = val;
+		}
+	}
+
+	/* Input ports marked for update because the control value changed
+	   since the last redisplay.
+	*/
+
+	for (Updates::iterator i = _updates.begin(); i != _updates.end(); ++i) {
+		float val = _lv2->get_parameter (*i);
+		/* push current value to the GUI */
+		suil_instance_port_event ((SuilInstance*)_inst, (*i), 4, 0, &val);
+		_values_last_sent_to_ui[(*i)] = val;
 	}
 
+	_updates.clear ();
 }
 
 LV2PluginUI::LV2PluginUI(boost::shared_ptr<PluginInsert> pi,
@@ -198,7 +227,7 @@ LV2PluginUI::LV2PluginUI(boost::shared_ptr<PluginInsert> pi,
 	, _pi(pi)
 	, _lv2(lv2p)
 	, _gui_widget(NULL)
-	, _values(NULL)
+	, _values_last_sent_to_ui(NULL)
 	, _external_ui_ptr(NULL)
 	, _inst(NULL)
 {
@@ -212,6 +241,8 @@ LV2PluginUI::LV2PluginUI(boost::shared_ptr<PluginInsert> pi,
 	_ardour_buttons_box.pack_end (add_button, false, false);
 	_ardour_buttons_box.pack_end (_preset_combo, false, false);
 	_ardour_buttons_box.pack_end (_preset_modified, false, false);
+
+	plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&LV2PluginUI::queue_port_update, this), gui_context ());
 }
 
 void
@@ -352,19 +383,29 @@ LV2PluginUI::lv2ui_instantiate(const std::string& title)
 		_external_ui_ptr = (struct lv2_external_ui*)GET_WIDGET(_inst);
 	}
 
-	_values = new float[num_ports];
+	_values_last_sent_to_ui = new float[num_ports];
 	_controllables.resize(num_ports);
+
 	for (uint32_t i = 0; i < num_ports; ++i) {
 		bool     ok;
 		uint32_t port = _lv2->nth_parameter(i, ok);
 		if (ok) {
-			_values[port]        = _lv2->get_parameter(port);
+			/* Cache initial value of the parameter, regardless of
+			   whether it is input or output
+			*/
+
+			_values_last_sent_to_ui[port]        = _lv2->get_parameter(port);
 			_controllables[port] = boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (
 				insert->control(Evoral::Parameter(PluginAutomation, 0, port)));
 
 			if (_lv2->parameter_is_control(port) && _lv2->parameter_is_input(port)) {
-				parameter_update(port, _values[port]);
+				if (_controllables[port]) {
+					_controllables[port]->Changed.connect (control_connections, invalidator (*this), boost::bind (&LV2PluginUI::control_changed, this, port), gui_context());
+				}
 			}
+
+			/* queue for first update ("push") to GUI */
+			_updates.insert (port);
 		}
 	}
 
@@ -401,9 +442,7 @@ LV2PluginUI::lv2ui_free()
 
 LV2PluginUI::~LV2PluginUI ()
 {
-	if (_values) {
-		delete[] _values;
-	}
+	delete [] _values_last_sent_to_ui;
 
 	_message_update_connection.disconnect();
 	_screen_update_connection.disconnect();
diff --git a/gtk2_ardour/lv2_plugin_ui.h b/gtk2_ardour/lv2_plugin_ui.h
index 6a8acf9..da6ffca 100644
--- a/gtk2_ardour/lv2_plugin_ui.h
+++ b/gtk2_ardour/lv2_plugin_ui.h
@@ -26,6 +26,7 @@
 
 #include <list>
 #include <map>
+#include <set>
 #include <vector>
 
 #include <gtkmm/widget.h>
@@ -64,7 +65,7 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
 
   private:
 
-	void parameter_changed (uint32_t, float);
+	void control_changed (uint32_t);
 
 	typedef boost::shared_ptr<ARDOUR::AutomationControl> ControllableRef;
 
@@ -76,7 +77,7 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
 	Gtk::Widget*                         _gui_widget;
 	/** a box containing the focus, bypass, delete, save / add preset buttons etc. */
 	Gtk::HBox                            _ardour_buttons_box;
-	float*                               _values;
+	float*                               _values_last_sent_to_ui;
 	std::vector<ControllableRef>         _controllables;
 	struct lv2_external_ui_host          _external_ui_host;
 	LV2_Feature                          _external_ui_feature;
@@ -85,6 +86,8 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
 	LV2_Feature                          _parent_feature;
 	Gtk::Window*                         _win_ptr;
 	void*                                _inst;
+	typedef std::set<uint32_t> Updates;
+	Updates                              _updates;
 
 	static void on_external_ui_closed(void* controller);
 
@@ -115,6 +118,7 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
 	bool configure_handler (GdkEventConfigure*);
 	void save_plugin_setting ();
 	void output_update();
+	void queue_port_update();
 	bool is_update_wanted(uint32_t index);
 
 	virtual bool on_window_show(const std::string& title);
diff --git a/gtk2_ardour/lxvst_plugin_ui.cc b/gtk2_ardour/lxvst_plugin_ui.cc
index ad8bc01..f5265cf 100644
--- a/gtk2_ardour/lxvst_plugin_ui.cc
+++ b/gtk2_ardour/lxvst_plugin_ui.cc
@@ -78,9 +78,12 @@ LXVSTPluginUI::resize_callback ()
 	void* gtk_parent_window = _vst->state()->extra_data;
 
 	if (gtk_parent_window) {
+		_socket.set_size_request(
+				new_width + _vst->state()->hoffset,
+				new_height + _vst->state()->voffset);
+
 		((Gtk::Window*) gtk_parent_window)->resize (new_width, new_height + LXVST_H_FIDDLE);
 	}
-
 	_vst->state()->want_resize = 0;
 }
 
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
index ce7dc4b..6a8347f 100644
--- a/gtk2_ardour/main.cc
+++ b/gtk2_ardour/main.cc
@@ -25,6 +25,10 @@
 #include <sigc++/bind.h>
 #include <gtkmm/settings.h>
 
+#ifdef HAVE_FFTW35F
+#include <fftw3.h>
+#endif
+
 #include "pbd/error.h"
 #include "pbd/file_utils.h"
 #include "pbd/textreceiver.h"
@@ -283,6 +287,10 @@ int main (int argc, char *argv[])
 		Glib::thread_init();
 	}
 
+#ifdef HAVE_FFTW35F
+	fftwf_make_planner_thread_safe ();
+#endif
+
 #ifdef ENABLE_NLS
 	gtk_set_locale ();
 #endif
diff --git a/gtk2_ardour/midi_channel_selector.cc b/gtk2_ardour/midi_channel_selector.cc
index 40ab968..d76a5d5 100644
--- a/gtk2_ardour/midi_channel_selector.cc
+++ b/gtk2_ardour/midi_channel_selector.cc
@@ -650,6 +650,8 @@ MidiChannelSelectorWindow::playback_mode_changed ()
 		}
 	}
 
+	playback_mask_changed(); // update buttons
+
 	last_drawn_playback_mode = mode;
 }
 
@@ -748,6 +750,8 @@ MidiChannelSelectorWindow::capture_mode_changed ()
 		}
 	}
 
+	capture_mask_changed (); // udpate buttons
+
 	last_drawn_capture_mode = mode;
 }
 
diff --git a/gtk2_ardour/midi_export_dialog.cc b/gtk2_ardour/midi_export_dialog.cc
index 34469ad..3e91ca4 100644
--- a/gtk2_ardour/midi_export_dialog.cc
+++ b/gtk2_ardour/midi_export_dialog.cc
@@ -37,8 +37,8 @@ MidiExportDialog::MidiExportDialog (PublicEditor&, boost::shared_ptr<MidiRegion>
 {
 	set_border_width (12);
 
-	add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
 	add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+	add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
 
 	get_vbox()->set_border_width (12);
 	get_vbox()->pack_start (file_chooser);
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 5300a82..a4b9c19 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -268,10 +268,6 @@ MidiRegionView::init (bool wfd)
 {
 	PublicEditor::DropDownKeys.connect (sigc::mem_fun (*this, &MidiRegionView::drop_down_keys));
 
-	NoteBase::NoteBaseDeleted.connect (note_delete_connection, MISSING_INVALIDATOR,
-					   boost::bind (&MidiRegionView::maybe_remove_deleted_note_from_selection, this, _1),
-					   gui_context());
-
 	if (wfd) {
 		Glib::Threads::Mutex::Lock lm(midi_region()->midi_source(0)->mutex());
 		midi_region()->midi_source(0)->load_model(lm);
@@ -547,7 +543,6 @@ MidiRegionView::button_release (GdkEventButton* ev)
 		case MouseContent:
 		case MouseTimeFX:
 			{
-				clear_selection();
 				_mouse_changed_selection = true;
 
 				if (Keyboard::is_insert_note_event(ev)) {
@@ -559,13 +554,9 @@ MidiRegionView::button_release (GdkEventButton* ev)
 					group->canvas_to_item (event_x, event_y);
 
 					Evoral::Beats beats = get_grid_beats(editor.pixel_to_sample(event_x));
-
-					/* Shorten the length by 1 tick so that we can add a new note at the next
-					   grid snap without it overlapping this one.
-					*/
-					beats -= Evoral::Beats::tick();
-
 					create_note_at (editor.pixel_to_sample (event_x), event_y, beats, true);
+				} else {
+					clear_selection ();
 				}
 
 				break;
@@ -573,14 +564,7 @@ MidiRegionView::button_release (GdkEventButton* ev)
 		case MouseDraw:
 			{
 				Evoral::Beats beats = get_grid_beats(editor.pixel_to_sample(event_x));
-
-				/* Shorten the length by 1 tick so that we can add a new note at the next
-				   grid snap without it overlapping this one.
-				*/
-				beats -= Evoral::Beats::tick();
-
 				create_note_at (editor.pixel_to_sample (event_x), event_y, beats, true);
-
 				break;
 			}
 		default:
@@ -700,9 +684,10 @@ MidiRegionView::scroll (GdkEventScroll* ev)
 		return false;
 	}
 
-	if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
-		/* XXX: bit of a hack; allow PrimaryModifier scroll through so that
-		   it still works for zoom.
+	if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier) ||
+	    Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
+		/* XXX: bit of a hack; allow PrimaryModifier and TertiaryModifier scroll
+		 * through so that it still works for navigation.
 		*/
 		return false;
 	}
@@ -710,7 +695,8 @@ MidiRegionView::scroll (GdkEventScroll* ev)
 	hide_verbose_cursor ();
 
 	bool fine = !Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier);
-	bool together = Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier);
+	Keyboard::ModifierMask mask_together(Keyboard::PrimaryModifier|Keyboard::TertiaryModifier);
+	bool together = Keyboard::modifier_state_contains (ev->state, mask_together);
 
 	if (ev->direction == GDK_SCROLL_UP) {
 		change_velocities (true, fine, false, together);
@@ -1384,8 +1370,6 @@ MidiRegionView::~MidiRegionView ()
 
 	hide_verbose_cursor ();
 
-	note_delete_connection.disconnect ();
-
 	delete _list_editor;
 
 	RegionViewGoingAway (this); /* EMIT_SIGNAL */
@@ -1538,9 +1522,9 @@ MidiRegionView::add_ghost (TimeAxisView& tv)
 		/* if ghost is inserted into midi track, use a dedicated midi ghost canvas group
 		   to allow having midi notes on top of note lines and waveforms.
 		*/
-		ghost = new MidiGhostRegion (*mtv->midi_view(), trackview, unit_position);
+		ghost = new MidiGhostRegion (*this, *mtv->midi_view(), trackview, unit_position);
 	} else {
-		ghost = new MidiGhostRegion (tv, trackview, unit_position);
+		ghost = new MidiGhostRegion (*this, tv, trackview, unit_position);
 	}
 
 	for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
@@ -1551,8 +1535,6 @@ MidiRegionView::add_ghost (TimeAxisView& tv)
 	ghost->set_duration (_region->length() / samples_per_pixel);
 	ghosts.push_back (ghost);
 
-	GhostRegion::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RegionView::remove_ghost, this, _1), gui_context());
-
 	return ghost;
 }
 
@@ -1722,9 +1704,9 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
 
 	if (note->length() > 0) {
 		const framepos_t note_end_frames = min (source_beats_to_region_frames (note->end_time()), _region->length());
-		ev->set_x1 (trackview.editor().sample_to_pixel (note_end_frames));
+		ev->set_x1 (std::max(1., trackview.editor().sample_to_pixel (note_end_frames)) - 1);
 	} else {
-		ev->set_x1 (trackview.editor().sample_to_pixel (_region->length()));
+		ev->set_x1 (std::max(1., trackview.editor().sample_to_pixel (_region->length())) - 1);
 	}
 
 	ev->set_y1 (y0 + std::max(1., floor(midi_stream_view()->note_height()) - 1));
@@ -2098,7 +2080,7 @@ MidiRegionView::step_patch (PatchChange& patch, bool bank, int delta)
 }
 
 void
-MidiRegionView::maybe_remove_deleted_note_from_selection (NoteBase* cne)
+MidiRegionView::note_deleted (NoteBase* cne)
 {
 	if (_selection.empty()) {
 		return;
@@ -2755,6 +2737,7 @@ void
 MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap)
 {
 	bool cursor_set = false;
+	bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic;
 
 	for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
 		ArdourCanvas::Rectangle* resize_rect = (*i)->resize_rect;
@@ -2786,14 +2769,14 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
 
 		if (at_front) {
 			if (with_snap) {
-				resize_rect->set_x0 (snap_to_pixel(current_x) - snap_delta);
+				resize_rect->set_x0 (snap_to_pixel (current_x, ensure_snap) - snap_delta);
 			} else {
 				resize_rect->set_x0 (current_x - snap_delta);
 			}
 			resize_rect->set_x1 (canvas_note->x1());
 		} else {
 			if (with_snap) {
-				resize_rect->set_x1 (snap_to_pixel(current_x) - snap_delta);
+				resize_rect->set_x1 (snap_to_pixel (current_x, ensure_snap) - snap_delta);
 			} else {
 				resize_rect->set_x1 (current_x - snap_delta);
 			}
@@ -2814,7 +2797,7 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
 				sign = -1;
 			}
 
-			const double  snapped_x = (with_snap ? snap_pixel_to_sample (current_x) : trackview.editor ().pixel_to_sample (current_x));
+			const double  snapped_x = (with_snap ? snap_pixel_to_sample (current_x, ensure_snap) : trackview.editor ().pixel_to_sample (current_x));
 			Evoral::Beats beats     = region_frames_to_region_beats (snapped_x);
 			Evoral::Beats len       = Evoral::Beats();
 
@@ -2850,6 +2833,9 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
 {
 	_note_diff_command = _model->new_note_diff_command (_("resize notes"));
 
+	/* XX why doesn't snap_pixel_to_sample() handle this properly? */
+	bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic;
+
 	for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
 		Note*  canvas_note = (*i)->note;
 		ArdourCanvas::Rectangle*  resize_rect = (*i)->resize_rect;
@@ -2896,7 +2882,7 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
 		/* Convert the new x position to a frame within the source */
 		framepos_t current_fr;
 		if (with_snap) {
-			current_fr = snap_pixel_to_sample (current_x) + _region->start ();
+			current_fr = snap_pixel_to_sample (current_x, ensure_snap) + _region->start ();
 		} else {
 			current_fr = trackview.editor().pixel_to_sample (current_x) + _region->start ();
 		}
diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h
index 786a7ec..05d5df9 100644
--- a/gtk2_ardour/midi_region_view.h
+++ b/gtk2_ardour/midi_region_view.h
@@ -332,6 +332,8 @@ public:
 
         ARDOUR::InstrumentInfo& instrument_info() const;
 
+	void note_deleted (NoteBase*);
+
 protected:
 	void region_resized (const PBD::PropertyChange&);
 
@@ -471,9 +473,6 @@ private:
 	MidiListEditor* _list_editor;
 	bool _no_sound_notes;
 
-	PBD::ScopedConnection note_delete_connection;
-	void maybe_remove_deleted_note_from_selection (NoteBase*);
-
 	void snap_changed ();
 	PBD::ScopedConnection snap_changed_connection;
 
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 9564ed2..8ff5d56 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -121,6 +121,8 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, ArdourCanva
 	, controller_menu (0)
 	, _step_editor (0)
 {
+	_midnam_model_selector.disable_scrolling();
+	_midnam_custom_device_mode_selector.disable_scrolling();
 }
 
 void
diff --git a/gtk2_ardour/missing_file_dialog.cc b/gtk2_ardour/missing_file_dialog.cc
index 691dd29..9fe1258 100644
--- a/gtk2_ardour/missing_file_dialog.cc
+++ b/gtk2_ardour/missing_file_dialog.cc
@@ -42,7 +42,10 @@ MissingFileDialog::MissingFileDialog (Session* s, const std::string& path, DataT
         , all_missing_ok (choice_group, _("Skip all missing files"), false)
         , this_missing_ok (choice_group, _("Skip this file"), false)
 {
-        set_session (s);
+	/* This dialog is always shown programatically. Center the window.*/
+	set_position (Gtk::WIN_POS_CENTER);
+
+	set_session (s);
 
         add_button (_("Done"), RESPONSE_OK);
         set_default_response (RESPONSE_OK);
diff --git a/gtk2_ardour/missing_plugin_dialog.cc b/gtk2_ardour/missing_plugin_dialog.cc
index fe0a597..d800946 100644
--- a/gtk2_ardour/missing_plugin_dialog.cc
+++ b/gtk2_ardour/missing_plugin_dialog.cc
@@ -28,7 +28,10 @@ using namespace PBD;
 MissingPluginDialog::MissingPluginDialog (Session * s, list<string> const & plugins)
         : ArdourDialog (_("Missing Plugins"), true, false)
 {
-        set_session (s);
+	/* This dialog is always shown programatically. Center the window.*/
+	set_position (Gtk::WIN_POS_CENTER);
+
+	set_session (s);
 
         add_button (_("OK"), RESPONSE_OK);
         set_default_response (RESPONSE_OK);
diff --git a/gtk2_ardour/mixer.bindings b/gtk2_ardour/mixer.bindings
index 0eb9bfc..62a19ba 100644
--- a/gtk2_ardour/mixer.bindings
+++ b/gtk2_ardour/mixer.bindings
@@ -14,7 +14,7 @@
      <Binding key="Primary-c" action="Mixer/copy-processors"/>
      <Binding key="Primary-v" action="Mixer/paste-processors"/>
      <Binding key="Delete" action="Mixer/delete-processors"/>
-     <Binding key="Backspace" action="Mixer/delete-processors"/>
+     <Binding key="BackSpace" action="Mixer/delete-processors"/>
      <Binding key="Return" action="Mixer/toggle-processors"/>
      <Binding key="Primary-a" action="Mixer/select-all-processors"/>
      <Binding key="Slash" action="Mixer/ab-plugins"/>
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index f3ae79d..5247d89 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -96,6 +96,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session* sess, bool in_mixer)
 	, mute_solo_table (1, 2)
 	, bottom_button_table (1, 3)
 	, meter_point_button (_("pre"))
+	, monitor_section_button (0)
 	, midi_input_enable_button (0)
 	, _comment_button (_("Comments"))
 	, trim_control (ArdourKnob::default_elements, ArdourKnob::Flags (ArdourKnob::Detent | ArdourKnob::ArcToZero))
@@ -126,6 +127,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session* sess, boost::shared_ptr<Route> rt
 	, mute_solo_table (1, 2)
 	, bottom_button_table (1, 3)
 	, meter_point_button (_("pre"))
+	, monitor_section_button (0)
 	, midi_input_enable_button (0)
 	, _comment_button (_("Comments"))
 	, trim_control (ArdourKnob::default_elements, ArdourKnob::Flags (ArdourKnob::Detent | ArdourKnob::ArcToZero))
@@ -491,13 +493,25 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
 	}
 
 	if (route()->is_master()) {
-		mute_solo_table.attach (*mute_button, 0, 2, 0, 1);
 		solo_button->hide ();
 		mute_button->show ();
 		rec_mon_table.hide ();
 		if (solo_iso_table.get_parent()) {
 			solo_iso_table.get_parent()->remove(solo_iso_table);
 		}
+		if (monitor_section_button == 0) {
+			Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
+			_session->MonitorChanged.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::monitor_changed, this), gui_context());
+
+			monitor_section_button = manage (new ArdourButton);
+			monitor_changed ();
+			monitor_section_button->set_related_action (act);
+			set_tooltip (monitor_section_button, _("Show/Hide Monitoring Section"));
+			mute_solo_table.attach (*monitor_section_button, 1, 2, 0, 1);
+			monitor_section_button->show();
+			monitor_section_button->unset_flags (Gtk::CAN_FOCUS);
+		}
+		parameter_changed ("use-monitor-bus");
 	} else {
 		bottom_button_table.attach (group_button, 1, 2, 0, 1);
 		mute_solo_table.attach (*mute_button, 0, 1, 0, 1);
@@ -669,6 +683,7 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
 	gpm.gain_automation_state_button.show();
 
 	parameter_changed ("mixer-element-visibility");
+	map_frozen();
 
 	show ();
 }
@@ -1252,7 +1267,7 @@ MixerStrip::update_io_button (boost::shared_ptr<ARDOUR::Route> route, Width widt
 						<< Gtkmm2ext::markup_escape_text ( pn.empty() ? connection_name : pn );
 				}
 
-				if (connection_name.find("ardour:") == 0) {
+				if (connection_name.find(RouteUI::program_port_prefix) == 0) {
 					if (ardour_track_name.empty()) {
 						// "ardour:Master/in 1" -> "ardour:Master/"
 						string::size_type slash = connection_name.find("/");
@@ -1473,7 +1488,7 @@ MixerStrip::setup_comment_button ()
 	}
 
 	set_tooltip (
-		_comment_button, _route->comment().empty() ? _("Click to Add/Edit Comments") : _route->comment()
+		_comment_button, _route->comment().empty() ? _("Click to add/edit comments") : _route->comment()
 		);
 
 }
@@ -1599,8 +1614,13 @@ MixerStrip::build_route_ops_menu ()
 				selection.set (rtav);
 			}
 
-			items.push_front (SeparatorElem());
-			items.push_front (MenuElem (_("Remove"), sigc::mem_fun(PublicEditor::instance(), &PublicEditor::remove_tracks)));
+			if (!_route->is_master()) {
+				items.push_back (SeparatorElem());
+				items.push_back (MenuElem (_("Duplicate..."), sigc::mem_fun (*this, &RouteUI::duplicate_selected_routes)));
+			}
+	
+			items.push_back (SeparatorElem());
+			items.push_back (MenuElem (_("Remove"), sigc::mem_fun(PublicEditor::instance(), &PublicEditor::remove_tracks)));
 		}
 	}
 }
@@ -1800,6 +1820,8 @@ MixerStrip::map_frozen ()
 			// XXX need some way, maybe, to retoggle redirect editors
 			break;
 		}
+	} else {
+		processor_box.set_sensitive (true);
 	}
 }
 
@@ -1928,6 +1950,18 @@ MixerStrip::meter_point_string (MeterPoint mp)
 	return string();
 }
 
+/** Called when the monitor-section state */
+void
+MixerStrip::monitor_changed ()
+{
+	assert (monitor_section_button);
+	if (_session->monitor_active()) {
+		monitor_section_button->set_name ("master monitor section button active");
+	} else {
+		monitor_section_button->set_name ("master monitor section button normal");
+	}
+}
+
 /** Called when the metering point has changed */
 void
 MixerStrip::meter_changed ()
@@ -2068,6 +2102,9 @@ MixerStrip::set_button_names ()
 		mute_button->set_text (_("Mute"));
 		monitor_input_button->set_text (_("In"));
 		monitor_disk_button->set_text (_("Disk"));
+		if (monitor_section_button) {
+			monitor_section_button->set_text (_("Mon"));
+		}
 
 		if (_route && _route->solo_safe()) {
 			solo_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
@@ -2094,6 +2131,9 @@ MixerStrip::set_button_names ()
 		mute_button->set_text (S_("Mute|M"));
 		monitor_input_button->set_text (S_("MonitorInput|I"));
 		monitor_disk_button->set_text (S_("MonitorDisk|D"));
+		if (monitor_section_button) {
+			monitor_section_button->set_text (S_("Mon|O"));
+		}
 
 		if (_route && _route->solo_safe()) {
 			solo_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
@@ -2191,6 +2231,25 @@ MixerStrip::parameter_changed (string p)
 	else if (p == "track-name-number") {
 		name_changed ();
 	}
+	else if (p == "use-monitor-bus") {
+		if (monitor_section_button) {
+			if (mute_button->get_parent()) {
+				mute_button->get_parent()->remove(*mute_button);
+			}
+			if (monitor_section_button->get_parent()) {
+				monitor_section_button->get_parent()->remove(*monitor_section_button);
+			}
+			if (Config->get_use_monitor_bus ()) {
+				mute_solo_table.attach (*mute_button, 0, 1, 0, 1);
+				mute_solo_table.attach (*monitor_section_button, 1, 2, 0, 1);
+				mute_button->show();
+				monitor_section_button->show();
+			} else {
+				mute_solo_table.attach (*mute_button, 0, 2, 0, 1);
+				mute_button->show();
+			}
+		}
+	}
 }
 
 /** Called to decide whether the solo isolate / solo lock button visibility should
diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h
index 9133d29..f0aebf0 100644
--- a/gtk2_ardour/mixer_strip.h
+++ b/gtk2_ardour/mixer_strip.h
@@ -180,10 +180,13 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
 	ArdourButton                 meter_point_button;
 
 	void meter_changed ();
+	void monitor_changed ();
 
 	ArdourButton input_button;
 	ArdourButton output_button;
 
+	ArdourButton* monitor_section_button;
+
 	void input_button_resized (Gtk::Allocation&);
 	void output_button_resized (Gtk::Allocation&);
 
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index b742382..348b23b 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -37,6 +37,7 @@
 #include <gtkmm2ext/tearoff.h>
 #include <gtkmm2ext/window_title.h>
 
+#include "ardour/amp.h"
 #include "ardour/debug.h"
 #include "ardour/midi_track.h"
 #include "ardour/plugin_manager.h"
@@ -100,6 +101,7 @@ Mixer_UI::Mixer_UI ()
         , _route_deletion_in_progress (false)
 	, _following_editor_selection (false)
 	, _maximised (false)
+	, _show_mixer_list (true)
 {
 	/* allow this window to become the key focus window */
 	set_flags (CAN_FOCUS);
@@ -192,23 +194,48 @@ Mixer_UI::Mixer_UI ()
 	group_display_frame.set_shadow_type (Gtk::SHADOW_IN);
 	group_display_frame.add (group_display_vbox);
 
-	rhs_pane1.pack1 (track_display_frame);
-	rhs_pane1.pack2 (group_display_frame);
-
-	list_vpacker.pack_start (rhs_pane1, true, true);
+	favorite_plugins_model = PluginTreeStore::create (favorite_plugins_columns);
+	favorite_plugins_display.set_model (favorite_plugins_model);
+	favorite_plugins_display.append_column (_("Favorite Plugins"), favorite_plugins_columns.name);
+	favorite_plugins_display.set_name ("EditGroupList");
+	favorite_plugins_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
+	favorite_plugins_display.set_reorderable (false);
+	favorite_plugins_display.set_headers_visible (true);
+	favorite_plugins_display.set_rules_hint (true);
+	favorite_plugins_display.set_can_focus (false);
+	favorite_plugins_display.add_object_drag (favorite_plugins_columns.plugin.index(), "PluginPresetPtr");
+	favorite_plugins_display.set_drag_column (favorite_plugins_columns.name.index());
+	favorite_plugins_display.signal_row_activated().connect (sigc::mem_fun (*this, &Mixer_UI::plugin_row_activated));
+	favorite_plugins_display.signal_button_press_event().connect (sigc::mem_fun (*this, &Mixer_UI::plugin_row_button_press), false);
+	favorite_plugins_display.signal_drop.connect (sigc::mem_fun (*this, &Mixer_UI::plugin_drop));
+	favorite_plugins_display.signal_row_expanded().connect (sigc::mem_fun (*this, &Mixer_UI::save_favorite_ui_state));
+	favorite_plugins_display.signal_row_collapsed().connect (sigc::mem_fun (*this, &Mixer_UI::save_favorite_ui_state));
+	favorite_plugins_model->signal_row_has_child_toggled().connect (sigc::mem_fun (*this, &Mixer_UI::sync_treeview_favorite_ui_state));
+
+	favorite_plugins_scroller.add (favorite_plugins_display);
+	favorite_plugins_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+
+	favorite_plugins_frame.set_name ("BaseFrame");
+	favorite_plugins_frame.set_shadow_type (Gtk::SHADOW_IN);
+	favorite_plugins_frame.add (favorite_plugins_scroller);
+
+	rhs_pane1.pack1 (favorite_plugins_frame, false, true);
+	rhs_pane1.pack2 (track_display_frame);
+	rhs_pane2.pack1 (rhs_pane1);
+	rhs_pane2.pack2 (group_display_frame);
+
+	list_vpacker.pack_start (rhs_pane2, true, true);
 
 	global_hpacker.pack_start (scroller, true, true);
-#ifdef GTKOSX
-	/* current gtk-quartz has dirty updates on borders like this one */
 	global_hpacker.pack_start (out_packer, false, false, 0);
-#else
-	global_hpacker.pack_start (out_packer, false, false, 12);
-#endif
-	list_hpane.pack1(list_vpacker, false, false);
+
+	list_hpane.pack1(list_vpacker, false, true);
 	list_hpane.pack2(global_hpacker, true, false);
 
 	rhs_pane1.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::pane_allocation_handler),
 							static_cast<Gtk::Paned*> (&rhs_pane1)));
+	rhs_pane2.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::pane_allocation_handler),
+							static_cast<Gtk::Paned*> (&rhs_pane2)));
 	list_hpane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::pane_allocation_handler),
 							 static_cast<Gtk::Paned*> (&list_hpane)));
 
@@ -240,24 +267,34 @@ Mixer_UI::Mixer_UI ()
 	group_display_button_label.show();
 	group_display_button.show();
 	group_display_scroller.show();
+	favorite_plugins_scroller.show();
 	group_display_vbox.show();
 	group_display_frame.show();
+	favorite_plugins_frame.show();
 	rhs_pane1.show();
+	rhs_pane2.show();
 	strip_packer.show();
 	out_packer.show();
 	list_hpane.show();
 	group_display.show();
+	favorite_plugins_display.show();
 
 	MixerStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_strip, this, _1), gui_context());
 
 #ifndef DEFER_PLUGIN_SELECTOR_LOAD
 	_plugin_selector = new PluginSelector (PluginManager::instance ());
+#else
+#error implement deferred Plugin-Favorite list
 #endif
+	PluginManager::instance ().PluginListChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::refill_favorite_plugins, this), gui_context());
+	PluginManager::instance ().PluginStatusesChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::refill_favorite_plugins, this), gui_context());
+	ARDOUR::Plugin::PresetsChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::refill_favorite_plugins, this), gui_context());
 }
 
 Mixer_UI::~Mixer_UI ()
 {
 	if (_monitor_section) {
+		monitor_section_detached ();
 		delete _monitor_section;
 	}
 	delete _plugin_selector;
@@ -363,6 +400,11 @@ Mixer_UI::add_strips (RouteList& routes)
 				_monitor_section->set_session (_session);
 				_monitor_section->tearoff().show_all ();
 
+				_monitor_section->tearoff().Detach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_detached));
+				_monitor_section->tearoff().Attach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_attached));
+
+				monitor_section_attached ();
+
 				route->DropReferences.connect (*this, invalidator(*this), boost::bind (&Mixer_UI::monitor_section_going_away, this), gui_context());
 
 				/* no regular strip shown for control out */
@@ -760,6 +802,8 @@ Mixer_UI::set_session (Session* sess)
 		return;
 	}
 
+	refill_favorite_plugins();
+
 	XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
 	set_state (*node);
 
@@ -782,7 +826,6 @@ Mixer_UI::set_session (Session* sess)
 	if (_visible) {
 		show_window();
 	}
-
 	start_updating ();
 }
 
@@ -802,9 +845,11 @@ Mixer_UI::session_going_away ()
 		delete (*i);
 	}
 
-        if (_monitor_section) {
-                _monitor_section->tearoff().hide_visible ();
-        }
+	if (_monitor_section) {
+		_monitor_section->tearoff().hide_visible ();
+	}
+
+	monitor_section_detached ();
 
 	strips.clear ();
 
@@ -1430,6 +1475,40 @@ Mixer_UI::route_group_property_changed (RouteGroup* group, const PropertyChange&
 }
 
 void
+Mixer_UI::show_mixer_list (bool yn)
+{
+	if (yn) {
+		list_vpacker.show ();
+		
+		//if user wants to show the pane, we should make sure that it is wide enough to be visible 
+		int width = list_hpane.get_position();
+		if (width < 40)
+			list_hpane.set_position(40);
+	} else {
+		list_vpacker.hide ();
+	}
+	
+	_show_mixer_list = yn;
+}
+
+void
+Mixer_UI::show_monitor_section (bool yn)
+{
+	if (!monitor_section()) {
+		return;
+	}
+	if (monitor_section()->tearoff().torn_off()) {
+		return;
+	}
+
+	if (yn) {
+		monitor_section()->tearoff().show();
+	} else {
+		monitor_section()->tearoff().hide();
+	}
+}
+
+void
 Mixer_UI::route_group_name_edit (const std::string& path, const std::string& new_text)
 {
 	RouteGroup* group;
@@ -1561,13 +1640,35 @@ Mixer_UI::set_window_pos_and_size ()
 	move (m_root_x, m_root_y);
 }
 
-	void
+void
 Mixer_UI::get_window_pos_and_size ()
 {
 	get_position(m_root_x, m_root_y);
 	get_size(m_width, m_height);
 }
 
+struct PluginStateSorter {
+public:
+	bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
+		std::list<std::string>::const_iterator aiter = std::find(_user.begin(), _user.end(), (*a).unique_id);
+		std::list<std::string>::const_iterator biter = std::find(_user.begin(), _user.end(), (*b).unique_id);
+		if (aiter != _user.end() && biter != _user.end()) {
+			return std::distance (_user.begin(), aiter)  < std::distance (_user.begin(), biter);
+		}
+		if (aiter != _user.end()) {
+			return true;
+		}
+		if (biter != _user.end()) {
+			return false;
+		}
+		return ARDOUR::cmp_nocase((*a).name, (*b).name) == -1;
+	}
+
+	PluginStateSorter(std::list<std::string> user) : _user (user)  {}
+private:
+	std::list<std::string> _user;
+};
+
 int
 Mixer_UI::set_state (const XMLNode& node)
 {
@@ -1639,6 +1740,37 @@ Mixer_UI::set_state (const XMLNode& node)
 		}
 	}
 
+	if ((prop = node.property ("show-mixer-list"))) {
+		bool yn = string_is_affirmative (prop->value());
+		Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMixerList"));
+		assert (act);
+		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+
+		/* do it twice to force the change */
+		tact->set_active (!yn);
+		tact->set_active (yn);
+	}
+
+
+	XMLNode* plugin_order;
+	if ((plugin_order = find_named_node (node, "PluginOrder")) != 0) {
+		store_current_favorite_order ();
+		std::list<string> order;
+		const XMLNodeList& kids = plugin_order->children("PluginInfo");
+		XMLNodeConstIterator i;
+		for (i = kids.begin(); i != kids.end(); ++i) {
+			if ((prop = (*i)->property ("unique-id"))) {
+				std::string unique_id = prop->value();
+				order.push_back (unique_id);
+				if ((prop = (*i)->property ("expanded"))) {
+					favorite_ui_state[unique_id] = string_is_affirmative (prop->value());
+				}
+			}
+		}
+		PluginStateSorter cmp (order);
+		favorite_order.sort (cmp);
+		sync_treeview_from_favorite_order ();
+	}
 
 	return 0;
 }
@@ -1672,6 +1804,8 @@ Mixer_UI::get_state (void)
 
 		snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&rhs_pane1)->gobj()));
 		geometry->add_property(X_("mixer_rhs_pane1_pos"), string(buf));
+		snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&rhs_pane2)->gobj()));
+		geometry->add_property(X_("mixer_rhs_pane2_pos"), string(buf));
 		snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&list_hpane)->gobj()));
 		geometry->add_property(X_("mixer_list_hpane_pos"), string(buf));
 
@@ -1682,8 +1816,24 @@ Mixer_UI::get_state (void)
 
 	node->add_property ("show-mixer", _visible ? "yes" : "no");
 
+	node->add_property ("show-mixer-list", _show_mixer_list ? "yes" : "no");
+
 	node->add_property ("maximised", _maximised ? "yes" : "no");
 
+	store_current_favorite_order ();
+	XMLNode* plugin_order = new XMLNode ("PluginOrder");
+	int cnt = 0;
+	for (PluginInfoList::const_iterator i = favorite_order.begin(); i != favorite_order.end(); ++i, ++cnt) {
+			XMLNode* p = new XMLNode ("PluginInfo");
+			p->add_property ("sort", cnt);
+			p->add_property ("unique-id", (*i)->unique_id);
+			if (favorite_ui_state.find ((*i)->unique_id) != favorite_ui_state.end ()) {
+				p->add_property ("expanded", favorite_ui_state[(*i)->unique_id]);
+			}
+			plugin_order->add_child_nocopy (*p);
+		;
+	}
+	node->add_child_nocopy (*plugin_order);
 	return *node;
 }
 
@@ -1693,7 +1843,6 @@ Mixer_UI::pane_allocation_handler (Allocation&, Gtk::Paned* which)
 {
 	int pos;
 	XMLProperty* prop = 0;
-	char buf[32];
 	XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
 	XMLNode* geometry;
 	int height;
@@ -1719,7 +1868,6 @@ Mixer_UI::pane_allocation_handler (Allocation&, Gtk::Paned* which)
 
 		if (!geometry || (prop = geometry->property("mixer-rhs-pane1-pos")) == 0) {
 			pos = height / 3;
-			snprintf (buf, sizeof(buf), "%d", pos);
 		} else {
 			pos = atoi (prop->value());
 		}
@@ -1728,6 +1876,20 @@ Mixer_UI::pane_allocation_handler (Allocation&, Gtk::Paned* which)
 			rhs_pane1.set_position (pos);
 		}
 
+	} else if (which == static_cast<Gtk::Paned*> (&rhs_pane2)) {
+		if (done[1]) {
+			return;
+		}
+
+		if (!geometry || (prop = geometry->property("mixer-rhs-pane2-pos")) == 0) {
+			pos = 2 * height / 3;
+		} else {
+			pos = atoi (prop->value());
+		}
+
+		if ((done[1] = GTK_WIDGET(rhs_pane2.gobj())->allocation.height > pos)) {
+			rhs_pane2.set_position (pos);
+		}
 	} else if (which == static_cast<Gtk::Paned*> (&list_hpane)) {
 
 		if (done[2]) {
@@ -1735,10 +1897,9 @@ Mixer_UI::pane_allocation_handler (Allocation&, Gtk::Paned* which)
 		}
 
 		if (!geometry || (prop = geometry->property("mixer-list-hpane-pos")) == 0) {
-			pos = 75;
-			snprintf (buf, sizeof(buf), "%d", pos);
+			pos = std::max ((float)100, rintf ((float) 125 * UIConfiguration::instance().get_ui_scale()));
 		} else {
-			pos = atoi (prop->value());
+			pos = max (36, atoi (prop->value ()));
 		}
 
 		if ((done[2] = GTK_WIDGET(list_hpane.gobj())->allocation.width > pos)) {
@@ -1849,6 +2010,10 @@ Mixer_UI::parameter_changed (string const & p)
 		}
 	} else if (p == "remote-model") {
 		reset_remote_control_ids ();
+	} else if (p == "use-monitor-bus") {
+		if (!_session->monitor_out()) {
+			monitor_section_detached ();
+		}
 	}
 }
 
@@ -1994,8 +2159,11 @@ void
 Mixer_UI::monitor_section_going_away ()
 {
 	if (_monitor_section) {
+		monitor_section_detached ();
 		out_packer.remove (_monitor_section->tearoff());
 		_monitor_section->set_session (0);
+		delete _monitor_section;
+		_monitor_section = 0;
 	}
 }
 
@@ -2042,3 +2210,367 @@ Mixer_UI::restore_mixer_space ()
 
 	_maximised = false;
 }
+
+void
+Mixer_UI::monitor_section_attached ()
+{
+	Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
+	Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+	act->set_sensitive (true);
+	tact->set_active ();
+}
+
+void
+Mixer_UI::monitor_section_detached ()
+{
+	Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
+	act->set_sensitive (false);
+}
+
+void
+Mixer_UI::store_current_favorite_order ()
+{
+	typedef Gtk::TreeModel::Children type_children;
+	type_children children = favorite_plugins_model->children();
+	favorite_order.clear();
+	for(type_children::iterator iter = children.begin(); iter != children.end(); ++iter)
+	{
+		Gtk::TreeModel::Row row = *iter;
+		ARDOUR::PluginPresetPtr ppp = row[favorite_plugins_columns.plugin];
+		favorite_order.push_back (ppp->_pip);
+		std::string name = row[favorite_plugins_columns.name];
+		favorite_ui_state[(*ppp->_pip).unique_id] = favorite_plugins_display.row_expanded (favorite_plugins_model->get_path(iter));
+	}
+}
+
+void
+Mixer_UI::save_favorite_ui_state (const TreeModel::iterator& iter, const TreeModel::Path& path)
+{
+	Gtk::TreeModel::Row row = *iter;
+	ARDOUR::PluginPresetPtr ppp = row[favorite_plugins_columns.plugin];
+	assert (ppp);
+	favorite_ui_state[(*ppp->_pip).unique_id] = favorite_plugins_display.row_expanded (favorite_plugins_model->get_path(iter));
+}
+
+void
+Mixer_UI::refiller (PluginInfoList& result, const PluginInfoList& plugs)
+{
+	PluginManager& manager (PluginManager::instance());
+	for (PluginInfoList::const_iterator i = plugs.begin(); i != plugs.end(); ++i) {
+		if (manager.get_status (*i) != PluginManager::Favorite) {
+			continue;
+		}
+		result.push_back (*i);
+	}
+}
+
+struct PluginCustomSorter {
+public:
+	bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
+		PluginInfoList::const_iterator aiter = _user.begin();
+		PluginInfoList::const_iterator biter = _user.begin();
+		while (aiter != _user.end()) { if ((*aiter)->unique_id == a->unique_id) { break; } ++aiter; }
+		while (biter != _user.end()) { if ((*biter)->unique_id == b->unique_id) { break; } ++biter; }
+
+		if (aiter != _user.end() && biter != _user.end()) {
+			return std::distance (_user.begin(), aiter) < std::distance (_user.begin(), biter);
+		}
+		if (aiter != _user.end()) {
+			return true;
+		}
+		if (biter != _user.end()) {
+			return false;
+		}
+		return ARDOUR::cmp_nocase((*a).name, (*b).name) == -1;
+	}
+	PluginCustomSorter(PluginInfoList user) : _user (user)  {}
+private:
+	PluginInfoList _user;
+};
+
+void
+Mixer_UI::refill_favorite_plugins ()
+{
+	PluginInfoList plugs;
+	PluginManager& mgr (PluginManager::instance());
+
+#ifdef LV2_SUPPORT
+	refiller (plugs, mgr.lv2_plugin_info ());
+#endif
+#ifdef WINDOWS_VST_SUPPORT
+	refiller (plugs, mgr.windows_vst_plugin_info ());
+#endif
+#ifdef LXVST_SUPPORT
+	refiller (plugs, mgr.lxvst_plugin_info ());
+#endif
+#ifdef AUDIOUNIT_SUPPORT
+	refiller (plugs, mgr.au_plugin_info ());
+#endif
+	refiller (plugs, mgr.ladspa_plugin_info ());
+
+	store_current_favorite_order ();
+
+	PluginCustomSorter cmp (favorite_order);
+	plugs.sort (cmp);
+
+	favorite_order = plugs;
+
+	sync_treeview_from_favorite_order ();
+}
+
+void
+Mixer_UI::sync_treeview_favorite_ui_state (const TreeModel::Path& path, const TreeModel::iterator&)
+{
+	TreeIter iter;
+	if (!(iter = favorite_plugins_model->get_iter (path))) {
+		return;
+	}
+	ARDOUR::PluginPresetPtr ppp = (*iter)[favorite_plugins_columns.plugin];
+	if (!ppp) {
+		return;
+	}
+	PluginInfoPtr pip = ppp->_pip;
+	if (favorite_ui_state.find (pip->unique_id) != favorite_ui_state.end ()) {
+		if (favorite_ui_state[pip->unique_id]) {
+			favorite_plugins_display.expand_row (path, true);
+		}
+	}
+}
+
+void
+Mixer_UI::sync_treeview_from_favorite_order ()
+{
+	favorite_plugins_model->clear ();
+	for (PluginInfoList::const_iterator i = favorite_order.begin(); i != favorite_order.end(); ++i) {
+		PluginInfoPtr pip = (*i);
+
+		TreeModel::Row newrow = *(favorite_plugins_model->append());
+		newrow[favorite_plugins_columns.name] = (*i)->name;
+		newrow[favorite_plugins_columns.plugin] = PluginPresetPtr (new PluginPreset(pip));
+		if (!_session) {
+			continue;
+		}
+
+		vector<ARDOUR::Plugin::PresetRecord> presets = (*i)->get_presets (true);
+		for (vector<ARDOUR::Plugin::PresetRecord>::const_iterator j = presets.begin(); j != presets.end(); ++j) {
+			Gtk::TreeModel::Row child_row = *(favorite_plugins_model->append (newrow.children()));
+			child_row[favorite_plugins_columns.name] = (*j).label;
+			child_row[favorite_plugins_columns.plugin] = PluginPresetPtr (new PluginPreset(pip, &(*j)));
+		}
+		if (favorite_ui_state.find (pip->unique_id) != favorite_ui_state.end ()) {
+			if (favorite_ui_state[pip->unique_id]) {
+				favorite_plugins_display.expand_row (favorite_plugins_model->get_path(newrow), true);
+			}
+		}
+	}
+}
+
+void
+Mixer_UI::popup_note_context_menu (GdkEventButton *ev)
+{
+	using namespace Gtk::Menu_Helpers;
+
+	Gtk::Menu* m = manage (new Menu);
+	MenuList& items = m->items ();
+
+	if (_selection.routes.empty()) {
+		items.push_back (MenuElem (_("No Track/Bus is selected.")));
+	} else {
+		items.push_back (MenuElem (_("Add at the top"),
+					sigc::bind (sigc::mem_fun (*this, &Mixer_UI::add_selected_processor), AddTop)));
+		items.push_back (MenuElem (_("Add Pre-Fader"),
+					sigc::bind (sigc::mem_fun (*this, &Mixer_UI::add_selected_processor), AddPreFader)));
+		items.push_back (MenuElem (_("Add Post-Fader"),
+					sigc::bind (sigc::mem_fun (*this, &Mixer_UI::add_selected_processor), AddPostFader)));
+		items.push_back (MenuElem (_("Add at the end"),
+					sigc::bind (sigc::mem_fun (*this, &Mixer_UI::add_selected_processor), AddBottom)));
+	}
+
+	items.push_back (SeparatorElem());
+
+	items.push_back (MenuElem (_("Remove from favorites"), sigc::mem_fun (*this, &Mixer_UI::remove_selected_from_favorites)));
+
+	ARDOUR::PluginPresetPtr ppp = selected_plugin();
+	if (ppp && ppp->_preset.valid && ppp->_preset.user) {
+		items.push_back (MenuElem (_("Delete Preset"), sigc::mem_fun (*this, &Mixer_UI::delete_selected_preset)));
+	}
+
+	m->popup (ev->button, ev->time);
+}
+
+bool
+Mixer_UI::plugin_row_button_press (GdkEventButton *ev)
+{
+	if ((ev->type == GDK_BUTTON_PRESS) && (ev->button == 3) ) {
+		TreeModel::Path path;
+		TreeViewColumn* column;
+		int cellx, celly;
+		if (favorite_plugins_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
+			Glib::RefPtr<Gtk::TreeView::Selection> selection = favorite_plugins_display.get_selection();
+			if (selection) {
+				selection->unselect_all();
+				selection->select(path);
+			}
+		}
+		ARDOUR::PluginPresetPtr ppp = selected_plugin();
+		if (ppp) {
+			popup_note_context_menu (ev);
+		}
+	}
+	return false;
+}
+
+
+PluginPresetPtr
+Mixer_UI::selected_plugin ()
+{
+	Glib::RefPtr<Gtk::TreeView::Selection> selection = favorite_plugins_display.get_selection();
+	if (!selection) {
+		return PluginPresetPtr();
+	}
+	Gtk::TreeModel::iterator iter = selection->get_selected();
+	if (!iter) {
+		return PluginPresetPtr();
+	}
+	return (*iter)[favorite_plugins_columns.plugin];
+}
+
+void
+Mixer_UI::add_selected_processor (ProcessorPosition pos)
+{
+	ARDOUR::PluginPresetPtr ppp = selected_plugin();
+	if (ppp) {
+		add_favorite_processor (ppp, pos);
+	}
+}
+
+void
+Mixer_UI::delete_selected_preset ()
+{
+	if (!_session) {
+		return;
+	}
+	ARDOUR::PluginPresetPtr ppp = selected_plugin();
+	if (!ppp || !ppp->_preset.valid || !ppp->_preset.user) {
+		return;
+	}
+	PluginPtr plugin = ppp->_pip->load (*_session);
+	plugin->get_presets();
+	plugin->remove_preset (ppp->_preset.label);
+}
+
+void
+Mixer_UI::remove_selected_from_favorites ()
+{
+	ARDOUR::PluginPresetPtr ppp = selected_plugin();
+	if (!ppp) {
+		return;
+	}
+	PluginManager::PluginStatusType status = PluginManager::Normal;
+	PluginManager& manager (PluginManager::instance());
+
+	manager.set_status (ppp->_pip->type, ppp->_pip->unique_id, status);
+	manager.save_statuses ();
+}
+
+void
+Mixer_UI::plugin_row_activated (const TreeModel::Path& path, TreeViewColumn* column)
+{
+	TreeIter iter;
+	if (!(iter = favorite_plugins_model->get_iter (path))) {
+		return;
+	}
+	ARDOUR::PluginPresetPtr ppp = (*iter)[favorite_plugins_columns.plugin];
+	add_favorite_processor (ppp, AddPreFader); // TODO: preference?!
+}
+
+void
+Mixer_UI::add_favorite_processor (ARDOUR::PluginPresetPtr ppp, ProcessorPosition pos)
+{
+	if (!_session || _selection.routes.empty()) {
+		return;
+	}
+
+	PluginInfoPtr pip = ppp->_pip;
+	for (RouteUISelection::iterator i = _selection.routes.begin(); i != _selection.routes.end(); ++i) {
+		boost::shared_ptr<ARDOUR::Route> rt = (*i)->route();
+		if (!rt) { continue; }
+
+		PluginPtr p = pip->load (*_session);
+		if (!p) { continue; }
+
+		if (ppp->_preset.valid) {
+			p->load_preset (ppp->_preset);
+		}
+
+		Route::ProcessorStreams err;
+		boost::shared_ptr<Processor> processor (new PluginInsert (*_session, p));
+
+		switch (pos) {
+			case AddTop:
+				rt->add_processor_by_index (processor, 0, &err, Config->get_new_plugins_active ());
+				break;
+			case AddPreFader:
+				rt->add_processor (processor, PreFader, &err, Config->get_new_plugins_active ());
+				break;
+			case AddPostFader:
+				{
+					int idx = 0;
+					for (;;++idx) {
+						boost::shared_ptr<Processor> np = rt->nth_processor (idx);
+						if (!np || boost::dynamic_pointer_cast<Amp> (np)) {
+							break;
+						}
+					}
+					rt->add_processor_by_index (processor, ++idx, &err, Config->get_new_plugins_active ());
+				}
+				break;
+			case AddBottom:
+				rt->add_processor_by_index (processor, -1, &err, Config->get_new_plugins_active ());
+				break;
+		}
+	}
+}
+
+bool
+PluginTreeStore::row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& data) const
+{
+	if (data.get_target() != "GTK_TREE_MODEL_ROW") {
+		return false;
+	}
+
+	// only allow to re-order top-level items
+	TreePath src;
+	if (TreePath::get_from_selection_data (data, src)) {
+		if (src.up() && src.up()) {
+			return false;
+		}
+	}
+
+	// don't allow to drop as child-rows.
+	Gtk::TreeModel::Path _dest = dest; // un const
+	const bool is_child = _dest.up (); // explicit bool for clang
+	if (!is_child || _dest.empty ()) {
+		return true;
+	}
+	return false;
+}
+
+void
+Mixer_UI::plugin_drop (const Glib::RefPtr<Gdk::DragContext>&, const Gtk::SelectionData& data)
+{
+	if (data.get_target() != "PluginPresetPtr") {
+		return;
+	}
+	if (data.get_length() != sizeof (PluginPresetPtr)) {
+		return;
+	}
+	const void *d = data.get_data();
+	const PluginPresetPtr ppp = *(static_cast<const PluginPresetPtr*> (d));
+
+	PluginManager::PluginStatusType status = PluginManager::Favorite;
+	PluginManager& manager (PluginManager::instance());
+
+	manager.set_status (ppp->_pip->type, ppp->_pip->unique_id, status);
+	manager.save_statuses ();
+}
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index a982546..a909228 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -39,8 +39,12 @@
 #include "ardour/ardour.h"
 #include "ardour/types.h"
 #include "ardour/session_handle.h"
+#include "ardour/plugin.h"
+#include "ardour/plugin_manager.h"
 
 #include "gtkmm2ext/visibility_tracker.h"
+#include "gtkmm2ext/dndtreeview.h"
+#include "gtkmm2ext/treeutils.h"
 
 #include "enums.h"
 #include "mixer_actor.h"
@@ -55,6 +59,19 @@ class PluginSelector;
 class MixerGroupTabs;
 class MonitorSection;
 
+class PluginTreeStore : public Gtk::TreeStore
+{
+public:
+	static Glib::RefPtr<PluginTreeStore> create(const Gtk::TreeModelColumnRecord& columns) {
+		return Glib::RefPtr<PluginTreeStore> (new PluginTreeStore (columns));
+	}
+
+protected:
+	PluginTreeStore (const Gtk::TreeModelColumnRecord& columns) : Gtk::TreeStore (columns) {}
+	virtual bool row_draggable_vfunc (const Gtk::TreeModel::Path&) const { return true; }
+	virtual bool row_drop_possible_vfunc (const Gtk::TreeModel::Path&, const Gtk::SelectionData&) const;
+};
+
 class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor, public Gtkmm2ext::VisibilityTracker
 {
   public:
@@ -75,6 +92,9 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
 	XMLNode& get_state (void);
 	int set_state (const XMLNode& );
 
+	void show_mixer_list (bool yn);
+	void show_monitor_section (bool);
+	
 	void show_window ();
 	bool hide_window (GdkEventAny *ev);
 	void show_strip (MixerStrip *);
@@ -112,10 +132,13 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
 	Gtk::Button				group_display_button;
 	Gtk::ScrolledWindow		track_display_scroller;
 	Gtk::ScrolledWindow		group_display_scroller;
+	Gtk::ScrolledWindow		favorite_plugins_scroller;
 	Gtk::VBox				group_display_vbox;
 	Gtk::Frame				track_display_frame;
 	Gtk::Frame				group_display_frame;
+	Gtk::Frame				favorite_plugins_frame;
 	Gtk::VPaned				rhs_pane1;
+	Gtk::VPaned				rhs_pane2;
 	Gtk::HBox				strip_packer;
 	Gtk::HBox				out_packer;
 	Gtk::HPaned				list_hpane;
@@ -175,6 +198,24 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
 	void track_list_delete (const Gtk::TreeModel::Path&);
 	void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order);
 
+	void plugin_row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
+	bool plugin_row_button_press (GdkEventButton*);
+	void popup_note_context_menu (GdkEventButton*);
+	void plugin_drop (const Glib::RefPtr<Gdk::DragContext>&, const Gtk::SelectionData& data);
+
+	enum ProcessorPosition {
+		AddTop,
+		AddPreFader,
+		AddPostFader,
+		AddBottom
+	};
+
+	void add_selected_processor (ProcessorPosition);
+	void add_favorite_processor (ARDOUR::PluginPresetPtr, ProcessorPosition);
+	void remove_selected_from_favorites ();
+	void delete_selected_preset ();
+	ARDOUR::PluginPresetPtr selected_plugin ();
+
 	void initial_track_display ();
 	void show_track_list_menu ();
 
@@ -243,14 +284,29 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
 	    Gtk::TreeModelColumn<ARDOUR::RouteGroup*>	group;
 	};
 
+	struct PluginsDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
+	    PluginsDisplayModelColumns() {
+		    add (name);
+		    add (plugin);
+	    }
+	    Gtk::TreeModelColumn<std::string> name;
+			Gtk::TreeModelColumn<ARDOUR::PluginPresetPtr> plugin;
+	};
+
+	ARDOUR::PluginInfoList favorite_order;
+	std::map<std::string, bool> favorite_ui_state;
+
 	TrackDisplayModelColumns    track_columns;
 	GroupDisplayModelColumns    group_columns;
+	PluginsDisplayModelColumns  favorite_plugins_columns;
 
 	Gtk::TreeView track_display;
 	Gtk::TreeView group_display;
+	Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr> favorite_plugins_display;
 
 	Glib::RefPtr<Gtk::ListStore> track_model;
 	Glib::RefPtr<Gtk::ListStore> group_model;
+	Glib::RefPtr<PluginTreeStore> favorite_plugins_model;
 
 	bool group_display_button_press (GdkEventButton*);
 	void group_display_selection_changed ();
@@ -291,8 +347,21 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
 
 	void monitor_section_going_away ();
 
+	void monitor_section_attached ();
+	void monitor_section_detached ();
+
+	void store_current_favorite_order();
+	void refiller (ARDOUR::PluginInfoList& result, const ARDOUR::PluginInfoList& plugs);
+	void refill_favorite_plugins ();
+	void sync_treeview_from_favorite_order ();
+	void sync_treeview_favorite_ui_state (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&);
+	void save_favorite_ui_state (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path);
+
 	/// true if we are in fullscreen mode
 	bool _maximised;
+
+	// true if mixer list is visible
+	bool _show_mixer_list;
 };
 
 #endif /* __ardour_mixer_ui_h__ */
diff --git a/gtk2_ardour/monitor_section.cc b/gtk2_ardour/monitor_section.cc
index f246871..0741bff 100644
--- a/gtk2_ardour/monitor_section.cc
+++ b/gtk2_ardour/monitor_section.cc
@@ -32,11 +32,13 @@
 #include <gtkmm/menu.h>
 #include <gtkmm/menuitem.h>
 
+#include "ardour/amp.h"
 #include "ardour/audioengine.h"
 #include "ardour/monitor_processor.h"
 #include "ardour/port.h"
 #include "ardour/route.h"
 #include "ardour/user_bundle.h"
+#include "ardour/plugin_manager.h"
 
 #include "gui_thread.h"
 #include "monitor_section.h"
@@ -80,7 +82,9 @@ MonitorSection::MonitorSection (Session* s)
 	, pfl_button (_("PFL"), ArdourButton::led_default_elements)
 	, exclusive_solo_button (ArdourButton::led_default_elements)
 	, solo_mute_override_button (ArdourButton::led_default_elements)
+	, toggle_processorbox_button (ArdourButton::default_elements)
 	, _inhibit_solo_model_update (false)
+	, _ui_initialized (false)
 {
 
 	using namespace Menu_Helpers;
@@ -88,20 +92,20 @@ MonitorSection::MonitorSection (Session* s)
 	Glib::RefPtr<Action> act;
 
 	if (!monitor_actions) {
-
-		/* do some static stuff */
-
 		register_actions ();
-
+	} else {
+		connect_actions ();
 	}
 
-	set_session (s);
-
-	VBox* spin_packer;
-	Label* spin_label;
+	_plugin_selector = new PluginSelector (PluginManager::instance());
+	insert_box = new ProcessorBox (_session, boost::bind (&MonitorSection::plugin_selector, this), _rr_selection, 0);
+	insert_box->set_no_show_all ();
+	insert_box->show ();
+	// TODO allow keyboard shortcuts in ProcessorBox
 
-	/* Rude Solo */
+	set_session (s);
 
+	/* Rude Solo  & Solo Isolated */
 	rude_solo_button.set_text (_("Soloing"));
 	rude_solo_button.set_name ("rude solo");
 	rude_solo_button.show ();
@@ -114,7 +118,7 @@ MonitorSection::MonitorSection (Session* s)
 	rude_audition_button.set_name ("rude audition");
 	rude_audition_button.show ();
 
-        Timers::blink_connect (sigc::mem_fun (*this, &MonitorSection::do_blink));
+	Timers::blink_connect (sigc::mem_fun (*this, &MonitorSection::do_blink));
 
 	act = ActionManager::get_action (X_("Main"), X_("cancel-solo"));
 	rude_solo_button.set_related_action (act);
@@ -126,19 +130,19 @@ MonitorSection::MonitorSection (Session* s)
 	rude_audition_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_audition), false);
 	UI::instance()->set_tip (rude_audition_button, _("When active, auditioning is active.\nClick to stop the audition"));
 
+	/* SIP, AFL, PFL radio */
+
 	solo_in_place_button.set_name ("monitor section solo model");
 	afl_button.set_name ("monitor section solo model");
 	pfl_button.set_name ("monitor section solo model");
 
-	solo_model_box.set_spacing (6);
-	solo_model_box.pack_start (solo_in_place_button, true, false);
-	solo_model_box.pack_start (afl_button, true, false);
-	solo_model_box.pack_start (pfl_button, true, false);
+	solo_in_place_button.set_led_left (true);
+	afl_button.set_led_left (true);
+	pfl_button.set_led_left (true);
 
 	solo_in_place_button.show ();
 	afl_button.show ();
 	pfl_button.show ();
-	solo_model_box.show ();
 
 	act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
 	set_tooltip (solo_in_place_button, _("Solo controls affect solo-in-place"));
@@ -158,131 +162,94 @@ MonitorSection::MonitorSection (Session* s)
 		pfl_button.set_related_action (act);
 	}
 
-	/* Solo Boost */
+	/* Solo option buttons */
+	exclusive_solo_button.set_text (_("Excl. Solo"));
+	exclusive_solo_button.set_name (X_("monitor section solo option"));
+	set_tooltip (&exclusive_solo_button, _("Exclusive solo means that only 1 solo is active at a time"));
+
+	act = ActionManager::get_action (X_("Monitor"), X_("toggle-exclusive-solo"));
+	if (act) {
+		exclusive_solo_button.set_related_action (act);
+	}
+
+	solo_mute_override_button.set_text (_("Solo » Mute"));
+	solo_mute_override_button.set_name (X_("monitor section solo option"));
+	set_tooltip (&solo_mute_override_button, _("If enabled, solo will override mute\n(a soloed & muted track or bus will be audible)"));
+
+	act = ActionManager::get_action (X_("Monitor"), X_("toggle-mute-overrides-solo"));
+	if (act) {
+		solo_mute_override_button.set_related_action (act);
+	}
+
+	/* Processor Box hide/shos */
+	toggle_processorbox_button.set_text (_("Processors"));
+	toggle_processorbox_button.set_name (X_("monitor section processors toggle"));
+	set_tooltip (&toggle_processorbox_button, _("Allow to add monitor effect processors"));
+
+	proctoggle = ToggleAction::create ();
+	toggle_processorbox_button.set_related_action (proctoggle);
+	proctoggle->signal_toggled().connect (sigc::mem_fun(*this, &MonitorSection::update_processor_box), false);
+
+	/* Knobs */
+	Label* solo_boost_label;
+	Label* solo_cut_label;
+	Label* dim_label;
+
+	/* Solo Boost Knob */
 
 	solo_boost_control = new ArdourKnob ();
-	solo_boost_control->set_name("monitor knob");
-	solo_boost_control->set_size_request (PX_SCALE(40), PX_SCALE(40));
+	solo_boost_control->set_name("monitor section knob");
+	solo_boost_control->set_size_request (PX_SCALE(36), PX_SCALE(36));
 	set_tooltip (*solo_boost_control, _("Gain increase for soloed signals (0dB is normal)"));
 
 	solo_boost_display = new ArdourDisplay ();
-	solo_boost_display->set_name("monitor section cut");
-	solo_boost_display->set_size_request (PX_SCALE(80), PX_SCALE(20));
+	solo_boost_display->set_size_request (PX_SCALE(68), PX_SCALE(20));
 	solo_boost_display->add_controllable_preset(_("0 dB"), 0.0);
 	solo_boost_display->add_controllable_preset(_("3 dB"), 3.0);
 	solo_boost_display->add_controllable_preset(_("6 dB"), 6.0);
 	solo_boost_display->add_controllable_preset(_("10 dB"), 10.0);
 
-	HBox* solo_packer = manage (new HBox);
-	solo_packer->set_spacing (6);
-	solo_packer->show ();
-
-	spin_label = manage (new Label (_("Solo Boost")));
-	spin_packer = manage (new VBox);
-	spin_packer->show ();
-	spin_packer->set_spacing (3);
-	spin_packer->pack_start (*spin_label, false, false);
-	spin_packer->pack_start (*solo_boost_control, false, false);
-	spin_packer->pack_start (*solo_boost_display, false, false);
-
-	solo_packer->pack_start (*spin_packer, true, false);
+	solo_boost_label = manage (new Label (_("Solo Boost")));
 
 	/* Solo (SiP) cut */
 
 	solo_cut_control = new ArdourKnob ();
-	solo_cut_control->set_name ("monitor knob");
-	solo_cut_control->set_size_request (PX_SCALE(40), PX_SCALE(40));
+	solo_cut_control->set_name ("monitor section knob");
+	solo_cut_control->set_size_request (PX_SCALE(36), PX_SCALE(36));
 	set_tooltip (*solo_cut_control, _("Gain reduction non-soloed signals\nA value above -inf dB causes \"solo-in-front\""));
 
 	solo_cut_display = new ArdourDisplay ();
-	solo_cut_display->set_name("monitor section cut");
-	solo_cut_display->set_size_request (PX_SCALE(80), PX_SCALE(20));
+	solo_cut_display->set_name("monitor section dropdown"); // XXX
+	solo_cut_display->set_size_request (PX_SCALE(68), PX_SCALE(20));
 	solo_cut_display->add_controllable_preset(_("0 dB"), 0.0);
 	solo_cut_display->add_controllable_preset(_("-6 dB"), -6.0);
 	solo_cut_display->add_controllable_preset(_("-12 dB"), -12.0);
 	solo_cut_display->add_controllable_preset(_("-20 dB"), -20.0);
 	solo_cut_display->add_controllable_preset(_("OFF"), -1200.0);
 
-	spin_label = manage (new Label (_("SiP Cut")));
-	spin_packer = manage (new VBox);
-	spin_packer->show ();
-	spin_packer->set_spacing (3);
-	spin_packer->pack_start (*spin_label, false, false);
-	spin_packer->pack_start (*solo_cut_control, false, false);
-	spin_packer->pack_start (*solo_cut_display, false, false);
-
-	solo_packer->pack_start (*spin_packer, true, false);
+	solo_cut_label = manage (new Label (_("SiP Cut")));
 
 	/* Dim */
 
 	dim_control = new ArdourKnob (ArdourKnob::default_elements, ArdourKnob::Detent);
-	dim_control->set_name ("monitor knob");
-	dim_control->set_size_request (PX_SCALE(40), PX_SCALE(40));
+	dim_control->set_name ("monitor section knob");
+	dim_control->set_size_request (PX_SCALE(36), PX_SCALE(36));
 	set_tooltip (*dim_control, _("Gain reduction to use when dimming monitor outputs"));
 
 	dim_display = new ArdourDisplay ();
-	dim_display->set_name("monitor section cut");
-	dim_display->set_size_request (PX_SCALE(80), PX_SCALE(20));
+	dim_display->set_size_request (PX_SCALE(68), PX_SCALE(20));
 	dim_display->add_controllable_preset(_("0 dB"), 0.0);
 	dim_display->add_controllable_preset(_("-3 dB"), -3.0);
 	dim_display->add_controllable_preset(_("-6 dB"), -6.0);
 	dim_display->add_controllable_preset(_("-12 dB"), -12.0);
 	dim_display->add_controllable_preset(_("-20 dB"), -20.0);
 
-	HBox* dim_packer = manage (new HBox);
-	dim_packer->show ();
-
-	spin_label = manage (new Label (_("Dim")));
-	spin_packer = manage (new VBox);
-	spin_packer->show ();
-	spin_packer->set_spacing (3);
-	spin_packer->pack_start (*spin_label, false, false);
-	spin_packer->pack_start (*dim_control, false, false);
-	spin_packer->pack_start (*dim_display, false, false);
-
-	dim_packer->pack_start (*spin_packer, true, false);
-
-	exclusive_solo_button.set_text (_("Excl. Solo"));
-	exclusive_solo_button.set_name (X_("monitor solo exclusive"));
-	set_tooltip (&exclusive_solo_button, _("Exclusive solo means that only 1 solo is active at a time"));
-
-	act = ActionManager::get_action (X_("Monitor"), X_("toggle-exclusive-solo"));
-	if (act) {
-		exclusive_solo_button.set_related_action (act);
-	}
-
-	solo_mute_override_button.set_text (_("Solo » Mute"));
-	solo_mute_override_button.set_name (X_("monitor solo override"));
-	set_tooltip (&solo_mute_override_button, _("If enabled, solo will override mute\n(a soloed & muted track or bus will be audible)"));
-
-	act = ActionManager::get_action (X_("Monitor"), X_("toggle-mute-overrides-solo"));
-	if (act) {
-		solo_mute_override_button.set_related_action (act);
-	}
-
-	HBox* solo_opt_box = manage (new HBox);
-	solo_opt_box->set_spacing (12);
-	solo_opt_box->set_homogeneous (true);
-	solo_opt_box->pack_start (exclusive_solo_button);
-	solo_opt_box->pack_start (solo_mute_override_button);
-	solo_opt_box->show ();
-
-	upper_packer.set_spacing (6);
-
-	Gtk::HBox* rude_box = manage (new HBox);
-	rude_box->pack_start (rude_solo_button, true, true);
-	rude_box->pack_start (rude_iso_button, true, true);
-
-	upper_packer.pack_start (*rude_box, false, false);
-	upper_packer.pack_start (rude_audition_button, false, false);
-	upper_packer.pack_start (solo_model_box, false, false, 12);
-	upper_packer.pack_start (*solo_opt_box, false, false);
-	upper_packer.pack_start (*solo_packer, false, false, 12);
+	dim_label = manage (new Label (_("Dim")));
 
+	// mute button
 	cut_all_button.set_text (_("Mute"));
-	cut_all_button.set_name ("monitor section cut");
-	cut_all_button.set_name (X_("monitor section cut"));
-	cut_all_button.set_size_request (-1, PX_SCALE(50));
+	cut_all_button.set_name ("mute button");
+	cut_all_button.set_size_request (-1, PX_SCALE(30));
 	cut_all_button.show ();
 
 	act = ActionManager::get_action (X_("Monitor"), X_("monitor-cut-all"));
@@ -290,39 +257,32 @@ MonitorSection::MonitorSection (Session* s)
 		cut_all_button.set_related_action (act);
 	}
 
+	// dim button
 	dim_all_button.set_text (_("Dim"));
 	dim_all_button.set_name ("monitor section dim");
+	dim_all_button.set_size_request (-1, PX_SCALE(25));
 	act = ActionManager::get_action (X_("Monitor"), X_("monitor-dim-all"));
 	if (act) {
 		dim_all_button.set_related_action (act);
 	}
 
+	// mono button
 	mono_button.set_text (_("Mono"));
 	mono_button.set_name ("monitor section mono");
+	mono_button.set_size_request (-1, PX_SCALE(25));
 	act = ActionManager::get_action (X_("Monitor"), X_("monitor-mono"));
 	if (act) {
 		mono_button.set_related_action (act);
 	}
 
-	HBox* bbox = manage (new HBox);
-
-	bbox->set_spacing (12);
-	bbox->pack_start (mono_button, true, true);
-	bbox->pack_start (dim_all_button, true, true);
-
-	lower_packer.set_spacing (12);
-	lower_packer.pack_start (*bbox, false, false);
-	lower_packer.pack_start (cut_all_button, false, false);
-
 	/* Gain */
 
 	gain_control = new ArdourKnob (ArdourKnob::default_elements, ArdourKnob::Detent);
-	gain_control->set_name("monitor knob");
-	gain_control->set_size_request (PX_SCALE(80), PX_SCALE(80));
+	gain_control->set_name("monitor section knob");
+	gain_control->set_size_request (PX_SCALE(60), PX_SCALE(60));
 
 	gain_display = new ArdourDisplay ();
-	gain_display->set_name("monitor section cut");
-	gain_display->set_size_request (PX_SCALE(40), PX_SCALE(20));
+	gain_display->set_size_request (PX_SCALE(68), PX_SCALE(20));
 	gain_display->add_controllable_preset(_("0 dB"), 0.0);
 	gain_display->add_controllable_preset(_("-3 dB"), -3.0);
 	gain_display->add_controllable_preset(_("-6 dB"), -6.0);
@@ -335,23 +295,9 @@ MonitorSection::MonitorSection (Session* s)
 
 	output_button = new ArdourButton ();
 	output_button->set_text (_("Output"));
-	output_button->set_name (X_("monitor section cut"));
+	output_button->set_name (X_("monitor section cut")); // XXX
 	output_button->set_text_ellipsize (Pango::ELLIPSIZE_MIDDLE);
-	VBox* out_packer = manage (new VBox);
-	out_packer->set_spacing (6);
-	out_packer->pack_start (*output_label, false, false);
-	out_packer->pack_start (*output_button, false, false);
-
-	spin_label = manage (new Label (_("Monitor")));
-	spin_packer = manage (new VBox);
-	spin_packer->show ();
-	spin_packer->set_spacing (3);
-	spin_packer->pack_start (*spin_label, false, false);
-	spin_packer->pack_start (*gain_control, false, false);
-	spin_packer->pack_start (*gain_display, false, false);
-	spin_packer->pack_start (*out_packer, false, false, 24);
-
-	lower_packer.pack_start (*spin_packer, true, true);
+	output_button->set_layout_ellipsize_width (PX_SCALE(128) * PANGO_SCALE);
 
 	channel_table_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
 	channel_table_scroller.set_size_request (-1, PX_SCALE(150));
@@ -387,19 +333,102 @@ MonitorSection::MonitorSection (Session* s)
 
 	channel_table_header.show ();
 
-	table_hpacker.pack_start (channel_table, true, true);
+
+	/****************************************************************************
+	 * LAYOUT  top to bottom
+	 */
+
+	// solo, iso information
+	HBox* rude_box = manage (new HBox);
+	rude_box->set_spacing (PX_SCALE(4));
+	rude_box->set_homogeneous (true);
+	rude_box->pack_start (rude_solo_button, true, true);
+	rude_box->pack_start (rude_iso_button, true, true);
+
+	// solo options (right align)
+	HBox* tbx1 = manage (new HBox);
+	tbx1->pack_end (exclusive_solo_button, false, false);
+
+	HBox* tbx2 = manage (new HBox);
+	tbx2->pack_end (solo_mute_override_button, false, false);
+
+	HBox* tbx3 = manage (new HBox);
+	tbx3->pack_end (toggle_processorbox_button, false, false);
+
+	HBox* tbx0 = manage (new HBox); // space
+
+	// combined solo mode (Sip, AFL, PFL) & solo options
+	Table *solo_tbl = manage (new Table);
+	solo_tbl->attach (solo_in_place_button,   0, 1, 0, 1, EXPAND|FILL, SHRINK, 0, 2);
+	solo_tbl->attach (pfl_button,             0, 1, 1, 2, EXPAND|FILL, SHRINK, 0, 2);
+	solo_tbl->attach (afl_button,             0, 1, 2, 3, EXPAND|FILL, SHRINK, 0, 2);
+	solo_tbl->attach (*tbx0,                  1, 2, 0, 3, EXPAND|FILL, SHRINK, 2, 2);
+	solo_tbl->attach (*tbx1,                  2, 3, 0, 1, EXPAND|FILL, SHRINK, 0, 2);
+	solo_tbl->attach (*tbx2,                  2, 3, 1, 2, EXPAND|FILL, SHRINK, 0, 2);
+	solo_tbl->attach (*tbx3,                  2, 3, 2, 3, EXPAND|FILL, SHRINK, 0, 2);
+
+	// boost, cut, dim  volume control
+	Table *level_tbl = manage (new Table);
+	level_tbl->attach (*solo_boost_label,    0, 2, 0, 1, EXPAND|FILL, SHRINK, 1, 2);
+	level_tbl->attach (*solo_boost_control,  0, 2, 1, 2, EXPAND|FILL, SHRINK, 1, 2);
+	level_tbl->attach (*solo_boost_display,  0, 2, 2, 3, EXPAND     , SHRINK, 1, 2);
+
+	level_tbl->attach (*solo_cut_label,      2, 4, 0, 1, EXPAND|FILL, SHRINK, 1, 2);
+	level_tbl->attach (*solo_cut_control,    2, 4, 1, 2, EXPAND|FILL, SHRINK, 1, 2);
+	level_tbl->attach (*solo_cut_display,    2, 4, 2, 3, EXPAND     , SHRINK, 1, 2);
+
+	level_tbl->attach (*dim_label,           1, 3, 3, 4, EXPAND|FILL, SHRINK, 1, 2);
+	level_tbl->attach (*dim_control,         1, 3, 4, 5, EXPAND|FILL, SHRINK, 1, 2);
+	level_tbl->attach (*dim_display,         1, 3, 5, 6, EXPAND     , SHRINK, 1, 2);
 
 	/* note that we don't pack the table_hpacker till later
-	*/
+	 * -> top level channel_table_packer */
+	table_hpacker.pack_start (channel_table, true, true);
 
-	vpacker.set_border_width (6);
-	vpacker.set_spacing (12);
-	vpacker.pack_start (upper_packer, false, false);
-	vpacker.pack_start (*dim_packer, false, false);
-	vpacker.pack_start (channel_table_header, false, false);
-	vpacker.pack_start (channel_table_packer, false, false);
-	vpacker.pack_start (lower_packer, false, false);
+	// mono, dim
+	HBox* mono_dim_box = manage (new HBox);
+	mono_dim_box->set_spacing (PX_SCALE(4));
+	mono_dim_box->set_homogeneous (true);
+	mono_dim_box->pack_start (mono_button, true, true);
+	mono_dim_box->pack_end (dim_all_button, true, true);
+
+	// master gain 
+	Label* spin_label = manage (new Label (_("Monitor")));
+	VBox* spin_packer = manage (new VBox);
+	spin_packer->set_spacing (PX_SCALE(2));
+	spin_packer->pack_start (*spin_label, false, false);
+	spin_packer->pack_start (*gain_control, false, false);
+	spin_packer->pack_start (*gain_display, false, false);
+
+	master_packer.pack_start (*spin_packer, true, false);
+
+	// combined gain section (channels, mute, dim)
+	VBox* lower_packer = manage (new VBox);
+	lower_packer->pack_start (channel_table_header, false, false, PX_SCALE(0));
+	lower_packer->pack_start (channel_table_packer, false, false, PX_SCALE(8));
+	lower_packer->pack_start (*mono_dim_box,        false, false, PX_SCALE(2));
+	lower_packer->pack_start (cut_all_button,       false, false, PX_SCALE(2));
 
+		// output port select
+	VBox* out_packer = manage (new VBox);
+	out_packer->set_spacing (PX_SCALE(2));
+	out_packer->pack_start (*output_label, false, false);
+	out_packer->pack_start (*output_button, false, false);
+
+	/****************************************************************************
+	 * TOP LEVEL LAYOUT
+	 */
+	vpacker.set_border_width (PX_SCALE(3));
+	vpacker.pack_start (*rude_box,            false, false, PX_SCALE(3));
+	vpacker.pack_start (rude_audition_button, false, false, 0);
+	vpacker.pack_start (*solo_tbl,            false, false, PX_SCALE(8));
+	vpacker.pack_start (*insert_box,          true,  true,  PX_SCALE(8));
+	vpacker.pack_start (*level_tbl,           false, false, PX_SCALE(8));
+	vpacker.pack_start (*lower_packer,        false, false, PX_SCALE(8));
+	vpacker.pack_start (master_packer,        false, false, PX_SCALE(10));
+	vpacker.pack_end   (*out_packer,          false, false, PX_SCALE(3));
+
+	hpacker.set_spacing (0);
 	hpacker.pack_start (vpacker, true, true);
 
 	gain_control->show_all ();
@@ -409,11 +438,19 @@ MonitorSection::MonitorSection (Session* s)
 	solo_boost_control->show_all ();
 	solo_boost_display->show_all();
 
+	mono_dim_box->show ();
+	spin_packer->show ();
+	master_packer.show ();
 	channel_table.show ();
-	hpacker.show ();
-	upper_packer.show ();
-	lower_packer.show ();
+
+	rude_box->show();
+	solo_tbl->show_all();
+	level_tbl->show();
+	lower_packer->show ();
+	out_packer->show ();
+
 	vpacker.show ();
+	hpacker.show ();
 
 	populate_buttons ();
 	map_state ();
@@ -421,16 +458,21 @@ MonitorSection::MonitorSection (Session* s)
 
 	output_button->signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::output_press), false);
 	output_button->signal_button_release_event().connect (sigc::mem_fun(*this, &MonitorSection::output_release), false);
-	output_button->signal_size_allocate().connect (sigc::mem_fun (*this, &MonitorSection::output_button_resized));
 
 	_tearoff = new TearOff (hpacker);
 
-	/* if torn off, make this a normal window */
-	_tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
+	if (!UIConfiguration::instance().get_floating_monitor_section()) {
+		/* if torn off, make this a normal window
+		 * (default is WINDOW_TYPE_HINT_UTILITY in libs/gtkmm2ext/tearoff.cc)
+		 */
+		_tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
+	}
 	_tearoff->tearoff_window().set_title (X_("Monitor"));
 	_tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false);
 
-	update_output_display();
+	update_output_display ();
+	update_processor_box ();
+	_ui_initialized = true;
 
 	/* catch changes that affect us */
 	AudioEngine::instance()->PortConnectedOrDisconnected.connect (
@@ -448,6 +490,7 @@ MonitorSection::~MonitorSection ()
 	_channel_buttons.clear ();
 	_output_changed_connection.disconnect ();
 
+	delete insert_box;
 	delete output_button;
 	delete gain_control;
 	delete gain_display;
@@ -462,10 +505,42 @@ MonitorSection::~MonitorSection ()
 	_output_selector = 0;
 }
 
+
+void
+MonitorSection::update_processor_box ()
+{
+	bool show_processor_box = proctoggle->get_active ();
+
+	if (count_processors () > 0 && !show_processor_box) {
+		toggle_processorbox_button.set_name (X_("monitor section processors present"));
+	} else {
+		toggle_processorbox_button.set_name (X_("monitor section processors toggle"));
+	}
+
+	if (insert_box->is_visible() == show_processor_box) {
+		return;
+	}
+
+	if (show_processor_box) {
+		if (master_packer.get_parent()) {
+			master_packer.get_parent()->remove (master_packer);
+		}
+		insert_box->show();
+		vpacker.pack_start (master_packer,        false, false, PX_SCALE(10));
+	} else {
+		if (master_packer.get_parent()) {
+			master_packer.get_parent()->remove (master_packer);
+		}
+		insert_box->hide();
+		vpacker.pack_start (master_packer,        true,  false, PX_SCALE(10));
+	}
+}
+
 void
 MonitorSection::set_session (Session* s)
 {
 	AxisView::set_session (s);
+	_plugin_selector->set_session (_session);
 
 	if (_session) {
 
@@ -478,6 +553,11 @@ MonitorSection::set_session (Session* s)
 			_route->output()->changed.connect (_output_changed_connection, invalidator (*this),
 											boost::bind (&MonitorSection::update_output_display, this),
 											gui_context());
+			insert_box->set_route (_route);
+			_route->processors_changed.connect (*this, invalidator (*this), boost::bind (&MonitorSection::processors_changed, this, _1), gui_context());
+			if (_ui_initialized) {
+				update_processor_box ();
+			}
 		} else {
 			/* session with no monitor section */
 			_output_changed_connection.disconnect();
@@ -540,10 +620,10 @@ MonitorSection::set_session (Session* s)
 
 MonitorSection::ChannelButtonSet::ChannelButtonSet ()
 {
-	cut.set_name (X_("monitor section cut"));
+	cut.set_name (X_("mute button"));
 	dim.set_name (X_("monitor section dim"));
-	solo.set_name (X_("monitor section solo"));
-	invert.set_name (X_("monitor section invert"));
+	solo.set_name (X_("solo button"));
+	invert.set_name (X_("invert button"));
 
 	cut.unset_flags (Gtk::CAN_FOCUS);
 	dim.unset_flags (Gtk::CAN_FOCUS);
@@ -597,25 +677,25 @@ MonitorSection::populate_buttons ()
 		channel_table.attach (cbs->solo, 3, 4, i+row_offset, i+row_offset+1, EXPAND|FILL);
 		channel_table.attach (cbs->invert, 4, 5, i+row_offset, i+row_offset+1, EXPAND|FILL);
 
-		snprintf (buf, sizeof (buf), "monitor-cut-%u", i+1);
+		snprintf (buf, sizeof (buf), "monitor-cut-%u", i);
 		act = ActionManager::get_action (X_("Monitor"), buf);
 		if (act) {
 			cbs->cut.set_related_action (act);
 		}
 
-		snprintf (buf, sizeof (buf), "monitor-dim-%u", i+1);
+		snprintf (buf, sizeof (buf), "monitor-dim-%u", i);
 		act = ActionManager::get_action (X_("Monitor"), buf);
 		if (act) {
 			cbs->dim.set_related_action (act);
 		}
 
-		snprintf (buf, sizeof (buf), "monitor-solo-%u", i+1);
+		snprintf (buf, sizeof (buf), "monitor-solo-%u", i);
 		act = ActionManager::get_action (X_("Monitor"), buf);
 		if (act) {
 			cbs->solo.set_related_action (act);
 		}
 
-		snprintf (buf, sizeof (buf), "monitor-invert-%u", i+1);
+		snprintf (buf, sizeof (buf), "monitor-invert-%u", i);
 		act = ActionManager::get_action (X_("Monitor"), buf);
 		if (act) {
 			cbs->invert.set_related_action (act);
@@ -707,8 +787,6 @@ MonitorSection::cut_channel (uint32_t chn)
 	char buf[64];
 	snprintf (buf, sizeof (buf), "monitor-cut-%u", chn);
 
-	--chn; // 0-based in backend
-
 	Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
 	if (act) {
 		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -726,8 +804,6 @@ MonitorSection::dim_channel (uint32_t chn)
 	char buf[64];
 	snprintf (buf, sizeof (buf), "monitor-dim-%u", chn);
 
-	--chn; // 0-based in backend
-
 	Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
 	if (act) {
 		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -746,8 +822,6 @@ MonitorSection::solo_channel (uint32_t chn)
 	char buf[64];
 	snprintf (buf, sizeof (buf), "monitor-solo-%u", chn);
 
-	--chn; // 0-based in backend
-
 	Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
 	if (act) {
 		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -766,8 +840,6 @@ MonitorSection::invert_channel (uint32_t chn)
 	char buf[64];
 	snprintf (buf, sizeof (buf), "monitor-invert-%u", chn);
 
-	--chn; // 0-based in backend
-
 	Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
 	if (act) {
 		Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -807,9 +879,7 @@ MonitorSection::register_actions ()
 	tact->set_active (Config->get_solo_mute_override());
 
 
-	/* note the 1-based counting (for naming - backend uses 0-based) */
-
-	for (uint32_t chn = 1; chn <= 16; ++chn) {
+	for (uint32_t chn = 0; chn < 16; ++chn) {
 
 		action_name = string_compose (X_("monitor-cut-%1"), chn);
 		action_descr = string_compose (_("Cut monitor channel %1"), chn);
@@ -848,6 +918,60 @@ MonitorSection::register_actions ()
 }
 
 void
+MonitorSection::connect_actions ()
+{
+	Glib::RefPtr<Action> act;
+	Glib::RefPtr<ToggleAction> tact;
+
+#define MON_TOG(NAME, FUNC) \
+	act = ActionManager::get_action (X_("Monitor"), NAME); \
+	tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act); \
+	assert (tact); \
+	tact->signal_toggled().connect (sigc::mem_fun (*this, &MonitorSection::FUNC)); \
+
+	MON_TOG("monitor-mono", mono);
+	MON_TOG("monitor-cut-all", cut_all);
+	MON_TOG("monitor-dim-all", dim_all);
+
+	MON_TOG("toggle-exclusive-solo", toggle_exclusive_solo);
+	tact->set_active (Config->get_exclusive_solo());
+
+	MON_TOG("toggle-mute-overrides-solo", toggle_mute_overrides_solo);
+	tact->set_active (Config->get_solo_mute_override());
+#undef MON_TOG
+
+#define MON_BIND(NAME, FUNC, ARG) \
+	act = ActionManager::get_action (X_("Monitor"), NAME); \
+	tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act); \
+	assert (tact); \
+	tact->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MonitorSection::FUNC), ARG));
+
+	for (uint32_t chn = 0; chn < 16; ++chn) {
+		std::string action_name = string_compose (X_("monitor-cut-%1"), chn);
+		MON_BIND(action_name.c_str(), cut_channel, chn);
+		action_name = string_compose (X_("monitor-dim-%1"), chn);
+		MON_BIND(action_name.c_str(), dim_channel, chn);
+		action_name = string_compose (X_("monitor-solo-%1"), chn);
+		MON_BIND(action_name.c_str(), solo_channel, chn);
+		action_name = string_compose (X_("monitor-invert-%1"), chn);
+		MON_BIND(action_name.c_str(), invert_channel, chn);
+	}
+#undef MON_BIND
+
+#define SOLO_RADIO(NAME, FUNC) \
+	act = ActionManager::get_action (X_("Solo"), NAME); \
+	ract = Glib::RefPtr<RadioAction>::cast_dynamic (act); \
+	assert (ract); \
+	ract->signal_toggled().connect (sigc::mem_fun (*this, &MonitorSection::FUNC)); \
+
+	Glib::RefPtr<RadioAction> ract;
+	SOLO_RADIO ("solo-use-in-place", solo_use_in_place);
+	SOLO_RADIO ("solo-use-afl", solo_use_afl);
+	SOLO_RADIO ("solo-use-pfl", solo_use_pfl);
+#undef SOLO_RADIO
+}
+
+void
 MonitorSection::solo_use_in_place ()
 {
 	/* this is driven by a toggle on a radio group, and so is invoked twice,
@@ -1315,12 +1439,6 @@ MonitorSection::output_press (GdkEventButton *ev)
 }
 
 void
-MonitorSection::output_button_resized (Gtk::Allocation& alloc)
-{
-	output_button->set_layout_ellipsize_width (alloc.get_width() * PANGO_SCALE);
-}
-
-void
 MonitorSection::update_output_display ()
 {
 	if (!_route || !_monitor || _session->deletion_in_progress()) {
@@ -1387,7 +1505,7 @@ MonitorSection::update_output_display ()
 						<< Gtkmm2ext::markup_escape_text ( pn.empty() ? connection_name : pn );
 				}
 
-				if (connection_name.find("ardour:") == 0) {
+				if (connection_name.find(RouteUI::program_port_prefix) == 0) {
 					if (ardour_track_name.empty()) {
 						// "ardour:Master/in 1" -> "ardour:Master/"
 						string::size_type slash = connection_name.find("/");
@@ -1511,3 +1629,32 @@ MonitorSection::port_connected_or_disconnected (boost::weak_ptr<Port> wa, boost:
 		update_output_display ();
 	}
 }
+
+void
+MonitorSection::help_count_processors (boost::weak_ptr<Processor> p, uint32_t* cnt) const
+{
+	boost::shared_ptr<Processor> processor (p.lock ());
+	if (!processor || !processor->display_to_user()) {
+		return;
+	}
+	if (boost::dynamic_pointer_cast<Amp>(processor)) {
+		return;
+	}
+	++(*cnt);
+}
+
+uint32_t
+MonitorSection::count_processors ()
+{
+	uint32_t processor_count = 0;
+	if (_route) {
+		_route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &MonitorSection::help_count_processors), &processor_count));
+	}
+	return processor_count;
+}
+
+void
+MonitorSection::processors_changed (ARDOUR::RouteProcessorChange)
+{
+	update_processor_box ();
+}
diff --git a/gtk2_ardour/monitor_section.h b/gtk2_ardour/monitor_section.h
index 31d7374..67d22d0 100644
--- a/gtk2_ardour/monitor_section.h
+++ b/gtk2_ardour/monitor_section.h
@@ -30,6 +30,10 @@
 #include "route_ui.h"
 #include "monitor_selector.h"
 
+#include "plugin_selector.h"
+#include "route_processor_selection.h"
+#include "processor_box.h"
+
 namespace Gtkmm2ext {
 	class TearOff;
 	class MotionFeedback;
@@ -49,15 +53,16 @@ class MonitorSection : public RouteUI
 
 	std::string state_id() const;
 
+	PluginSelector* plugin_selector() { return _plugin_selector; }
+
 	private:
-	Gtk::VBox vpacker;
 	Gtk::HBox hpacker;
-	Gtk::VBox upper_packer;
-	Gtk::VBox lower_packer;
+	Gtk::VBox vpacker;
 	Gtkmm2ext::TearOff* _tearoff;
 
 	Gtk::HBox  channel_table_packer;
 	Gtk::HBox  table_hpacker;
+	Gtk::HBox  master_packer;
 	Gtk::Table channel_table;
 	Gtk::Table channel_table_header;
 	Gtk::ScrolledWindow channel_table_scroller;
@@ -93,7 +98,6 @@ class MonitorSection : public RouteUI
 
 	void maybe_add_bundle_to_output_menu (boost::shared_ptr<ARDOUR::Bundle>, ARDOUR::BundleList const &);
 	void bundle_output_chosen (boost::shared_ptr<ARDOUR::Bundle>);
-	void output_button_resized (Gtk::Allocation&);
 	void update_output_display ();
 	void disconnect_output ();
 	void edit_output_configuration ();
@@ -106,6 +110,7 @@ class MonitorSection : public RouteUI
 
 	static Glib::RefPtr<Gtk::ActionGroup> monitor_actions;
 	void register_actions ();
+	void connect_actions ();
 
 	void cut_channel (uint32_t);
 	void dim_channel (uint32_t);
@@ -126,7 +131,7 @@ class MonitorSection : public RouteUI
 	ArdourButton solo_in_place_button;
 	ArdourButton afl_button;
 	ArdourButton pfl_button;
-	Gtk::HBox        solo_model_box;
+	Gtk::VBox    solo_model_box;
 
 	void solo_use_in_place ();
 	void solo_use_afl ();
@@ -140,6 +145,7 @@ class MonitorSection : public RouteUI
 	ArdourButton rude_audition_button;
 	ArdourButton exclusive_solo_button;
 	ArdourButton solo_mute_override_button;
+	ArdourButton toggle_processorbox_button;
 
 	void do_blink (bool);
 	void solo_blink (bool);
@@ -158,5 +164,18 @@ class MonitorSection : public RouteUI
 	bool _inhibit_solo_model_update;
 
 	void assign_controllables ();
+
 	void port_connected_or_disconnected (boost::weak_ptr<ARDOUR::Port>, boost::weak_ptr<ARDOUR::Port>);
+
+	void update_processor_box ();
+
+	ProcessorBox* insert_box;
+	PluginSelector* _plugin_selector;
+	RouteProcessorSelection _rr_selection;
+	void help_count_processors (boost::weak_ptr<ARDOUR::Processor> p, uint32_t* cnt) const;
+	uint32_t count_processors ();
+
+	void processors_changed (ARDOUR::RouteProcessorChange);
+	Glib::RefPtr<Gtk::ToggleAction> proctoggle;
+	bool _ui_initialized;
 };
diff --git a/gtk2_ardour/mono_panner.cc b/gtk2_ardour/mono_panner.cc
index 23b64ee..0dd54ef 100644
--- a/gtk2_ardour/mono_panner.cc
+++ b/gtk2_ardour/mono_panner.cc
@@ -51,6 +51,8 @@ using namespace Gtk;
 using namespace Gtkmm2ext;
 using namespace ARDOUR_UI_UTILS;
 
+using PBD::Controllable;
+
 MonoPanner::ColorScheme MonoPanner::colors;
 bool MonoPanner::have_colors = false;
 
@@ -318,11 +320,11 @@ MonoPanner::on_button_press_event (GdkEventButton* ev)
 
 		if (ev->x <= width/3) {
 			/* left side dbl click */
-			position_control->set_value (0);
+			position_control->set_value (0, Controllable::NoGroup);
 		} else if (ev->x > 2*width/3) {
-			position_control->set_value (1.0);
+			position_control->set_value (1.0, Controllable::NoGroup);
 		} else {
-			position_control->set_value (0.5);
+			position_control->set_value (0.5, Controllable::NoGroup);
 		}
 
 		_dragging = false;
@@ -393,12 +395,12 @@ MonoPanner::on_scroll_event (GdkEventScroll* ev)
 		case GDK_SCROLL_UP:
 		case GDK_SCROLL_LEFT:
 			pv -= step;
-			position_control->set_value (pv);
+			position_control->set_value (pv, Controllable::NoGroup);
 			break;
 		case GDK_SCROLL_DOWN:
 		case GDK_SCROLL_RIGHT:
 			pv += step;
-			position_control->set_value (pv);
+			position_control->set_value (pv, Controllable::NoGroup);
 			break;
 	}
 
@@ -423,7 +425,7 @@ MonoPanner::on_motion_notify_event (GdkEventMotion* ev)
 	if (!detented && ARDOUR::Panner::equivalent (position_control->get_value(), 0.5)) {
 		detented = true;
 		/* snap to center */
-		position_control->set_value (0.5);
+		position_control->set_value (0.5, Controllable::NoGroup);
 	}
 
 	if (detented) {
@@ -432,13 +434,13 @@ MonoPanner::on_motion_notify_event (GdkEventMotion* ev)
 		/* have we pulled far enough to escape ? */
 
 		if (fabs (accumulated_delta) >= 0.025) {
-			position_control->set_value (position_control->get_value() + accumulated_delta);
+			position_control->set_value (position_control->get_value() + accumulated_delta, Controllable::NoGroup);
 			detented = false;
 			accumulated_delta = false;
 		}
 	} else {
 		double pv = position_control->get_value(); // 0..1.0 ; 0 = left
-		position_control->set_value (pv + delta);
+		position_control->set_value (pv + delta, Controllable::NoGroup);
 	}
 
 	last_drag_x = ev->x;
@@ -465,15 +467,15 @@ MonoPanner::on_key_press_event (GdkEventKey* ev)
 	switch (ev->keyval) {
 		case GDK_Left:
 			pv -= step;
-			position_control->set_value (pv);
+			position_control->set_value (pv, Controllable::NoGroup);
 			break;
 		case GDK_Right:
 			pv += step;
-			position_control->set_value (pv);
+			position_control->set_value (pv, Controllable::NoGroup);
 			break;
 		case GDK_0:
 		case GDK_KP_0:
-			position_control->set_value (0.0);
+			position_control->set_value (0.0, Controllable::NoGroup);
 			break;
 		default:
 			return false;
diff --git a/gtk2_ardour/mono_panner_editor.cc b/gtk2_ardour/mono_panner_editor.cc
index 134c812..5a9a092 100644
--- a/gtk2_ardour/mono_panner_editor.cc
+++ b/gtk2_ardour/mono_panner_editor.cc
@@ -29,6 +29,8 @@
 using namespace Gtk;
 using namespace Gtkmm2ext;
 
+using PBD::Controllable;
+
 MonoPannerEditor::MonoPannerEditor (MonoPanner* p)
 	: PannerEditor (_("Mono Panner"))
 	, _panner (p)
@@ -98,7 +100,7 @@ MonoPannerEditor::left_changed ()
 
 	_ignore_changes = true;
 	_right.set_value (100 * v);
-	_panner->get_controllable()->set_value (v);
+	_panner->get_controllable()->set_value (v, Controllable::NoGroup);
 	_ignore_changes = false;
 }
 
@@ -113,7 +115,7 @@ MonoPannerEditor::right_changed ()
 
 	_ignore_changes = true;
 	_left.set_value (100 * (1 - v));
-	_panner->get_controllable()->set_value (v);
+	_panner->get_controllable()->set_value (v, Controllable::NoGroup);
 	_ignore_changes = false;
 }
 
diff --git a/gtk2_ardour/new_plugin_preset_dialog.cc b/gtk2_ardour/new_plugin_preset_dialog.cc
index 828344b..cc5c4b9 100644
--- a/gtk2_ardour/new_plugin_preset_dialog.cc
+++ b/gtk2_ardour/new_plugin_preset_dialog.cc
@@ -25,8 +25,8 @@
 using namespace std;
 using namespace Gtk;
 
-NewPluginPresetDialog::NewPluginPresetDialog (boost::shared_ptr<ARDOUR::Plugin> p)
-	: ArdourDialog (_("New Preset"))
+NewPluginPresetDialog::NewPluginPresetDialog (boost::shared_ptr<ARDOUR::Plugin> p, std::string title, bool favorite_btn)
+	: ArdourDialog (title)
 	, _replace (_("Replace existing preset with this name"))
 {
 	HBox* h = manage (new HBox);
@@ -40,10 +40,14 @@ NewPluginPresetDialog::NewPluginPresetDialog (boost::shared_ptr<ARDOUR::Plugin>
 	get_vbox()->pack_start (_replace);
 
 	add_button (Stock::CANCEL, RESPONSE_CANCEL);
+	if (favorite_btn) {
+		add_button (_("New Favorite Only"), RESPONSE_NO);
+	}
 	_add = add_button (Stock::ADD, RESPONSE_ACCEPT);
 	set_default_response (RESPONSE_ACCEPT);
 	_name.set_activates_default(true);
 
+
 	show_all ();
 
 	_presets = p->get_presets ();
diff --git a/gtk2_ardour/new_plugin_preset_dialog.h b/gtk2_ardour/new_plugin_preset_dialog.h
index 8dddf6c..feb1bf0 100644
--- a/gtk2_ardour/new_plugin_preset_dialog.h
+++ b/gtk2_ardour/new_plugin_preset_dialog.h
@@ -26,7 +26,7 @@
 class NewPluginPresetDialog : public ArdourDialog
 {
 public:
-	NewPluginPresetDialog (boost::shared_ptr<ARDOUR::Plugin>);
+	NewPluginPresetDialog (boost::shared_ptr<ARDOUR::Plugin>, std::string, bool fav = false);
 
 	std::string name () const;
 	bool replace () const;
diff --git a/gtk2_ardour/note.h b/gtk2_ardour/note.h
index e763ea9..37d5573 100644
--- a/gtk2_ardour/note.h
+++ b/gtk2_ardour/note.h
@@ -51,8 +51,8 @@ public:
 	void set_x1 (ArdourCanvas::Coord);
 	void set_y1 (ArdourCanvas::Coord);
 
-        void set_outline_what (ArdourCanvas::Rectangle::What);
-        void set_outline_all ();
+	void set_outline_what (ArdourCanvas::Rectangle::What);
+	void set_outline_all ();
 
 	void set_outline_color (uint32_t);
 	void set_fill_color (uint32_t);
diff --git a/gtk2_ardour/note_base.cc b/gtk2_ardour/note_base.cc
index 228a6de..9c47fa7 100644
--- a/gtk2_ardour/note_base.cc
+++ b/gtk2_ardour/note_base.cc
@@ -36,8 +36,6 @@ using namespace Gtkmm2ext;
 using ARDOUR::MidiModel;
 using namespace ArdourCanvas;
 
-PBD::Signal1<void,NoteBase*> NoteBase::NoteBaseDeleted;
-
 /// dividing the hue circle in 16 parts, hand adjusted for equal look, courtesy Thorsten Wilms
 const uint32_t NoteBase::midi_channel_colors[16] = {
 	  0xd32d2dff,  0xd36b2dff,  0xd3972dff,  0xd3d12dff,
@@ -62,7 +60,7 @@ NoteBase::NoteBase(MidiRegionView& region, bool with_events, const boost::shared
 
 NoteBase::~NoteBase()
 {
-	NoteBaseDeleted (this);
+	_region.note_deleted (this);
 
 	delete _text;
 }
@@ -240,14 +238,14 @@ NoteBase::set_mouse_fractions (GdkEvent* ev)
 	_mouse_y_fraction = yf;
 
 	if (notify) {
-                if (big_enough_to_trim()) {
-                        _region.note_mouse_position (_mouse_x_fraction, _mouse_y_fraction, set_cursor);
-                } else {
-                        /* pretend the mouse is in the middle, because this is not big enough
-                           to trim right now.
-                        */
-                        _region.note_mouse_position (0.5, 0.5, set_cursor);
-                }
+		if (big_enough_to_trim()) {
+			_region.note_mouse_position (_mouse_x_fraction, _mouse_y_fraction, set_cursor);
+		} else {
+			/* pretend the mouse is in the middle, because this is not big enough
+			   to trim right now.
+			*/
+			_region.note_mouse_position (0.5, 0.5, set_cursor);
+		}
 	}
 }
 
diff --git a/gtk2_ardour/note_base.h b/gtk2_ardour/note_base.h
index e63e59b..059aa9d 100644
--- a/gtk2_ardour/note_base.h
+++ b/gtk2_ardour/note_base.h
@@ -59,9 +59,7 @@ class NoteBase : public sigc::trackable
 	virtual ~NoteBase ();
 
 	void set_item (ArdourCanvas::Item *);
-        ArdourCanvas::Item* item() const { return _item; }
-
-        static PBD::Signal1<void, NoteBase*> NoteBaseDeleted;
+	ArdourCanvas::Item* item() const { return _item; }
 
 	virtual void show() = 0;
 	virtual void hide() = 0;
@@ -96,8 +94,8 @@ class NoteBase : public sigc::trackable
 	virtual ArdourCanvas::Coord x1 () const = 0;
 	virtual ArdourCanvas::Coord y1 () const = 0;
 
-        float mouse_x_fraction() const { return _mouse_x_fraction; }
-        float mouse_y_fraction() const { return _mouse_y_fraction; }
+	float mouse_x_fraction() const { return _mouse_x_fraction; }
+	float mouse_y_fraction() const { return _mouse_y_fraction; }
 
 	const boost::shared_ptr<NoteType> note() const { return _note; }
 	MidiRegionView& region_view() const { return _region; }
@@ -130,8 +128,8 @@ class NoteBase : public sigc::trackable
 	/// hue circle divided into 16 equal-looking parts, courtesy Thorsten Wilms
 	static const uint32_t midi_channel_colors[16];
 
-        bool mouse_near_ends () const;
-        virtual bool big_enough_to_trim () const;
+	bool mouse_near_ends () const;
+	virtual bool big_enough_to_trim () const;
 
 protected:
 	enum State { None, Pressed, Dragging };
@@ -145,10 +143,10 @@ protected:
 	bool                              _own_note;
 	bool                              _selected;
 	bool                              _valid;
-        float                             _mouse_x_fraction;
-        float                             _mouse_y_fraction;
+	float                             _mouse_x_fraction;
+	float                             _mouse_y_fraction;
 
-        void set_mouse_fractions (GdkEvent*);
+	void set_mouse_fractions (GdkEvent*);
 
 private:
 	bool event_handler (GdkEvent *);
diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc
index a8c35f2..e963726 100644
--- a/gtk2_ardour/option_editor.cc
+++ b/gtk2_ardour/option_editor.cc
@@ -31,9 +31,10 @@
 #include "pbd/configuration.h"
 #include "pbd/replace_all.h"
 
-#include "public_editor.h"
-#include "option_editor.h"
 #include "gui_thread.h"
+#include "option_editor.h"
+#include "public_editor.h"
+#include "utils.h"
 #include "i18n.h"
 
 using namespace std;
@@ -112,6 +113,70 @@ OptionEditorBox::add_to_page (OptionEditorPage* p)
 	add_widget_to_page (p, _box);
 }
 
+RcActionButton::RcActionButton (std::string const & t, const Glib::SignalProxy0< void >::SlotType & slot, std::string const & l)
+	: _label (NULL)
+{
+	_button = manage (new Button (t));
+	_button->signal_clicked().connect (slot);
+	if (!l.empty ()) {
+		_label = manage (right_aligned_label (l));
+	}
+}
+
+void
+RcActionButton::add_to_page (OptionEditorPage *p)
+{
+	int const n = p->table.property_n_rows();
+	int m = n + 1;
+	p->table.resize (m, 3);
+	if (_label) {
+		p->table.attach (*_label,  1, 2, n, n + 1, FILL | EXPAND);
+		p->table.attach (*_button, 2, 3, n, n + 1, FILL | EXPAND);
+	} else {
+		p->table.attach (*_button, 1, 3, n, n + 1, FILL | EXPAND);
+	}
+}
+
+RcConfigDisplay::RcConfigDisplay (string const & i, string const & n, sigc::slot<string> g, char s)
+	: _get (g)
+	, _id (i)
+	, _sep (s)
+{
+	_label = manage (right_aligned_label (n));
+	_info = manage (new Label);
+	_info-> set_line_wrap (true);
+	set_state_from_config ();
+}
+
+void
+RcConfigDisplay::set_state_from_config ()
+{
+	string p = _get();
+	if (_sep) {
+		std::replace (p.begin(), p.end(), _sep, '\n');
+	}
+	_info->set_text (p);
+}
+
+void
+RcConfigDisplay::parameter_changed (std::string const & p)
+{
+	if (p == _id) {
+		set_state_from_config ();
+	}
+}
+
+void
+RcConfigDisplay::add_to_page (OptionEditorPage *p)
+{
+	int const n = p->table.property_n_rows();
+	int m = n + 1;
+	p->table.resize (m, 3);
+	p->table.attach (*_label, 1, 2, n, n + 1, FILL | EXPAND);
+	p->table.attach (*_info,  2, 3, n, n + 1, FILL | EXPAND);
+}
+
+
 BoolOption::BoolOption (string const & i, string const & n, sigc::slot<bool> g, sigc::slot<bool, bool> s)
 	: Option (i, n),
 	  _get (g),
@@ -289,6 +354,8 @@ FaderOption::FaderOption (string const & i, string const & n, sigc::slot<gain_t>
 	set_size_request_to_display_given_text (_db_display, "-99.00", 12, 12);
 
 	_db_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FaderOption::db_changed));
+	_db_display.signal_activate().connect (sigc::mem_fun (*this, &FaderOption::on_activate));
+	_db_display.signal_key_press_event().connect (sigc::mem_fun (*this, &FaderOption::on_key_press), false);
 }
 
 void
@@ -315,6 +382,26 @@ FaderOption::db_changed ()
 }
 
 void
+FaderOption::on_activate ()
+{
+	float db_val = atof (_db_display.get_text ().c_str ());
+	gain_t coeff_val = dB_to_coefficient (db_val);
+
+	_db_adjustment.set_value (gain_to_slider_position_with_max (coeff_val, Config->get_max_gain ()));
+}
+
+bool
+FaderOption::on_key_press (GdkEventKey* ev)
+{
+	if (ARDOUR_UI_UTILS::key_is_legal_for_numeric_entry (ev->keyval)) {
+		/* drop through to normal handling */
+		return false;
+	}
+	/* illegal key for gain entry */
+	return true;
+}
+
+void
 FaderOption::add_to_page (OptionEditorPage* p)
 {
 	add_widgets_to_page (p, &_label, &_box);
diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h
index 67835b2..7637061 100644
--- a/gtk2_ardour/option_editor.h
+++ b/gtk2_ardour/option_editor.h
@@ -121,6 +121,38 @@ protected:
 	Gtk::VBox* _box; ///< constituent box for subclasses to add widgets to
 };
 
+class RcConfigDisplay : public OptionEditorComponent
+{
+public:
+	RcConfigDisplay (std::string const &, std::string const &, sigc::slot<std::string>, char s = '\0');
+	void add_to_page (OptionEditorPage *);
+	void parameter_changed (std::string const & p);
+	void set_state_from_config ();
+	Gtk::Widget& tip_widget() { return *_info; }
+protected:
+	sigc::slot<std::string> _get;
+	Gtk::Label* _label;
+	Gtk::Label* _info;
+	std::string _id;
+	char _sep;
+};
+
+class RcActionButton : public OptionEditorComponent
+{
+public:
+	RcActionButton (std::string const & t, const Glib::SignalProxy0< void >::SlotType & slot, std::string const & l = "");
+	void add_to_page (OptionEditorPage *);
+
+	void parameter_changed (std::string const & p) {}
+	void set_state_from_config () {}
+	Gtk::Widget& tip_widget() { return *_button; }
+
+protected:
+	Gtk::Button* _button;
+	Gtk::Label* _label;
+	std::string _name;
+};
+
 /** Base class for components which provide UI to change an option */
 class Option : public OptionEditorComponent
 {
@@ -582,6 +614,8 @@ public:
 
 private:
 	void db_changed ();
+	void on_activate ();
+	bool on_key_press (GdkEventKey* ev);
 
 	Gtk::Adjustment _db_adjustment;
 	Gtkmm2ext::HSliderController* _db_slider;
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
index 8aff9c4..d518df5 100644
--- a/gtk2_ardour/plugin_selector.cc
+++ b/gtk2_ardour/plugin_selector.cc
@@ -64,7 +64,15 @@ static const char* _filter_mode_strings[] = {
 PluginSelector::PluginSelector (PluginManager& mgr)
 	: ArdourDialog (_("Plugin Manager"), true, false)
 	, filter_button (Stock::CLEAR)
+	, fil_hidden_button (ArdourButton::led_default_elements)
+	, fil_instruments_button (ArdourButton::default_elements)
+	, fil_analysis_button (ArdourButton::default_elements)
+	, fil_utils_button (ArdourButton::default_elements)
 	, manager (mgr)
+	, _show_hidden (false)
+	, _show_instruments (Gtkmm2ext::ImplicitActive)
+	, _show_analysers (Gtkmm2ext::Off)
+	, _show_utils (Gtkmm2ext::Off)
 
 {
 	set_name ("PluginSelectorWindow");
@@ -75,6 +83,8 @@ PluginSelector::PluginSelector (PluginManager& mgr)
 
 	manager.PluginListChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::build_plugin_menu, this), gui_context());
 	manager.PluginListChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::refill, this), gui_context());
+	manager.PluginStatusesChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::build_plugin_menu, this), gui_context());
+	manager.PluginStatusesChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::refill, this), gui_context());
 	build_plugin_menu ();
 
 	plugin_model = Gtk::ListStore::create (plugin_columns);
@@ -97,6 +107,11 @@ PluginSelector::PluginSelector (PluginManager& mgr)
 	plugin_display.set_headers_clickable (true);
 	plugin_display.set_reorderable (false);
 	plugin_display.set_rules_hint (true);
+	plugin_display.add_object_drag (plugin_columns.plugin.index(), "PluginInfoPtr");
+	plugin_display.set_drag_column (plugin_columns.name.index());
+
+	// setting a sort-column prevents re-ordering via Drag/Drop
+	plugin_model->set_sort_column (plugin_columns.name.index(), Gtk::SORT_ASCENDING);
 
 	CellRendererToggle* fav_cell = dynamic_cast<CellRendererToggle*>(plugin_display.get_column_cell_renderer (0));
 	fav_cell->property_activatable() = true;
@@ -136,33 +151,69 @@ PluginSelector::PluginSelector (PluginManager& mgr)
 	btn_add->set_name("PluginSelectorButton");
 	btn_remove->set_name("PluginSelectorButton");
 
+
 	Gtk::Table* table = manage(new Gtk::Table(7, 11));
 	table->set_size_request(750, 500);
-	table->attach(scroller, 0, 7, 0, 5);
 
-	HBox* filter_box = manage (new HBox);
+	Gtk::Table* filter_table = manage(new Gtk::Table(2, 5));
+
+	fil_hidden_button.set_name ("pluginlist hide button");
+	fil_hidden_button.set_text (_("Show Hidden"));
+	fil_hidden_button.set_active (_show_hidden);
+	set_tooltip (fil_hidden_button, _("Include hidden plugins in list."));
+
+	fil_instruments_button.set_name ("pluginlist filter button");
+	fil_instruments_button.set_text (_("Instruments"));
+	fil_instruments_button.set_active_state (_show_instruments);
+	set_tooltip (fil_instruments_button, _("Cycle display of instrument plugins (if any)."));
+
+	fil_analysis_button.set_name ("pluginlist filter button");
+	fil_analysis_button.set_text (_("Analyzers"));
+	fil_analysis_button.set_active_state (_show_analysers);
+	set_tooltip (fil_analysis_button, _("Cycle display of analysis plugins (if any)."));
+
+	fil_utils_button.set_name ("pluginlist filter button");
+	fil_utils_button.set_text (_("Utils"));
+	fil_utils_button.set_active_state (_show_utils);
+	set_tooltip (fil_utils_button, _("Cycle display of utility plugins (if any)."));
 
 	vector<string> filter_strings = I18N (_filter_mode_strings);
 	Gtkmm2ext::set_popdown_strings (filter_mode, filter_strings);
 	filter_mode.set_active_text (filter_strings.front());
 
-	filter_box->pack_start (filter_mode, false, false);
-	filter_box->pack_start (filter_entry, true, true);
-	filter_box->pack_start (filter_button, false, false);
+	fil_hidden_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_hidden_button_release), false);
+	fil_instruments_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_instruments_button_release), false);
+	fil_analysis_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_analysis_button_release), false);
+	fil_utils_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_utils_button_release), false);
 
 	filter_entry.signal_changed().connect (sigc::mem_fun (*this, &PluginSelector::filter_entry_changed));
 	filter_button.signal_clicked().connect (sigc::mem_fun (*this, &PluginSelector::filter_button_clicked));
 	filter_mode.signal_changed().connect (sigc::mem_fun (*this, &PluginSelector::filter_mode_changed));
 
-	filter_box->show ();
-	filter_mode.show ();
-	filter_entry.show ();
-	filter_button.show ();
+	filter_table->attach (filter_mode,            0, 1, 0, 1, FILL, FILL);
+	filter_table->attach (filter_entry,           1, 4, 0, 1, FILL|EXPAND, FILL);
+	filter_table->attach (filter_button,          4, 5, 0, 1, FILL, FILL);
+
+	filter_table->attach (fil_hidden_button,      1, 2, 1, 2, FILL, FILL);
+	filter_table->attach (fil_instruments_button, 2, 3, 1, 2, FILL, FILL);
+	filter_table->attach (fil_analysis_button,    3, 4, 1, 2, FILL, FILL);
+	filter_table->attach (fil_utils_button,       4, 5, 1, 2, FILL, FILL);
+
+	filter_table->set_border_width (4);
+	filter_table->set_col_spacings (2);
+	filter_table->set_row_spacings (4);
 
-	table->attach (*filter_box, 0, 7, 5, 6, FILL|EXPAND, FILL, 5, 5);
+	Frame* filter_frame = manage (new Frame);
+	filter_frame->set_name ("BaseFrame");
+	filter_frame->set_label (_("Filter"));
+	filter_frame->add (*filter_table);
 
-	table->attach(*btn_add, 1, 2, 6, 7, FILL, FILL, 5, 5);
-	table->attach(*btn_remove, 5, 6, 6, 7, FILL, FILL, 5, 5);
+	filter_frame->show_all ();
+
+	table->attach (scroller, 0, 7, 0, 5);
+	table->attach (*filter_frame, 0, 7, 6, 7, FILL|EXPAND, FILL, 5, 5);
+	table->attach(*btn_add, 1, 2, 7, 8, FILL, FILL, 5, 5);
+	table->attach(*btn_remove, 5, 6, 7, 8, FILL, FILL, 5, 5);
 
 	table->attach(ascroller, 0, 7, 8, 10);
 
@@ -221,6 +272,40 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string&
 		return manager.get_status (info) == PluginManager::Hidden;
 	}
 
+	if (!_show_hidden && manager.get_status (info) == PluginManager::Hidden) {
+		return false;
+	}
+
+	if (_show_instruments == Gtkmm2ext::Off && info->is_instrument()) {
+		return false;
+	}
+	if (_show_analysers == Gtkmm2ext::Off && info->in_category ("Analyser")) {
+		return false;
+	}
+	if (_show_utils == Gtkmm2ext::Off && info->in_category ("Utility")) {
+		return false;
+	}
+
+	/* NB once lilv_node_as_string() does honor translation AND
+	 * the lv2 onthology provides localized class name,
+	 * PluginInfo will need methods for Util & Analysis.
+	 */
+	bool exp_ok = false;
+	if (_show_instruments == Gtkmm2ext::ExplicitActive && info->is_instrument()) {
+		exp_ok = true;
+	}
+	if (_show_analysers == Gtkmm2ext::ExplicitActive && info->in_category ("Analyser")) {
+		exp_ok = true;
+	}
+	if (_show_utils == Gtkmm2ext::ExplicitActive && info->in_category ("Utility")) {
+		exp_ok = true;
+	}
+	if (_show_instruments == Gtkmm2ext::ExplicitActive  || _show_analysers == Gtkmm2ext::ExplicitActive || _show_utils == Gtkmm2ext::ExplicitActive) {
+		if (!exp_ok) {
+			return false;
+		}
+	}
+
 	if (!filterstr.empty()) {
 
 		if (mode == _("Name contains")) {
@@ -527,8 +612,18 @@ PluginSelector::filter_mode_changed ()
 
 	if (mode == _("Favorites only") || mode == _("Hidden only")) {
 		filter_entry.set_sensitive (false);
+		filter_button.set_sensitive (false);
+		fil_hidden_button.set_sensitive (false);
+		fil_instruments_button.set_sensitive (false);
+		fil_analysis_button.set_sensitive (false);
+		fil_utils_button.set_sensitive (false);
 	} else {
 		filter_entry.set_sensitive (true);
+		filter_button.set_sensitive (true);
+		fil_hidden_button.set_sensitive (true);
+		fil_instruments_button.set_sensitive (true);
+		fil_analysis_button.set_sensitive (true);
+		fil_utils_button.set_sensitive (true);
 	}
 
 	refill ();
@@ -845,6 +940,84 @@ PluginSelector::hidden_changed (const std::string& path)
 	in_row_change = false;
 }
 
+bool
+PluginSelector::fil_hidden_button_release (GdkEventButton*)
+{
+	_show_hidden = (fil_hidden_button.active_state() == 0);
+	fil_hidden_button.set_active (_show_hidden);
+	refill ();
+	return false;
+}
+
+static Gtkmm2ext::ActiveState next_state (Gtkmm2ext::ActiveState s){
+	switch (s) {
+		case Gtkmm2ext::Off:
+			return Gtkmm2ext::ImplicitActive;
+			break;
+		case Gtkmm2ext::ImplicitActive:
+			return Gtkmm2ext::ExplicitActive;
+			break;
+		case Gtkmm2ext::ExplicitActive:
+			return Gtkmm2ext::Off;
+			break;
+		default: assert(0); break; // not reached
+	}
+}
+
+static Gtkmm2ext::ActiveState prev_state (Gtkmm2ext::ActiveState s){
+	switch (s) {
+		case Gtkmm2ext::Off:
+			return Gtkmm2ext::ExplicitActive;
+			break;
+		case Gtkmm2ext::ImplicitActive:
+			return Gtkmm2ext::Off;
+			break;
+		case Gtkmm2ext::ExplicitActive:
+			return Gtkmm2ext::ImplicitActive;
+			break;
+		default: assert(0); break; // not reached
+	}
+}
+
+bool
+PluginSelector::fil_instruments_button_release (GdkEventButton* ev)
+{
+	if (ev->button == 3) {
+		_show_instruments = prev_state (fil_instruments_button.active_state());
+	} else {
+		_show_instruments = next_state (fil_instruments_button.active_state());
+	}
+	fil_instruments_button.set_active_state (_show_instruments);
+	refill ();
+	return false;
+}
+
+bool
+PluginSelector::fil_analysis_button_release (GdkEventButton* ev)
+{
+	if (ev->button == 3) {
+		_show_analysers = prev_state (fil_analysis_button.active_state());
+	} else {
+		_show_analysers = next_state (fil_analysis_button.active_state());
+	}
+	fil_analysis_button.set_active_state (_show_analysers);
+	refill ();
+	return false;
+}
+
+bool
+PluginSelector::fil_utils_button_release (GdkEventButton* ev)
+{
+	if (ev->button == 3) {
+		_show_utils = prev_state (fil_utils_button.active_state());
+	} else {
+		_show_utils = next_state (fil_utils_button.active_state());
+	}
+	fil_utils_button.set_active_state (_show_utils);
+	refill ();
+	return false;
+}
+
 void
 PluginSelector::show_manager ()
 {
diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h
index 8c76965..a377d5b 100644
--- a/gtk2_ardour/plugin_selector.h
+++ b/gtk2_ardour/plugin_selector.h
@@ -23,12 +23,14 @@
 #include <gtkmm/dialog.h>
 #include <gtkmm/notebook.h>
 #include <gtkmm/treeview.h>
+#include "gtkmm2ext/dndtreeview.h"
 #include <gtkmm2ext/selector.h>
 
 #include "ardour/plugin.h"
 #include "ardour/session_handle.h"
 #include "plugin_interest.h"
 
+#include "ardour_button.h"
 #include "ardour_dialog.h"
 
 namespace ARDOUR {
@@ -61,6 +63,11 @@ class PluginSelector : public ArdourDialog
 	Gtk::Entry filter_entry;
 	Gtk::Button filter_button;
 
+	ArdourButton fil_hidden_button;
+	ArdourButton fil_instruments_button;
+	ArdourButton fil_analysis_button;
+	ArdourButton fil_utils_button;
+
 	void filter_button_clicked ();
 	void filter_entry_changed ();
 	void filter_mode_changed ();
@@ -93,7 +100,7 @@ class PluginSelector : public ArdourDialog
 	};
 	PluginColumns plugin_columns;
 	Glib::RefPtr<Gtk::ListStore> plugin_model;
-	Gtk::TreeView plugin_display;
+	Gtkmm2ext::DnDTreeView<ARDOUR::PluginInfoPtr> plugin_display;
 	Gtk::Button* btn_add;
 	Gtk::Button* btn_remove;
 
@@ -131,6 +138,11 @@ class PluginSelector : public ArdourDialog
 	bool show_this_plugin (const ARDOUR::PluginInfoPtr&, const std::string&);
 	void setup_filter_string (std::string&);
 
+	bool fil_hidden_button_release (GdkEventButton*);
+	bool fil_instruments_button_release (GdkEventButton*);
+	bool fil_analysis_button_release (GdkEventButton*);
+	bool fil_utils_button_release (GdkEventButton*);
+
 	void favorite_changed (const std::string& path);
 	void hidden_changed (const std::string& path);
 	bool in_row_change;
@@ -142,6 +154,11 @@ class PluginSelector : public ArdourDialog
 	Gtk::Menu* create_by_category_menu (ARDOUR::PluginInfoList&);
 	void build_plugin_menu ();
 	PBD::ScopedConnectionList plugin_list_changed_connection;
+
+	bool _show_hidden;
+	Gtkmm2ext::ActiveState _show_instruments;
+	Gtkmm2ext::ActiveState _show_analysers;
+	Gtkmm2ext::ActiveState _show_utils;
 };
 
 #endif // __ardour_plugin_selector_h__
diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc
index 37c0146..256a90d 100644
--- a/gtk2_ardour/plugin_ui.cc
+++ b/gtk2_ardour/plugin_ui.cc
@@ -484,7 +484,7 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
 	plugin->PresetAdded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
 	plugin->PresetRemoved.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
 	plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset, this), gui_context ());
-	plugin->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::parameter_changed, this, _1, _2), gui_context ());
+	plugin->PresetDirty.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset_modified, this), gui_context ());
 
 	insert->AutomationStateChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::automation_state_changed, this), gui_context());
 
@@ -589,7 +589,7 @@ void
 PlugUIBase::add_plugin_setting ()
 {
 #ifndef NO_PLUGIN_STATE
-	NewPluginPresetDialog d (plugin);
+	NewPluginPresetDialog d (plugin, _("New Preset"));
 
 	switch (d.run ()) {
 	case Gtk::RESPONSE_ACCEPT:
@@ -814,12 +814,6 @@ PlugUIBase::update_preset_modified ()
 }
 
 void
-PlugUIBase::parameter_changed (uint32_t, float)
-{
-	update_preset_modified ();
-}
-
-void
 PlugUIBase::preset_added_or_removed ()
 {
 	/* Update both the list and the currently-displayed preset */
diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h
index 41f4ef3..d2e5e21 100644
--- a/gtk2_ardour/plugin_ui.h
+++ b/gtk2_ardour/plugin_ui.h
@@ -170,7 +170,6 @@ class PlugUIBase : public virtual sigc::trackable, public PBD::ScopedConnectionL
 	void processor_active_changed (boost::weak_ptr<ARDOUR::Processor> p);
 	void plugin_going_away ();
 	void automation_state_changed ();
-	virtual void parameter_changed (uint32_t, float);
 	void preset_added_or_removed ();
 	void update_preset_modified ();
 
diff --git a/gtk2_ardour/po/de.po b/gtk2_ardour/po/de.po
index 44dae72..eb333b0 100644
--- a/gtk2_ardour/po/de.po
+++ b/gtk2_ardour/po/de.po
@@ -10,8 +10,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gtk-ardour 0.347.2\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-08-13 10:38+0200\n"
-"PO-Revision-Date: 2015-08-13 11:53+0200\n"
+"POT-Creation-Date: 2015-12-23 09:42+0100\n"
+"PO-Revision-Date: 2015-12-23 12:23+0100\n"
 "Last-Translator: Edgar Aichinger <edogawa at aon.at>\n"
 "Language-Team: German <ardour-dev at lists.ardour.org>\n"
 "Language: de\n"
@@ -23,259 +23,271 @@ msgstr ""
 "X-Poedit-Basepath: ../../\n"
 "X-Poedit-SearchPath-0: gtk2_ardour\n"
 
-#: about.cc:125
+#: about.cc:127
 msgid "Brian Ahr"
 msgstr "Brian Ahr"
 
-#: about.cc:126
+#: about.cc:128
 msgid "John Anderson"
 msgstr "John Anderson"
 
-#: about.cc:127
+#: about.cc:129
 msgid "Marcus Andersson"
 msgstr "Marcus Andersson"
 
-#: about.cc:128
+#: about.cc:130
 msgid "Nedko Arnaudov"
 msgstr "Nedko Arnaudov"
 
-#: about.cc:129
+#: about.cc:131
 msgid "Hans Baier"
 msgstr "Hans Baier"
 
-#: about.cc:130
+#: about.cc:132
 msgid "Ben Bell"
 msgstr "Ben Bell"
 
-#: about.cc:131
+#: about.cc:133
 msgid "Sakari Bergen"
 msgstr "Sakari Bergen"
 
-#: about.cc:132
+#: about.cc:134
 msgid "Christian Borss"
 msgstr "Christian Borss"
 
-#: about.cc:133
+#: about.cc:135
 msgid "Chris Cannam"
 msgstr "Chris Cannam"
 
-#: about.cc:134
+#: about.cc:136
 msgid "Jeremy Carter"
 msgstr "Jeremy Carter"
 
-#: about.cc:135
+#: about.cc:137
 msgid "Jesse Chappell"
 msgstr "Jesse Chappell"
 
-#: about.cc:136
+#: about.cc:138
 msgid "Thomas Charbonnel"
 msgstr "Thomas Charbonnel"
 
-#: about.cc:137
+#: about.cc:139
 msgid "Sam Chessman"
 msgstr "Sam Chessman"
 
-#: about.cc:138
+#: about.cc:140
 msgid "André Colomb"
 msgstr "André Colomb"
 
-#: about.cc:139
+#: about.cc:141
 msgid "Paul Davis"
 msgstr "Paul Davis"
 
-#: about.cc:140
+#: about.cc:142
 msgid "Gerard van Dongen"
 msgstr "Gerard van Dongen"
 
-#: about.cc:141
+#: about.cc:143
 msgid "John Emmas"
 msgstr "John Emmas"
 
-#: about.cc:142
+#: about.cc:144
 msgid "Colin Fletcher"
 msgstr "Colin Fletcher"
 
-#: about.cc:143
+#: about.cc:145
 msgid "Dave Flick"
 msgstr "Dave Flick"
 
-#: about.cc:144
+#: about.cc:146
 msgid "Hans Fugal"
 msgstr "Hans Fugal"
 
-#: about.cc:145
+#: about.cc:147
 msgid "Robin Gareus"
 msgstr "Robin Gareus"
 
-#: about.cc:146
+#: about.cc:148
+msgid "Nil Geisweiller"
+msgstr "Nil Geisweiller"
+
+#: about.cc:149
 msgid "Christopher George"
 msgstr "Christopher George"
 
-#: about.cc:147
+#: about.cc:150
 msgid "Chris Goddard"
 msgstr "Chris Goddard"
 
-#: about.cc:148
+#: about.cc:151
 msgid "J. Abelardo Gutierrez"
 msgstr "J. Abelardo Gutierrez"
 
-#: about.cc:149
+#: about.cc:152
 msgid "Jeremy Hall"
 msgstr "Jeremy Hall"
 
-#: about.cc:150
+#: about.cc:153
 msgid "Audun Halland"
 msgstr "Audun Halland"
 
-#: about.cc:151
+#: about.cc:154
 msgid "David Halter"
 msgstr "David Halter"
 
-#: about.cc:152
+#: about.cc:155
 msgid "Steve Harris"
 msgstr "Steve Harris"
 
-#: about.cc:153
+#: about.cc:156
 msgid "Melvin Ray Herr"
 msgstr "Melvin Ray Herr"
 
-#: about.cc:154
+#: about.cc:157
 msgid "Carl Hetherington"
 msgstr "Carl Hetherington"
 
-#: about.cc:155
+#: about.cc:158
 msgid "Rob Holland"
 msgstr "Rob Holland"
 
-#: about.cc:156
+#: about.cc:159
 msgid "Robert Jordens"
 msgstr "Robert Jordens"
 
-#: about.cc:157
+#: about.cc:160
 msgid "Stefan Kersten"
 msgstr "Stefan Kersten"
 
-#: about.cc:158
+#: about.cc:161
 msgid "Armand Klenk"
 msgstr "Armand Klenk"
 
-#: about.cc:159
+#: about.cc:162
 msgid "Julien de Kozak"
 msgstr "Julien de Kozak"
 
-#: about.cc:160
+#: about.cc:163
 msgid "Matt Krai"
 msgstr "Matt Krai"
 
-#: about.cc:161
+#: about.cc:164
 msgid "Georg Krause"
 msgstr "Georg Krause"
 
-#: about.cc:162
+#: about.cc:165
 msgid "Nick Lanham"
 msgstr "Nick Lanham"
 
-#: about.cc:163
+#: about.cc:166
 msgid "Colin Law"
 msgstr "Colin Law"
 
-#: about.cc:164
+#: about.cc:167
 msgid "Joshua Leach"
 msgstr "Joshua Leach"
 
-#: about.cc:165
+#: about.cc:168
 msgid "Ben Loftis"
 msgstr "Ben Loftis"
 
-#: about.cc:166
+#: about.cc:169
 msgid "Nick Mainsbridge"
 msgstr "Nick Mainsbridge"
 
-#: about.cc:167
+#: about.cc:170
 msgid "Tim Mayberry"
 msgstr "Tim Mayberry"
 
-#: about.cc:168
+#: about.cc:171
 msgid "Doug Mclain"
 msgstr "Doug Mclain"
 
-#: about.cc:169
+#: about.cc:172
 msgid "Todd Naugle"
 msgstr "Todd Naugle"
 
-#: about.cc:170
+#: about.cc:173
+msgid "André Nusser"
+msgstr "André Nusser"
+
+#: about.cc:174
+msgid "Bent Bisballe Nyeng"
+msgstr "Bent Bisballe Nyeng"
+
+#: about.cc:175
 msgid "Jack O'Quin"
 msgstr "Jack O'Quin"
 
-#: about.cc:171
+#: about.cc:176
 msgid "Nimal Ratnayake"
 msgstr "Nimal Ratnayake"
 
-#: about.cc:172
+#: about.cc:177
 msgid "David Robillard"
 msgstr "David Robillard"
 
-#: about.cc:173
+#: about.cc:178
 msgid "Taybin Rutkin"
 msgstr "Taybin Rutkin"
 
-#: about.cc:174
+#: about.cc:179
 msgid "Andreas Ruge"
 msgstr "Andreas Ruge"
 
-#: about.cc:175
+#: about.cc:180
 msgid "Sampo Savolainen"
 msgstr "Sampo Savolainen"
 
-#: about.cc:176
+#: about.cc:181
 msgid "Rodrigo Severo"
 msgstr "Rodrigo Severo"
 
-#: about.cc:177
+#: about.cc:182
 msgid "Per Sigmond"
 msgstr "Per Sigmond"
 
-#: about.cc:178
+#: about.cc:183
 msgid "Lincoln Spiteri"
 msgstr "Lincoln Spiteri"
 
-#: about.cc:179
+#: about.cc:184
 msgid "Mike Start"
 msgstr "Mike Start"
 
-#: about.cc:180
+#: about.cc:185
 msgid "Mark Stewart"
 msgstr "Mark Stewart"
 
-#: about.cc:181
+#: about.cc:186
 msgid "Roland Stigge"
 msgstr "Roland Stigge"
 
-#: about.cc:182
+#: about.cc:187
 msgid "Petter Sundlöf"
 msgstr "Petter Sundlöf"
 
-#: about.cc:183
+#: about.cc:188
 msgid "Mike Täht"
 msgstr "Mike Täht"
 
-#: about.cc:184
+#: about.cc:189
 msgid "Roy Vegard"
 msgstr "Roy Vegard"
 
-#: about.cc:185
+#: about.cc:190
 msgid "Thorsten Wilms"
 msgstr "Thorsten Wilms"
 
-#: about.cc:186
+#: about.cc:191
 msgid "Damien Zammit"
 msgstr "Damien Zammit"
 
-#: about.cc:187
+#: about.cc:192
 msgid "Grygorii Zharun"
 msgstr "Grygorii Zharun"
 
-#: about.cc:192
+#: about.cc:197
 msgid ""
 "French:\n"
 "\tAlain Fréhel <alain.frehel at free.fr>\n"
@@ -289,7 +301,7 @@ msgstr ""
 "\tMartin Blanchard\n"
 "\tRomain Arnaud <roming22 at gmail.com>\n"
 
-#: about.cc:193
+#: about.cc:198
 msgid ""
 "German:\n"
 "\tKarsten Petersen <kapet at kapet.de>\n"
@@ -309,7 +321,7 @@ msgstr ""
 "\tRichard Oax <richard at pagliacciempire.de>\n"
 "\tRobin Gloster <robin at loc-com.de>\n"
 
-#: about.cc:200
+#: about.cc:205
 msgid ""
 "Italian:\n"
 "\tFilippo Pappalardo <filippo at email.it>\n"
@@ -319,7 +331,7 @@ msgstr ""
 "\tFilippo Pappalardo <filippo at email.it>\n"
 "\tRaffaele Morelli <raffaele.morelli at gmail.com>\n"
 
-#: about.cc:201
+#: about.cc:206
 msgid ""
 "Portuguese:\n"
 "\tRui Nuno Capela <rncbc at rncbc.org>\n"
@@ -327,7 +339,7 @@ msgstr ""
 "Portugiesisch:\n"
 "\tRui Nuno Capela <rncbc at rncbc.org>\n"
 
-#: about.cc:202
+#: about.cc:207
 msgid ""
 "Brazilian Portuguese:\n"
 "\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
@@ -337,7 +349,7 @@ msgstr ""
 "\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
 "\tChris Ross <chris at tebibyte.org>\n"
 
-#: about.cc:204
+#: about.cc:209
 msgid ""
 "Spanish:\n"
 "\t Alex Krohn <alexkrohn at fastmail.fm>\n"
@@ -347,7 +359,7 @@ msgstr ""
 "\t Alex Krohn <alexkrohn at fastmail.fm>\n"
 "\tPablo Fernández <pablo.fbus at gmail.com>\n"
 
-#: about.cc:205
+#: about.cc:210
 msgid ""
 "Russian:\n"
 "\t Igor Blinov <pitstop at nm.ru>\n"
@@ -357,7 +369,7 @@ msgstr ""
 "\t Igor Blinov <pitstop at nm.ru>\n"
 "\tAlexandre Prokoudine <alexandre.prokoudine at gmail.com>\n"
 
-#: about.cc:207
+#: about.cc:212
 msgid ""
 "Greek:\n"
 "\t Klearchos Gourgourinis <muadib at in.gr>\n"
@@ -365,7 +377,7 @@ msgstr ""
 "Griechisch:\n"
 "\t Klearchos Gourgourinis <muadib at in.gr>\n"
 
-#: about.cc:208
+#: about.cc:213
 msgid ""
 "Swedish:\n"
 "\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
@@ -373,7 +385,7 @@ msgstr ""
 "Schwedisch:\n"
 "\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
 
-#: about.cc:209
+#: about.cc:214
 msgid ""
 "Polish:\n"
 "\t Piotr Zaryk <pzaryk at gmail.com>\n"
@@ -381,7 +393,7 @@ msgstr ""
 "Polnisch:\n"
 "\t Piotr Zaryk <pzaryk at gmail.com>\n"
 
-#: about.cc:210
+#: about.cc:215
 msgid ""
 "Czech:\n"
 "\t Pavel Fric <pavelfric at seznam.cz>\n"
@@ -389,7 +401,7 @@ msgstr ""
 "Tschechisch:\n"
 "\t Pavel Fric <pavelfric at seznam.cz>\n"
 
-#: about.cc:211
+#: about.cc:216
 msgid ""
 "Norwegian:\n"
 "\t Eivind Ødegård\n"
@@ -397,7 +409,7 @@ msgstr ""
 "Norwegisch:\n"
 "\t Eivind Ødegård\n"
 
-#: about.cc:212
+#: about.cc:217
 msgid ""
 "Chinese:\n"
 "\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
@@ -405,39 +417,65 @@ msgstr ""
 "Chinesisch:\n"
 "\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
 
-#: about.cc:592
+#: about.cc:597
+msgid "Intel 64-bit"
+msgstr "Intel 64-bit"
+
+#: about.cc:599
+msgid "Intel 32-bit"
+msgstr "Intel 32-bit"
+
+#: about.cc:601
+msgid "PowerPC 64-bit"
+msgstr "PowerPC 64-bit"
+
+#: about.cc:603
+msgid "PowerPC 32-bit"
+msgstr "PowerPC 32-bit"
+
+#: about.cc:605
+msgid "64-bit"
+msgstr "64-bit"
+
+#: about.cc:607
+msgid "32-bit"
+msgstr "32-bit"
+
+#: about.cc:615
 msgid "Copyright (C) 1999-2015 Paul Davis\n"
 msgstr "Copyright (C) 1999-2015 Paul Davis\n"
 
-#: about.cc:596
+#: about.cc:619
 msgid "http://ardour.org/"
 msgstr "http://ardour.org/"
 
-#: about.cc:597
+#: about.cc:620
 msgid ""
 "%1%2\n"
-"(built from revision %3)"
+"(built from revision %3)\n"
+"%4"
 msgstr ""
 "%1%2\n"
-"(kompiliert aus Revision %3)"
+"(erzeugt aus Revision %3)\n"
+"%4"
 
-#: about.cc:601
+#: about.cc:625
 msgid "Config"
 msgstr "Konfiguration"
 
-#: actions.cc:85
+#: actions.cc:83
 msgid "Loading menus from %1"
 msgstr "Lade Menüs von %1"
 
-#: actions.cc:88 actions.cc:89
+#: actions.cc:86 actions.cc:87
 msgid "badly formatted menu definition file: %1"
 msgstr "schlecht formatierte Menüdefinitions-Datei: %1"
 
-#: actions.cc:91
+#: actions.cc:89
 msgid "%1 menu definition file not found"
 msgstr "Konnte die %1 Menü-Definitionsdatei nicht finden"
 
-#: actions.cc:95 actions.cc:96
+#: actions.cc:93 actions.cc:94
 msgid "%1 will not work without a valid menu definition file"
 msgstr "%1 wird ohne gültige Menüdefinitions-Datei nicht funktionieren"
 
@@ -473,15 +511,15 @@ msgstr "Audio+MIDI-Spuren"
 msgid "Busses"
 msgstr "Audiobusse"
 
-#: add_route_dialog.cc:83 add_route_dialog.cc:559
+#: add_route_dialog.cc:83 add_route_dialog.cc:554
 msgid "First"
 msgstr "Zuerst"
 
-#: add_route_dialog.cc:84 add_route_dialog.cc:563
+#: add_route_dialog.cc:84 add_route_dialog.cc:558
 msgid "Before Selection"
 msgstr "Vor Auswahl"
 
-#: add_route_dialog.cc:85 add_route_dialog.cc:561
+#: add_route_dialog.cc:85 add_route_dialog.cc:556
 msgid "After Selection"
 msgstr "Nach Auswahl"
 
@@ -494,11 +532,11 @@ msgid "Add:"
 msgstr "Erstelle:"
 
 #: add_route_dialog.cc:116 time_fx_dialog.cc:91 add_video_dialog.cc:135
-#: video_server_dialog.cc:121
+#: video_server_dialog.cc:118
 msgid "<b>Options</b>"
 msgstr "<b>Optionen</b>"
 
-#: add_route_dialog.cc:126 bundle_manager.cc:193 region_editor.cc:50
+#: add_route_dialog.cc:126 bundle_manager.cc:193 region_editor.cc:52
 #: route_group_dialog.cc:71
 msgid "Name:"
 msgstr "Name:"
@@ -512,23 +550,25 @@ msgid "Insert:"
 msgstr "Insert:"
 
 #: add_route_dialog.cc:223 add_route_dialog.cc:232 add_route_dialog.cc:306
-#: ardour_ui_ed.cc:548 engine_dialog.cc:240 rc_option_editor.cc:2279
-#: rc_option_editor.cc:2281 rc_option_editor.cc:2283 rc_option_editor.cc:2301
-#: rc_option_editor.cc:2303 rc_option_editor.cc:2311 rc_option_editor.cc:2313
-#: rc_option_editor.cc:2331 rc_option_editor.cc:2344 rc_option_editor.cc:2346
-#: rc_option_editor.cc:2348 rc_option_editor.cc:2393 rc_option_editor.cc:2395
-#: rc_option_editor.cc:2397 rc_option_editor.cc:2405 rc_option_editor.cc:2413
-#: rc_option_editor.cc:2415 rc_option_editor.cc:2423
+#: ardour_ui_ed.cc:574 engine_dialog.cc:242 rc_option_editor.cc:2257
+#: rc_option_editor.cc:2259 rc_option_editor.cc:2261 rc_option_editor.cc:2279
+#: rc_option_editor.cc:2281 rc_option_editor.cc:2290 rc_option_editor.cc:2292
+#: rc_option_editor.cc:2310 rc_option_editor.cc:2323 rc_option_editor.cc:2326
+#: rc_option_editor.cc:2328 rc_option_editor.cc:2373 rc_option_editor.cc:2375
+#: rc_option_editor.cc:2377 rc_option_editor.cc:2385 rc_option_editor.cc:2393
+#: rc_option_editor.cc:2395 rc_option_editor.cc:2403
 msgid "Audio"
 msgstr "Audio"
 
 #: add_route_dialog.cc:224 add_route_dialog.cc:235 add_route_dialog.cc:307
-#: editor_actions.cc:109 engine_dialog.cc:242 missing_file_dialog.cc:56
-#: rc_option_editor.cc:2558 rc_option_editor.cc:2568 rc_option_editor.cc:2576
-#: rc_option_editor.cc:2584 rc_option_editor.cc:2593 rc_option_editor.cc:2601
-#: rc_option_editor.cc:2609 rc_option_editor.cc:2617 rc_option_editor.cc:2626
-#: rc_option_editor.cc:2635 rc_option_editor.cc:2644 rc_option_editor.cc:2652
-#: rc_option_editor.cc:2660 rc_option_editor.cc:2668 rc_option_editor.cc:2691
+#: editor_actions.cc:110 engine_dialog.cc:244 missing_file_dialog.cc:60
+#: rc_option_editor.cc:2536 rc_option_editor.cc:2538 rc_option_editor.cc:2548
+#: rc_option_editor.cc:2557 rc_option_editor.cc:2565 rc_option_editor.cc:2573
+#: rc_option_editor.cc:2581 rc_option_editor.cc:2589 rc_option_editor.cc:2591
+#: rc_option_editor.cc:2599 rc_option_editor.cc:2601 rc_option_editor.cc:2609
+#: rc_option_editor.cc:2618 rc_option_editor.cc:2620 rc_option_editor.cc:2628
+#: rc_option_editor.cc:2636 rc_option_editor.cc:2645 rc_option_editor.cc:2654
+#: rc_option_editor.cc:2677
 msgid "MIDI"
 msgstr "MIDI"
 
@@ -554,8 +594,8 @@ msgstr ""
 "Falls Sie nicht vorhaben, so ein Plugin zu benutzen, verwenden Sie "
 "stattdessen eine normale Audio- oder MIDI-Spur"
 
-#: add_route_dialog.cc:327 add_route_dialog.cc:346 editor_actions.cc:431
-#: editor_rulers.cc:251 time_axis_view.cc:1385
+#: add_route_dialog.cc:327 add_route_dialog.cc:346 editor_actions.cc:438
+#: editor_rulers.cc:250 time_axis_view.cc:1383
 msgid "Normal"
 msgstr "Normal"
 
@@ -567,7 +607,7 @@ msgstr "Non Layered"
 msgid "Tape"
 msgstr "Band"
 
-#: add_route_dialog.cc:431 monitor_section.cc:296
+#: add_route_dialog.cc:431 monitor_section.cc:264
 msgid "Mono"
 msgstr "Mono"
 
@@ -599,7 +639,7 @@ msgstr "8 Kanäle"
 msgid "12 Channel"
 msgstr "12 Kanäle"
 
-#: add_route_dialog.cc:483 mixer_strip.cc:1898 mixer_strip.cc:2306
+#: add_route_dialog.cc:483 mixer_strip.cc:1918 mixer_strip.cc:2351
 msgid "Custom"
 msgstr "Benutzerdefiniert"
 
@@ -615,7 +655,7 @@ msgstr "Keine Gruppe"
 msgid "Ambiguous File"
 msgstr "Mehrmals gefundene Datei"
 
-#: ambiguous_file_dialog.cc:35
+#: ambiguous_file_dialog.cc:37
 msgid ""
 "%1 has found the file <i>%2</i> in the following places:\n"
 "\n"
@@ -623,7 +663,7 @@ msgstr ""
 "%1 hat die Datei <i>%2</i> an den folgenden Orten gefunden:\n"
 "\n"
 
-#: ambiguous_file_dialog.cc:44
+#: ambiguous_file_dialog.cc:46
 msgid ""
 "\n"
 "\n"
@@ -633,7 +673,7 @@ msgstr ""
 "\n"
 "Bitte wähle den Pfad der gewünschten Datei aus."
 
-#: ambiguous_file_dialog.cc:46 missing_file_dialog.cc:46
+#: ambiguous_file_dialog.cc:48 missing_file_dialog.cc:50
 msgid "Done"
 msgstr "Fertig"
 
@@ -673,16 +713,16 @@ msgstr "Normalisieren"
 msgid "FFT analysis window"
 msgstr "FFT-Analysefenster"
 
-#: analysis_window.cc:60 editor.cc:1835
+#: analysis_window.cc:60 editor.cc:1848
 msgid "Spectral Analysis"
 msgstr "FFT-Analyse"
 
-#: analysis_window.cc:67 editor_actions.cc:142 session_metadata_dialog.cc:667
+#: analysis_window.cc:67 editor_actions.cc:143 session_metadata_dialog.cc:667
 msgid "Track"
 msgstr "Spur"
 
-#: analysis_window.cc:68 editor_actions.cc:657 mixer_ui.cc:131
-#: mixer_ui.cc:1874
+#: analysis_window.cc:68 editor_actions.cc:664 mixer_ui.cc:135
+#: mixer_ui.cc:2035
 msgid "Show"
 msgstr "Anzeigen"
 
@@ -700,7 +740,7 @@ msgstr ""
 msgid "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
 msgstr "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
 
-#: ardour_ui.cc:172
+#: ardour_ui.cc:174
 msgid ""
 "%1 %2.x has discovered configuration files from %1 %3.x.\n"
 "\n"
@@ -714,83 +754,83 @@ msgstr ""
 "\n"
 "(Dies erfordert einen Neustart von %1.)"
 
-#: ardour_ui.cc:252 editor_actions.cc:651 region_editor.cc:51
+#: ardour_ui.cc:253 editor_actions.cc:658 region_editor.cc:53
 msgid "Audition"
 msgstr "Vorhören"
 
-#: ardour_ui.cc:253 editor_actions.cc:136 mixer_strip.cc:2078
-#: monitor_section.cc:376 rc_option_editor.cc:2433 route_time_axis.cc:254
-#: route_time_axis.cc:2739
+#: ardour_ui.cc:254 editor_actions.cc:137 mixer_strip.cc:2101
+#: monitor_section.cc:321 rc_option_editor.cc:2413 route_time_axis.cc:255
+#: route_time_axis.cc:2748
 msgid "Solo"
 msgstr "Solo"
 
-#: ardour_ui.cc:254 rc_option_editor.cc:1192
+#: ardour_ui.cc:255 rc_option_editor.cc:1356
 msgid "Feedback"
 msgstr "Feedback"
 
-#: ardour_ui.cc:265 speaker_dialog.cc:36
+#: ardour_ui.cc:264 speaker_dialog.cc:36
 msgid "Speaker Configuration"
 msgstr "Lautsprechereinstellung"
 
-#: ardour_ui.cc:266 keyeditor.cc:53
+#: ardour_ui.cc:265 keyeditor.cc:53
 msgid "Key Bindings"
 msgstr "Tastaturkürzel"
 
-#: ardour_ui.cc:267
+#: ardour_ui.cc:266
 msgid "Preferences"
 msgstr "Globale Einstellungen"
 
-#: ardour_ui.cc:268 ardour_ui.cc:275
+#: ardour_ui.cc:267 ardour_ui.cc:274
 msgid "Add Tracks/Busses"
 msgstr "Spuren/Busse hinzufügen"
 
-#: ardour_ui.cc:269
+#: ardour_ui.cc:268
 msgid "About"
 msgstr "Ãœber..."
 
-#: ardour_ui.cc:270 location_ui.cc:1141 session_option_editor.cc:189
-#: session_option_editor.cc:195 session_option_editor.cc:202
+#: ardour_ui.cc:269 location_ui.cc:1143 session_option_editor.cc:210
+#: session_option_editor.cc:216 session_option_editor.cc:223
 msgid "Locations"
 msgstr "Dateiorte"
 
-#: ardour_ui.cc:271 route_params_ui.cc:59 route_params_ui.cc:630
+#: ardour_ui.cc:270 route_params_ui.cc:59 route_params_ui.cc:630
 msgid "Tracks and Busses"
 msgstr "Spuren/Busse"
 
-#: ardour_ui.cc:272 engine_dialog.cc:74
+#: ardour_ui.cc:271 engine_dialog.cc:73
 msgid "Audio/MIDI Setup"
 msgstr "Audio/MIDI Einstellungen"
 
-#: ardour_ui.cc:273
+#: ardour_ui.cc:272
 msgid "Video Export Dialog"
 msgstr "Videoexport-Dialog"
 
-#: ardour_ui.cc:274
+#: ardour_ui.cc:273
 msgid "Properties"
 msgstr "Projekteinstellungen"
 
-#: ardour_ui.cc:276 bundle_manager.cc:264
+#: ardour_ui.cc:275 bundle_manager.cc:264
 msgid "Bundle Manager"
 msgstr "Bundle Manager"
 
-#: ardour_ui.cc:277 big_clock_window.cc:37
+#: ardour_ui.cc:276 big_clock_window.cc:37
 msgid "Big Clock"
 msgstr "Große Zeitanzeige"
 
-#: ardour_ui.cc:278
+#: ardour_ui.cc:277
 msgid "Audio Connections"
 msgstr "Audio-Verbindungen"
 
-#: ardour_ui.cc:279
+#: ardour_ui.cc:278
 msgid "MIDI Connections"
 msgstr "MIDI-Verbindungen"
 
-#: ardour_ui.cc:293
+#: ardour_ui.cc:295
 msgid "Your configuration files were copied. You can now restart %1."
 msgstr ""
 "Ihre Konfigurationsdateien wurden kopiert. Sie können jetzt %1 neu starten."
 
-#: ardour_ui.cc:519
+#: ardour_ui.cc:527
 msgid ""
 "The audio backend was shutdown because:\n"
 "\n"
@@ -800,7 +840,7 @@ msgstr ""
 "\n"
 "%1"
 
-#: ardour_ui.cc:521
+#: ardour_ui.cc:529
 msgid ""
 "The audio backend has either been shutdown or it\n"
 "disconnected %1 because %1\n"
@@ -812,7 +852,7 @@ msgstr ""
 "war. Sie sollten versuchen, das Audiobackend \n"
 "neu zu starten und das Projekt zu speichern."
 
-#: ardour_ui.cc:545
+#: ardour_ui.cc:553
 msgid ""
 "Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. "
 "Please see the log window for further details."
@@ -820,39 +860,39 @@ msgstr ""
 "Audio Unit Plugin Scan fehlgeschlagen. Automatische AU Scans wurden "
 "deaktiviert. Weitere Einzelheiten finden Sie im Logfenster."
 
-#: ardour_ui.cc:546
+#: ardour_ui.cc:554
 msgid "Audio Unit Plugin Scan Failed:"
 msgstr "Audio Unit Plugin Scan fehlgeschlagen:"
 
-#: ardour_ui.cc:877
+#: ardour_ui.cc:903
 msgid "NSM server did not announce itself"
 msgstr "Der NSM Server hat sich nicht angemeldet"
 
-#: ardour_ui.cc:890
+#: ardour_ui.cc:916
 msgid "NSM: no client ID provided"
 msgstr "NSM: keine Client-ID verfügbar"
 
-#: ardour_ui.cc:897
+#: ardour_ui.cc:923
 msgid "NSM: no session created"
 msgstr "NSM: kein Projekt erzeugt"
 
-#: ardour_ui.cc:920
+#: ardour_ui.cc:946
 msgid "NSM: initialization failed"
 msgstr "NSM: Initialisierung gescheitert"
 
-#: ardour_ui.cc:952
+#: ardour_ui.cc:978
 msgid "Free/Demo Version Warning"
 msgstr "Demoversionswarnung"
 
-#: ardour_ui.cc:954
+#: ardour_ui.cc:980
 msgid "Subscribe and support development of %1"
 msgstr "%1 abonnieren und die Entwicklung unterstützen"
 
-#: ardour_ui.cc:955
+#: ardour_ui.cc:981
 msgid "Don't warn me about this again"
 msgstr "Nicht noch einmal warnen"
 
-#: ardour_ui.cc:957
+#: ardour_ui.cc:983
 msgid ""
 "<span weight=\"bold\" size=\"large\">%1</span>\n"
 "\n"
@@ -870,15 +910,15 @@ msgstr ""
 "\n"
 "%4"
 
-#: ardour_ui.cc:958
+#: ardour_ui.cc:984
 msgid "This is a free/demo version of %1"
 msgstr "Dies ist eine freie Demoversion von %1"
 
-#: ardour_ui.cc:959
+#: ardour_ui.cc:985
 msgid "It will not restore OR save any plugin settings"
 msgstr "Sie kann keine Plugin-Einstellungen speichern oder laden"
 
-#: ardour_ui.cc:960
+#: ardour_ui.cc:986
 msgid ""
 "If you load an existing session with plugin settings\n"
 "they will not be used and will be lost."
@@ -886,7 +926,7 @@ msgstr ""
 "Wenn Sie ein existierendes Projekt mit Plugin-Einstellungen laden, werden "
 "diese nicht benutzt und beim Speichern verloren gehen."
 
-#: ardour_ui.cc:962 plugin_ui.cc:579
+#: ardour_ui.cc:988 plugin_ui.cc:579
 msgid ""
 "To get full access to updates without this limitation\n"
 "consider becoming a subscriber for a low cost every month."
@@ -895,19 +935,19 @@ msgstr ""
 "Sie, uns durch ein Abonnement mit einem geringen monatlichen Betrag zu "
 "unterstützen."
 
-#: ardour_ui.cc:972
+#: ardour_ui.cc:998
 msgid "Quit now"
 msgstr "Jetzt beenden"
 
-#: ardour_ui.cc:973
+#: ardour_ui.cc:999
 msgid "Continue using %1"
 msgstr "%1 weiterhin benutzen"
 
-#: ardour_ui.cc:1006 startup.cc:346
+#: ardour_ui.cc:1032 startup.cc:348
 msgid "%1 is ready for use"
 msgstr "%1 ist nun bereit"
 
-#: ardour_ui.cc:1048
+#: ardour_ui.cc:1074
 msgid ""
 "WARNING: Your system has a limit for maximum amount of locked memory. This "
 "might cause %1 to run out of memory before your system runs out of memory. \n"
@@ -922,23 +962,23 @@ msgstr ""
 "Sie können die Speicherbegrenzung mit 'ulimit -l' einsehen und normalerweise "
 "in %2 verändern."
 
-#: ardour_ui.cc:1065
+#: ardour_ui.cc:1091
 msgid "Do not show this window again"
 msgstr "Diese Meldung nicht erneut anzeigen"
 
-#: ardour_ui.cc:1109
+#: ardour_ui.cc:1135
 msgid "Don't quit"
 msgstr "Abbrechen"
 
-#: ardour_ui.cc:1110
+#: ardour_ui.cc:1136
 msgid "Just quit"
 msgstr "Beenden ohne zu speichern"
 
-#: ardour_ui.cc:1111 ardour_ui.cc:4903
+#: ardour_ui.cc:1137 ardour_ui.cc:5008
 msgid "Save and quit"
 msgstr "Speichern und beenden"
 
-#: ardour_ui.cc:1121
+#: ardour_ui.cc:1147
 msgid ""
 "%1 was unable to save your session.\n"
 "\n"
@@ -952,11 +992,11 @@ msgstr ""
 "\n"
 "\"Trotzdem beenden\"."
 
-#: ardour_ui.cc:1171
+#: ardour_ui.cc:1197
 msgid "Unsaved Session"
 msgstr "Nicht gespeichertes Projekt"
 
-#: ardour_ui.cc:1192
+#: ardour_ui.cc:1218
 msgid ""
 "The session \"%1\"\n"
 "has not been saved.\n"
@@ -974,7 +1014,7 @@ msgstr ""
 "\n"
 "Wie wollen Sie vorgehen?"
 
-#: ardour_ui.cc:1195
+#: ardour_ui.cc:1221
 msgid ""
 "The snapshot \"%1\"\n"
 "has not been saved.\n"
@@ -992,93 +1032,106 @@ msgstr ""
 "\n"
 "Wie wollen Sie vorgehen?"
 
-#: ardour_ui.cc:1209
+#: ardour_ui.cc:1235
 msgid "Prompter"
 msgstr "Frage"
 
-#: ardour_ui.cc:1322 ardour_ui.cc:1330
+#: ardour_ui.cc:1349 ardour_ui.cc:1357
 msgid "Audio: <span foreground=\"red\">none</span>"
 msgstr "Audio: <span foreground=\"red\">Kein</span>"
 
-#: ardour_ui.cc:1334
+#: ardour_ui.cc:1361
 #, c-format
 msgid "Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"
 msgstr "Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"
 
-#: ardour_ui.cc:1338
+#: ardour_ui.cc:1365
 #, c-format
 msgid "Audio: <span foreground=\"green\">%<PRId64> kHz / %4.1f ms</span>"
 msgstr "Audio: <span foreground=\"green\">%<PRId64> kHz / %4.1f ms</span>"
 
-#: ardour_ui.cc:1356 export_video_dialog.cc:76
+#: ardour_ui.cc:1383 export_video_dialog.cc:76
 msgid "File:"
 msgstr "Datei:"
 
-#: ardour_ui.cc:1360
+#: ardour_ui.cc:1387
 msgid "BWF"
 msgstr "BWF"
 
-#: ardour_ui.cc:1363
+#: ardour_ui.cc:1390
 msgid "WAV"
 msgstr "WAV"
 
-#: ardour_ui.cc:1366
+#: ardour_ui.cc:1393
 msgid "WAV64"
 msgstr "WAV64"
 
-#: ardour_ui.cc:1369 session_option_editor.cc:185
+#: ardour_ui.cc:1396 session_option_editor.cc:202
 msgid "CAF"
 msgstr "CAF"
 
-#: ardour_ui.cc:1372
+#: ardour_ui.cc:1399
 msgid "AIFF"
 msgstr "AIFF"
 
-#: ardour_ui.cc:1375
+#: ardour_ui.cc:1402
 msgid "iXML"
 msgstr "iXML"
 
-#: ardour_ui.cc:1378
+#: ardour_ui.cc:1405 session_option_editor.cc:203
 msgid "RF64"
 msgstr "RF64"
 
-#: ardour_ui.cc:1386
+#: ardour_ui.cc:1408
+msgid "RF64/WAV"
+msgstr "RF64/WAV"
+
+#: ardour_ui.cc:1411
+msgid "MBWF"
+msgstr "MBWF"
+
+#: ardour_ui.cc:1419
 msgid "32-float"
 msgstr "32-float"
 
-#: ardour_ui.cc:1389
+#: ardour_ui.cc:1422
 msgid "24-int"
 msgstr "24-int"
 
-#: ardour_ui.cc:1392
+#: ardour_ui.cc:1425
 msgid "16-int"
 msgstr "16-int"
 
-#: ardour_ui.cc:1413
+#: ardour_ui.cc:1446
 #, c-format
 msgid "X: <span foreground=\"%s\">>10K</span>"
 msgstr "X: <span foreground=\"%s\">>10K</span>"
 
-#: ardour_ui.cc:1415
+#: ardour_ui.cc:1448
 #, c-format
 msgid "X: <span foreground=\"%s\">%u</span>"
 msgstr "X: <span foreground=\"%s\">%u</span>"
 
-#: ardour_ui.cc:1418
+#: ardour_ui.cc:1451
 #, c-format
 msgid "X: <span foreground=\"%s\">?</span>"
 msgstr "X: <span foreground=\"%s\">?</span>"
 
-#: ardour_ui.cc:1421
+#: ardour_ui.cc:1454
 msgid "Audio dropouts. Shift+click to reset"
 msgstr "Audio Dropouts. Zum Zurücksetzen Shift+Klick"
 
-#: ardour_ui.cc:1434
+#: ardour_ui.cc:1467
 #, c-format
 msgid "DSP: <span foreground=\"%s\">%5.1f%%</span>"
 msgstr "DSP: <span foreground=\"%s\">%5.1f%%</span>"
 
-#: ardour_ui.cc:1453
+#: ardour_ui.cc:1477
+#, c-format
+msgid "PkBld: <span foreground=\"%s\">%d</span>"
+msgstr "PkBld: <span foreground=\"%s\">%d</span>"
+
+#: ardour_ui.cc:1499
 #, c-format
 msgid ""
 "Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">"
@@ -1089,34 +1142,29 @@ msgstr ""
 "%%</span> <span foreground=\"green\">c:</span><span foreground=\"%s\">"
 "%<PRIu32>%%</span>"
 
-#: ardour_ui.cc:1494
+#: ardour_ui.cc:1540
 msgid "Disk: <span foreground=\"green\">Unknown</span>"
 msgstr "Disk: <span foreground=\"green\">Unbekannt</span>"
 
-#: ardour_ui.cc:1496
+#: ardour_ui.cc:1542
 msgid "Disk: <span foreground=\"green\">24hrs+</span>"
 msgstr "Disk: <span foreground=\"green\">24h+</span>"
 
-#: ardour_ui.cc:1514
+#: ardour_ui.cc:1560
 msgid "Disk: <span foreground=\"green\">>24 hrs</span>"
 msgstr "Disk: <span foreground=\"green\">>24 h</span>"
 
-#: ardour_ui.cc:1525
+#: ardour_ui.cc:1571
 #, c-format
 msgid "Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"
 msgstr "Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"
 
-#: ardour_ui.cc:1551
+#: ardour_ui.cc:1597
 #, c-format
 msgid "Timecode|TC: <span foreground=\"%s\">%s</span>"
 msgstr "TC: <span foreground=\"%s\">%s</span>"
 
-#: ardour_ui.cc:1672 ardour_ui.cc:1681 session_dialog.cc:318
-#: session_dialog.cc:323
-msgid "Recent Sessions"
-msgstr "Zuletzt verwendete Projekte"
-
-#: ardour_ui.cc:1760
+#: ardour_ui.cc:1675
 msgid ""
 "%1 is not connected to any audio backend.\n"
 "You cannot open or close sessions in this condition"
@@ -1124,27 +1172,27 @@ msgstr ""
 "%1 ist derzeit mit keinem Audiobackend verbunden.\n"
 "Daher können keine Projekte geöffnet oder geschlossen werden."
 
-#: ardour_ui.cc:1784
+#: ardour_ui.cc:1693
 msgid "Open Session"
 msgstr "Projekt öffnen"
 
-#: ardour_ui.cc:1809 session_dialog.cc:349 session_import_dialog.cc:170
+#: ardour_ui.cc:1717 session_dialog.cc:407 session_import_dialog.cc:170
 #: session_metadata_dialog.cc:858
 msgid "%1 sessions"
 msgstr "%1 Projekte"
 
-#: ardour_ui.cc:1846
+#: ardour_ui.cc:1748
 msgid "You cannot add a track without a session already loaded."
 msgstr ""
 "Sie können erst Spuren oder Busse hinzufügen, wenn ein Projekt geladen wurde."
 
-#: ardour_ui.cc:1854
+#: ardour_ui.cc:1756
 msgid "could not create %1 new mixed track"
 msgid_plural "could not create %1 new mixed tracks"
 msgstr[0] "konnte %1 neue Audio+MIDI-Spur nicht erstellen"
 msgstr[1] "konnte %1 neue Audio+MIDI-Spuren nicht erstellen"
 
-#: ardour_ui.cc:1860 ardour_ui.cc:1921
+#: ardour_ui.cc:1762 ardour_ui.cc:1823
 msgid ""
 "There are insufficient ports available\n"
 "to create a new track or bus.\n"
@@ -1156,24 +1204,24 @@ msgstr ""
 "Sie sollten %1 sichern, beenden und\n"
 " mit mehr Ports neustarten."
 
-#: ardour_ui.cc:1895
+#: ardour_ui.cc:1797
 msgid "You cannot add a track or bus without a session already loaded."
 msgstr ""
 "Sie können erst Spuren oder Busse hinzufügen, wenn ein Projekt geladen wurde."
 
-#: ardour_ui.cc:1904
+#: ardour_ui.cc:1806
 msgid "could not create %1 new audio track"
 msgid_plural "could not create %1 new audio tracks"
 msgstr[0] "konnte %1 neue Audiospur nicht erstellen."
 msgstr[1] "konnte %1 neue Audiospuren nicht erstellen."
 
-#: ardour_ui.cc:1913
+#: ardour_ui.cc:1815
 msgid "could not create %1 new audio bus"
 msgid_plural "could not create %1 new audio busses"
 msgstr[0] "konnte %1 neuen Audiobus nicht erstellen"
 msgstr[1] "konnte %1 neue Audiobusse nicht erstellen"
 
-#: ardour_ui.cc:2066
+#: ardour_ui.cc:1968
 msgid ""
 "Please create one or more tracks before trying to record.\n"
 "You can do this with the \"Add Track or Bus\" option in the Session menu."
@@ -1182,36 +1230,20 @@ msgstr ""
 "eine oder mehrere Spur hinzu. Die geht über \"Spur/Bus hinzufügen\"\n"
 "im Menüpunkt Projekt."
 
-#: ardour_ui.cc:2444
+#: ardour_ui.cc:2359
 #, c-format
 msgid "Copied %<PRId64> of %<PRId64>"
 msgstr "%<PRId64> von %<PRId64> kopiert"
 
-#: ardour_ui.cc:2498 save_as_dialog.cc:33
+#: ardour_ui.cc:2413 save_as_dialog.cc:33
 msgid "Save As"
 msgstr "Speichern unter"
 
-#: ardour_ui.cc:2526
+#: ardour_ui.cc:2441
 msgid "Save As failed: %1"
 msgstr "Sichern unter fehlgeschlagen: %1"
 
-#: ardour_ui.cc:2548
-msgid "Save as..."
-msgstr "Speichern unter..."
-
-#: ardour_ui.cc:2549 ardour_ui.cc:2628
-msgid "New session name"
-msgstr "Neuer Projektname"
-
-#: ardour_ui.cc:2551
-msgid "Take Snapshot"
-msgstr "Schnappschuss machen"
-
-#: ardour_ui.cc:2552
-msgid "Name of new snapshot"
-msgstr "Name für neuen Schnappschuss"
-
-#: ardour_ui.cc:2577
+#: ardour_ui.cc:2463
 msgid ""
 "To ensure compatibility with various systems\n"
 "snapshot names may not contain a '%1' character"
@@ -1219,25 +1251,37 @@ msgstr ""
 "Um die Kompatibilität mit verschiedenen Systemen sicher zu stellen,\n"
 "dürfen Namen von Schnappschüssen kein '%1'-Zeichen enthalten"
 
-#: ardour_ui.cc:2589
+#: ardour_ui.cc:2477
 msgid "Confirm Snapshot Overwrite"
 msgstr "Überschreiben des Schnappschusses bestätigen"
 
-#: ardour_ui.cc:2590
-msgid "A snapshot already exists with that name.  Do you want to overwrite it?"
+#: ardour_ui.cc:2478
+msgid "A snapshot already exists with that name. Do you want to overwrite it?"
 msgstr ""
-"Ein Schnappschuss mit diesem Namen existiert bereits. Wollen Sie ihn "
+"Ein Schnappschuss mit diesem Namen existiert bereits Wollen Sie sie "
 "überschreiben?"
 
-#: ardour_ui.cc:2593 utils_videotl.cc:74
-msgid "Overwrite"
-msgstr "Ãœberschreiben"
+#: ardour_ui.cc:2503
+msgid "Save as..."
+msgstr "Speichern unter..."
+
+#: ardour_ui.cc:2504 ardour_ui.cc:2553
+msgid "New session name"
+msgstr "Neuer Projektname"
+
+#: ardour_ui.cc:2506
+msgid "Take Snapshot"
+msgstr "Schnappschuss machen"
 
-#: ardour_ui.cc:2627
+#: ardour_ui.cc:2507
+msgid "Name of new snapshot"
+msgstr "Name für neuen Schnappschuss"
+
+#: ardour_ui.cc:2552
 msgid "Rename Session"
 msgstr "Projekt umbenennen"
 
-#: ardour_ui.cc:2642 ardour_ui.cc:3056 ardour_ui.cc:3094
+#: ardour_ui.cc:2567 ardour_ui.cc:3047 ardour_ui.cc:3085
 msgid ""
 "To ensure compatibility with various systems\n"
 "session names may not contain a '%1' character"
@@ -1245,14 +1289,14 @@ msgstr ""
 "Um die Kompatibilität mit verschiedenen Systemen sicher zu stellen,\n"
 "dürfen Projektnamen kein '%1'-Zeichen enthalten"
 
-#: ardour_ui.cc:2650
+#: ardour_ui.cc:2575
 msgid ""
 "That name is already in use by another directory/folder. Please try again."
 msgstr ""
 "Dieser Name wird schon von einem anderen Verzeichnis/Ordner benutzt. Bitte "
 "versuchen Sie einen anderen Namen."
 
-#: ardour_ui.cc:2659
+#: ardour_ui.cc:2584
 msgid ""
 "Renaming this session failed.\n"
 "Things could be seriously messed up at this point"
@@ -1260,19 +1304,28 @@ msgstr ""
 "Das Umbenennen des Projekts ist fehlgeschlagen.\n"
 "Dies könnte auf schwerwiegende Probleme hinweisen."
 
-#: ardour_ui.cc:2774
+#: ardour_ui.cc:2700 route_ui.cc:1871
+msgid "Confirm Template Overwrite"
+msgstr "Bestätige Überschreiben der Vorlage"
+
+#: ardour_ui.cc:2701 route_ui.cc:1872
+msgid "A template already exists with that name. Do you want to overwrite it?"
+msgstr ""
+"Eine Vorlage mit diesem Namen existiert bereits Wollen Sie sie überschreiben?"
+
+#: ardour_ui.cc:2725
 msgid "Save Template"
 msgstr "Als Vorlage Speichern"
 
-#: ardour_ui.cc:2775
+#: ardour_ui.cc:2726
 msgid "Name for template:"
 msgstr "Name für Vorlage"
 
-#: ardour_ui.cc:2776
+#: ardour_ui.cc:2727
 msgid "-template"
 msgstr "-Vorlage"
 
-#: ardour_ui.cc:2813
+#: ardour_ui.cc:2764
 msgid ""
 "This session\n"
 "%1\n"
@@ -1282,35 +1335,39 @@ msgstr ""
 "%1\n"
 "existiert bereits. Wollen Sie es öffnen?"
 
-#: ardour_ui.cc:2823
+#: ardour_ui.cc:2774
 msgid "Open Existing Session"
 msgstr "Vorhandenes Projekt öffnen"
 
-#: ardour_ui.cc:3084
+#: ardour_ui.cc:3075
 msgid "There is no existing session at \"%1\""
 msgstr "Es gibt kein Projekt in: \"%1\""
 
-#: ardour_ui.cc:3176
+#: ardour_ui.cc:3169
 msgid "Please wait while %1 loads your session"
 msgstr "Bitte warten Sie, während %1 das Projekt lädt"
 
-#: ardour_ui.cc:3191
+#: ardour_ui.cc:3184
 msgid "Port Registration Error"
 msgstr "Fehler bei der Registrierung von Ports"
 
-#: ardour_ui.cc:3192
+#: ardour_ui.cc:3185
 msgid "Click the Close button to try again."
 msgstr "Klicken Sie auf Schließen, um es erneut zu versuchen."
 
-#: ardour_ui.cc:3213
-msgid "Session \"%1 (snapshot %2)\" did not load successfully"
-msgstr "Projekt  \"%1 (Schnappschuss %2)\" konnte nicht geladen werden."
+#: ardour_ui.cc:3204
+msgid "Session \"%1 (snapshot %2)\" did not load successfully: %3"
+msgstr "Projekt \"%1 (Schnappschuss %2)\" konnte nicht geladen werden: %3"
 
-#: ardour_ui.cc:3219
+#: ardour_ui.cc:3210 ardour_ui.cc:3231 ardour_ui.cc:3328 ardour_ui.cc:3337
 msgid "Loading Error"
 msgstr "Fehler beim Laden"
 
-#: ardour_ui.cc:3241
+#: ardour_ui.cc:3225
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "Projekt  \"%1 (Schnappschuss %2)\" konnte nicht geladen werden."
+
+#: ardour_ui.cc:3253
 msgid ""
 "This session has been opened in read-only mode.\n"
 "\n"
@@ -1320,24 +1377,60 @@ msgstr ""
 "\n"
 "Aufnehmen oder Speichern wird nicht möglich sein."
 
-#: ardour_ui.cc:3246
+#: ardour_ui.cc:3258
 msgid "Read-only Session"
 msgstr "Schreibgeschütztes Projekt"
 
-#: ardour_ui.cc:3312
+#: ardour_ui.cc:3327
+msgid "Could not create session in \"%1\": %2"
+msgstr "Konnte Projekt in \"%1\" nicht erstellen: %2"
+
+#: ardour_ui.cc:3336
 msgid "Could not create session in \"%1\""
 msgstr "Konnte kein Projekt in \"%1\" anlegen"
 
-#: ardour_ui.cc:3461
+#: ardour_ui.cc:3376
+msgid ""
+"<b>Just ask and wait for an answer.\n"
+"It may take from minutes to hours.</b>"
+msgstr ""
+"<b>Stellen Sie Ihre Frage und warten auf Antwort.\n"
+"Es kann ein paar Minuten, aber vielleicht auch Stunden dauern.</b>"
+
+#: ardour_ui.cc:3378
+msgid "About the Chat"
+msgstr "Ãœber den Chat"
+
+#: ardour_ui.cc:3379
+msgid ""
+"When you're inside the chat just ask your question and wait for an answer. "
+"The chat is occupied by real people with real lives so many of them are "
+"passively online and might not read your question before minutes or hours "
+"later.\n"
+"So please be patient and wait for an answer.\n"
+"\n"
+"You should just leave the chat window open and check back regularly until "
+"someone has answered your question."
+msgstr ""
+"Wenn Sie im Chat sind, stellen Sie einfach Ihre Frage und warten auf "
+"Antwort. Der Chat wird mit echten Leuten mit echten Leben benutzt, daher "
+"sind viele von ihnen  passiv online und lesen Ihre Frage möglicherweise "
+"innerhalb von ein paar Minuten, oder auch erst Stunden später.\n"
+"Also seien Sie bitte geduldig und warten Sie auf Antwort.\n"
+"\n"
+"Lassen Sie einfach Ihr Chatfenster geöffnet und schauen gelegentlich nach, "
+"bis jemand auf Ihre Fragen geantwortet hat."
+
+#: ardour_ui.cc:3498
 msgid "No files were ready for clean-up"
 msgstr "Keine Audiodateien zum Aufräumen vorhanden"
 
-#: ardour_ui.cc:3465 ardour_ui.cc:3475 ardour_ui.cc:3608 ardour_ui.cc:3615
-#: ardour_ui_ed.cc:103
+#: ardour_ui.cc:3502 ardour_ui.cc:3512 ardour_ui.cc:3645 ardour_ui.cc:3652
+#: ardour_ui_ed.cc:104
 msgid "Clean-up"
 msgstr "Aufräumen"
 
-#: ardour_ui.cc:3466
+#: ardour_ui.cc:3503
 msgid ""
 "If this seems suprising, \n"
 "check for any existing snapshots.\n"
@@ -1349,19 +1442,19 @@ msgstr ""
 "sind sie wahrscheinlich noch in einem\n"
 "älteren Schnappschuss als Region eingebunden."
 
-#: ardour_ui.cc:3525
+#: ardour_ui.cc:3562
 msgid "kilo"
 msgstr "kilo"
 
-#: ardour_ui.cc:3528
+#: ardour_ui.cc:3565
 msgid "mega"
 msgstr "mega"
 
-#: ardour_ui.cc:3531
+#: ardour_ui.cc:3568
 msgid "giga"
 msgstr "giga"
 
-#: ardour_ui.cc:3536
+#: ardour_ui.cc:3573
 msgid ""
 "The following file was deleted from %2,\n"
 "releasing %3 %4bytes of disk space"
@@ -1375,7 +1468,7 @@ msgstr[1] ""
 "Die folgenden %1 Dateien wurden von %2\n"
 "gelöscht und gaben %3 %4bytes Speicherplatz frei"
 
-#: ardour_ui.cc:3543
+#: ardour_ui.cc:3580
 msgid ""
 "The following file was not in use and \n"
 "has been moved to: %2\n"
@@ -1413,11 +1506,11 @@ msgstr[1] ""
 "\n"
 "%3 %4bytes Speicherplatz freigegeben werden.\n"
 
-#: ardour_ui.cc:3603
+#: ardour_ui.cc:3640
 msgid "Are you sure you want to clean-up?"
 msgstr "Wollen Sie wirklich aufräumen?"
 
-#: ardour_ui.cc:3610
+#: ardour_ui.cc:3647
 msgid ""
 "Clean-up is a destructive operation.\n"
 "ALL undo/redo information will be lost if you clean-up.\n"
@@ -1429,41 +1522,41 @@ msgstr ""
 "Nach dem Aufräumen werden alle nicht benötigten Audiodateien in den \"dead "
 "sounds\" Ordner verschoben."
 
-#: ardour_ui.cc:3618
+#: ardour_ui.cc:3655
 msgid "CleanupDialog"
 msgstr "Aufräumdialog"
 
-#: ardour_ui.cc:3648
+#: ardour_ui.cc:3685
 msgid "Cleaned Files"
 msgstr "Aufgeräumte Dateien"
 
-#: ardour_ui.cc:3665
+#: ardour_ui.cc:3702
 msgid "deleted file"
 msgstr "gelöschte Datei"
 
-#: ardour_ui.cc:3803
+#: ardour_ui.cc:3895
 msgid "Video-Server was not launched by %1. The request to stop it is ignored."
 msgstr ""
 "Der Video-Server wurde nicht von %1 gestartet. Die Aufforderung ihn zu "
 "beenden wird ignoriert."
 
-#: ardour_ui.cc:3807
+#: ardour_ui.cc:3899
 msgid "Stop Video-Server"
 msgstr "Video-Server anhalten"
 
-#: ardour_ui.cc:3808
+#: ardour_ui.cc:3900
 msgid "Do you really want to stop the Video Server?"
 msgstr "Wollen Sie den Video-Server wirklich anhalten?"
 
-#: ardour_ui.cc:3811
+#: ardour_ui.cc:3903
 msgid "Yes, Stop It"
 msgstr "Ja, anhalten."
 
-#: ardour_ui.cc:3837
+#: ardour_ui.cc:3929
 msgid "The Video Server is already started."
 msgstr "Der Video-Server läuft bereits"
 
-#: ardour_ui.cc:3839
+#: ardour_ui.cc:3931
 msgid ""
 "An external Video Server is configured and can be reached. Not starting a "
 "new instance."
@@ -1471,7 +1564,7 @@ msgstr ""
 "Ein externer Video-Server wurde konfiguriert, ist aber nicht erreichbar. Es "
 "wird keine neue Instanz gestartet."
 
-#: ardour_ui.cc:3847 ardour_ui.cc:3952
+#: ardour_ui.cc:3939 ardour_ui.cc:4044
 msgid ""
 "Could not connect to the Video Server. Start it or configure its access URL "
 "in Preferences."
@@ -1480,40 +1573,48 @@ msgstr ""
 "ihn vorher starten oder die URL für den Zugriff in den Einstellungen "
 "anpassen."
 
-#: ardour_ui.cc:3877
+#: ardour_ui.cc:3969
 msgid "Specified docroot is not an existing directory."
 msgstr "Das eingestellte Dokumentenverzeichnis existiert nicht."
 
-#: ardour_ui.cc:3883 ardour_ui.cc:3889
+#: ardour_ui.cc:3975 ardour_ui.cc:3981
 msgid "Given Video Server is not an executable file."
 msgstr "Der eingestellte Video-Server ist keine ausführbare Datei."
 
-#: ardour_ui.cc:3923
+#: ardour_ui.cc:4015
 msgid "Cannot launch the video-server"
 msgstr "Kann den Videoserver nicht starten "
 
-#: ardour_ui.cc:3933
+#: ardour_ui.cc:4025
 msgid "Video-server was started but does not respond to requests..."
 msgstr "Viideoserver wurde gestartet, reagiert aber nicht auf Anfragen..."
 
-#: ardour_ui.cc:3978 editor_audio_import.cc:644
+#: ardour_ui.cc:4070 editor_audio_import.cc:644
 msgid "could not open %1"
 msgstr "Konnte %1 nicht öffnen"
 
-#: ardour_ui.cc:3982
+#: ardour_ui.cc:4074
 msgid "no video-file selected"
 msgstr "Es wurde keine Videodatei ausgewählt."
 
-#: ardour_ui.cc:4174
+#: ardour_ui.cc:4170
+msgid "No LTC detected, video will not be aligned."
+msgstr "Kein LTC entdeckt, Video wird nicht ausgerichtet."
+
+#: ardour_ui.cc:4176
+msgid "Align video-start to %1 [samples]"
+msgstr "Richte Video auf %1 [samples] aus"
+
+#: ardour_ui.cc:4310
 msgid "xrun"
 msgstr "xrun"
 
-#: ardour_ui.cc:4183
+#: ardour_ui.cc:4319
 msgid "Recording was stopped because your system could not keep up."
 msgstr ""
 "Die Aufnahme wurde gestoppt, da Ihr System nicht schnell genug folgen konnte."
 
-#: ardour_ui.cc:4212
+#: ardour_ui.cc:4348
 msgid ""
 "The disk system on your computer\n"
 "was not able to keep up with %1.\n"
@@ -1527,23 +1628,23 @@ msgstr ""
 "Die Daten konnten nicht schnell genug geschrieben\n"
 "werden, um die Aufnahme fortzuführen.\n"
 
-#: ardour_ui.cc:4285
+#: ardour_ui.cc:4421
 msgid "Scanning for plugins"
 msgstr "Suche nach Plugins"
 
-#: ardour_ui.cc:4287
+#: ardour_ui.cc:4423
 msgid "Cancel plugin scan"
 msgstr "Plugin-Suche abbrechen"
 
-#: ardour_ui.cc:4296
+#: ardour_ui.cc:4432
 msgid "Stop Timeout"
 msgstr "Stopp-Timeout"
 
-#: ardour_ui.cc:4303
+#: ardour_ui.cc:4439
 msgid "Scan Timeout"
 msgstr "Such-Timeout"
 
-#: ardour_ui.cc:4347
+#: ardour_ui.cc:4483
 msgid ""
 "The disk system on your computer\n"
 "was not able to keep up with %1.\n"
@@ -1557,11 +1658,11 @@ msgstr ""
 "Die Daten konnten nicht schnell genug gelesen\n"
 "werden, um die Wiedergabe aufrechtzuerhalten.\n"
 
-#: ardour_ui.cc:4387
+#: ardour_ui.cc:4523
 msgid "Crash Recovery"
 msgstr "Absturz-Wiederherstellung"
 
-#: ardour_ui.cc:4388
+#: ardour_ui.cc:4524
 msgid ""
 "This session appears to have been in the\n"
 "middle of recording when %1 or\n"
@@ -1579,19 +1680,19 @@ msgstr ""
 "für Sie wiederherstellen oder sie verwerfen.\n"
 "Bitte entscheiden Sie, wie Sie vorgehen möchten.\n"
 
-#: ardour_ui.cc:4400
+#: ardour_ui.cc:4536
 msgid "Ignore crash data"
 msgstr "Daten verwerfen"
 
-#: ardour_ui.cc:4401
+#: ardour_ui.cc:4537
 msgid "Recover from crash"
 msgstr "Daten wiederherstellen"
 
-#: ardour_ui.cc:4421
+#: ardour_ui.cc:4557
 msgid "Sample Rate Mismatch"
 msgstr "Samplerate passt nicht"
 
-#: ardour_ui.cc:4422
+#: ardour_ui.cc:4558
 msgid ""
 "This session was created with a sample rate of %1 Hz, but\n"
 "%2 is currently running at %3 Hz.  If you load this session,\n"
@@ -1602,23 +1703,15 @@ msgstr ""
 "%2 läuft derzeit mit %3 Hz. Wenn Sie dieses Projekt laden, \n"
 "wird Ihr Audiomaterial mit der falschen Samplerate abgespielt.\n"
 
-#: ardour_ui.cc:4431
+#: ardour_ui.cc:4567
 msgid "Do not load session"
 msgstr "Projekt nicht laden"
 
-#: ardour_ui.cc:4432
+#: ardour_ui.cc:4568
 msgid "Load session anyway"
 msgstr "Projekt trotzdem laden"
 
-#: ardour_ui.cc:4459
-msgid "Could not disconnect from Audio/MIDI engine"
-msgstr "Konnte Verbindung mit der Audio/MIDI Engine nicht trennen"
-
-#: ardour_ui.cc:4476 ardour_ui.cc:4479
-msgid "Could not reconnect to the Audio/MIDI engine"
-msgstr "Konnte nicht zur Audio/MIDI Engine wiederverbinden"
-
-#: ardour_ui.cc:4763
+#: ardour_ui.cc:4860
 msgid ""
 "%4This is a session from an older version of %3%5\n"
 "\n"
@@ -1645,41 +1738,41 @@ msgstr ""
 "\n"
 "Benutzen Sie von nun an die -2000 Version mit älteren Versionen von %3"
 
-#: ardour_ui.cc:4872
+#: ardour_ui.cc:4977
 msgid "This is a free/demo copy of %1. It has just switched to silent mode."
 msgstr ""
 "Dies ist eine freie Demoversion von %1. Sie hat sich gerade stummgeschaltet."
 
-#: ardour_ui.cc:4878
+#: ardour_ui.cc:4983
 msgid "%1 is now silent"
 msgstr "%1 ist nun stumm"
 
-#: ardour_ui.cc:4880
+#: ardour_ui.cc:4985
 msgid ""
 "Please consider paying for a copy of %1 - you can pay whatever you want."
 msgstr ""
 "Bitte ziehen Sie in Erwägung, für eine Kopie von %1 einen Geldbetrag - in "
 "beliebiger Höhe - zu zahlen."
 
-#: ardour_ui.cc:4881
+#: ardour_ui.cc:4986
 msgid "Better yet become a subscriber - subscriptions start at US$1 per month."
 msgstr ""
 "Besser noch, werden Sie ein Abonnent - Abonnements beginnen bei US$1 pro "
 "Monat."
 
-#: ardour_ui.cc:4882
+#: ardour_ui.cc:4987
 msgid "Pay for a copy (via the web)"
 msgstr "Für eine Kopie zahlen (über das WWW)"
 
-#: ardour_ui.cc:4883
+#: ardour_ui.cc:4988
 msgid "Become a subscriber (via the web)"
 msgstr "Abonnent werden (über das Web)"
 
-#: ardour_ui.cc:4902
+#: ardour_ui.cc:5007
 msgid "Remain silent"
 msgstr "Stumm bleiben"
 
-#: ardour_ui.cc:4904
+#: ardour_ui.cc:5009
 msgid "Give me more time"
 msgstr "Ich möchte mehr Zeit haben"
 
@@ -1705,7 +1798,7 @@ msgstr "Wiedergabe anhalten"
 
 #: ardour_ui2.cc:130
 msgid "Toggle record"
-msgstr "Aufnahmestatus aktivieren"
+msgstr "Aufnahmestatus umschalten"
 
 #: ardour_ui2.cc:131
 msgid "Play range/selection"
@@ -1737,8 +1830,8 @@ msgid "Return to last playback start when stopped"
 msgstr "Bei Stopp zum letzten Wiedergabepunkt springen"
 
 #: ardour_ui2.cc:137
-msgid "Playhead follows Range Selections and Edits"
-msgstr "Positionszeiger folgt Auswahl und Editierungen"
+msgid "Playhead follows range selections and edits"
+msgstr "Positionszeiger folgt Auswahl und Bearbeitungen"
 
 #: ardour_ui2.cc:138
 msgid "Be sensible about input monitoring"
@@ -1748,7 +1841,7 @@ msgstr "Automatisches Input Monitoring aktivieren"
 msgid "Enable/Disable audio click"
 msgstr "Aktiviert/Deaktiviert Klick"
 
-#: ardour_ui2.cc:140 monitor_section.cc:117
+#: ardour_ui2.cc:140 monitor_section.cc:124
 msgid ""
 "When active, something is soloed.\n"
 "Click to de-solo everything"
@@ -1758,11 +1851,11 @@ msgstr ""
 
 #: ardour_ui2.cc:141
 msgid ""
-"When active, auditioning is taking place\n"
+"When active, auditioning is taking place.\n"
 "Click to stop the audition"
 msgstr ""
-"Wird beim Vorhören aktiv.\n"
-"Klicken stoppt das Vorhören."
+"Wenn aktiv, wird vorgehört.\n"
+"Klicken, um das Vorhören zu beenden"
 
 #: ardour_ui2.cc:142
 msgid "When active, there is a feedback loop."
@@ -1816,442 +1909,469 @@ msgstr "[WARNUNG]:"
 msgid "[INFO]: "
 msgstr "[INFO]: "
 
-#: ardour_ui2.cc:255 ardour_ui_ed.cc:408
+#: ardour_ui2.cc:255 ardour_ui_ed.cc:430
 msgid "Auto Return"
 msgstr "Auto Return"
 
-#: ardour_ui2.cc:257 ardour_ui_ed.cc:411
+#: ardour_ui2.cc:257 ardour_ui_ed.cc:433
 msgid "Follow Edits"
 msgstr "Folge Bearbeitungen"
 
-#: ardour_ui2.cc:716 rc_option_editor.cc:2786
+#: ardour_ui2.cc:704 rc_option_editor.cc:2895
 msgid "GUI"
 msgstr "GUI"
 
-#: ardour_ui2.cc:733 rc_option_editor.cc:1778 rc_option_editor.cc:1796
-#: rc_option_editor.cc:1799 rc_option_editor.cc:1801 rc_option_editor.cc:1803
-#: rc_option_editor.cc:1811 rc_option_editor.cc:1819 rc_option_editor.cc:1821
-#: rc_option_editor.cc:1829 rc_option_editor.cc:1836 rc_option_editor.cc:1845
-#: rc_option_editor.cc:1847 rc_option_editor.cc:1849 rc_option_editor.cc:1857
-#: rc_option_editor.cc:1859 rc_option_editor.cc:1868
-#: session_option_editor.cc:321 session_option_editor.cc:323
-#: session_option_editor.cc:344 session_option_editor.cc:346
-#: session_option_editor.cc:348 session_option_editor.cc:355
-#: session_option_editor.cc:362 session_option_editor.cc:366
+#: ardour_ui2.cc:721 rc_option_editor.cc:1734 rc_option_editor.cc:1752
+#: rc_option_editor.cc:1755 rc_option_editor.cc:1757 rc_option_editor.cc:1759
+#: rc_option_editor.cc:1767 rc_option_editor.cc:1769 rc_option_editor.cc:1777
+#: rc_option_editor.cc:1785 rc_option_editor.cc:1792 rc_option_editor.cc:1801
+#: rc_option_editor.cc:1803 rc_option_editor.cc:1805 rc_option_editor.cc:1813
+#: rc_option_editor.cc:1815 rc_option_editor.cc:1824
+#: session_option_editor.cc:342 session_option_editor.cc:344
+#: session_option_editor.cc:365 session_option_editor.cc:367
+#: session_option_editor.cc:369 session_option_editor.cc:376
+#: session_option_editor.cc:383 session_option_editor.cc:387
 msgid "Misc"
 msgstr "Allgemein"
 
-#: ardour_ui_dependents.cc:76
+#: ardour_ui_dependents.cc:77
 msgid "Setup Editor"
 msgstr "Editor laden"
 
-#: ardour_ui_dependents.cc:78
+#: ardour_ui_dependents.cc:79
 msgid "Setup Mixer"
 msgstr "Mixer laden"
 
-#: ardour_ui_dependents.cc:84
+#: ardour_ui_dependents.cc:85
 msgid "Reload Session History"
 msgstr "Projekt-Aktionsverlauf laden"
 
-#: ardour_ui_dialogs.cc:250
+#: ardour_ui_dialogs.cc:251
 msgid "Don't close"
 msgstr "Abbrechen"
 
-#: ardour_ui_dialogs.cc:251
+#: ardour_ui_dialogs.cc:252
 msgid "Just close"
 msgstr "Ohne speichern schließen"
 
-#: ardour_ui_dialogs.cc:252
+#: ardour_ui_dialogs.cc:253
 msgid "Save and close"
 msgstr "Speichern und schließen"
 
-#: ardour_ui_dialogs.cc:362
+#: ardour_ui_dialogs.cc:363
 msgid "This screen is not tall enough to display the mixer window"
 msgstr ""
 "Dieser Bildschirm ist nicht hoch genug, um das Mixerfenster darzustellen"
 
-#: ardour_ui_ed.cc:102
+#: ardour_ui_ed.cc:103
 msgid "Session"
 msgstr "Projekt"
 
-#: ardour_ui_ed.cc:105 editor_actions.cc:138 editor_regions.cc:116
-#: port_group.cc:458 session_option_editor.cc:82 session_option_editor.cc:89
+#: ardour_ui_ed.cc:106 editor_actions.cc:139 editor_regions.cc:119
+#: port_group.cc:468 session_option_editor.cc:82 session_option_editor.cc:89
 msgid "Sync"
 msgstr "Sync"
 
-#: ardour_ui_ed.cc:106
+#: ardour_ui_ed.cc:107
 msgid "Options"
 msgstr "Optionen"
 
-#: ardour_ui_ed.cc:107
+#: ardour_ui_ed.cc:108
 msgid "Window"
 msgstr "Fenster"
 
-#: ardour_ui_ed.cc:108
+#: ardour_ui_ed.cc:109
 msgid "Help"
 msgstr "Hilfe"
 
-#: ardour_ui_ed.cc:109
+#: ardour_ui_ed.cc:110
 msgid "Misc. Shortcuts"
 msgstr "Verschiedenes"
 
-#: ardour_ui_ed.cc:110
+#: ardour_ui_ed.cc:111
 msgid "Audio File Format"
 msgstr "Audio-Dateiformat"
 
-#: ardour_ui_ed.cc:111
+#: ardour_ui_ed.cc:112
 msgid "File Type"
 msgstr "Dateiformat"
 
-#: ardour_ui_ed.cc:112 export_format_dialog.cc:67
+#: ardour_ui_ed.cc:113 export_format_dialog.cc:67
 msgid "Sample Format"
 msgstr "Sampleformat"
 
-#: ardour_ui_ed.cc:113 rc_option_editor.cc:2719 rc_option_editor.cc:2731
+#: ardour_ui_ed.cc:114 rc_option_editor.cc:2705 rc_option_editor.cc:2717
 msgid "Control Surfaces"
 msgstr "Eingabegeräte / Controller"
 
-#: ardour_ui_ed.cc:114 rc_option_editor.cc:2395 rc_option_editor.cc:2738
+#: ardour_ui_ed.cc:115 rc_option_editor.cc:2375 rc_option_editor.cc:2723
+#: rc_option_editor.cc:2725 rc_option_editor.cc:2735 rc_option_editor.cc:2742
+#: rc_option_editor.cc:2750 rc_option_editor.cc:2762 rc_option_editor.cc:2767
+#: rc_option_editor.cc:2769 rc_option_editor.cc:2774 rc_option_editor.cc:2781
+#: rc_option_editor.cc:2786 rc_option_editor.cc:2795 rc_option_editor.cc:2799
+#: rc_option_editor.cc:2808 rc_option_editor.cc:2816 rc_option_editor.cc:2820
+#: rc_option_editor.cc:2825 rc_option_editor.cc:2832 rc_option_editor.cc:2833
 msgid "Plugins"
 msgstr "Plugins"
 
-#: ardour_ui_ed.cc:115 rc_option_editor.cc:2853
+#: ardour_ui_ed.cc:116 rc_option_editor.cc:2969
 msgid "Metering"
 msgstr "Pegelanzeige"
 
-#: ardour_ui_ed.cc:116
+#: ardour_ui_ed.cc:117
 msgid "Fall Off Rate"
 msgstr "Abfall der Pegelanzeige"
 
-#: ardour_ui_ed.cc:117
+#: ardour_ui_ed.cc:118
 msgid "Hold Time"
 msgstr "Pegelanzeige halten"
 
-#: ardour_ui_ed.cc:118
+#: ardour_ui_ed.cc:119
 msgid "Denormal Handling"
 msgstr "Umgang mit Denormals"
 
-#: ardour_ui_ed.cc:122 route_time_axis.cc:1689
+#: ardour_ui_ed.cc:123 route_time_axis.cc:1694
 msgid "New..."
 msgstr "Neu..."
 
-#: ardour_ui_ed.cc:124
+#: ardour_ui_ed.cc:125
 msgid "Open..."
 msgstr "Öffnen..."
 
-#: ardour_ui_ed.cc:125
+#: ardour_ui_ed.cc:126
 msgid "Recent..."
 msgstr "Zuletzt verwendet..."
 
-#: ardour_ui_ed.cc:126 panner_editor.cc:29 playlist_selector.cc:64
+#: ardour_ui_ed.cc:127 panner_editor.cc:29 playlist_selector.cc:64
 msgid "Close"
 msgstr "Schließen"
 
-#: ardour_ui_ed.cc:129
+#: ardour_ui_ed.cc:130
 msgid "Add Track or Bus..."
 msgstr "Spur/Bus hinzufügen..."
 
-#: ardour_ui_ed.cc:134
+#: ardour_ui_ed.cc:135
+msgid "Duplicate Tracks/Busses..."
+msgstr "Spuren/Busse duplizieren..."
+
+#: ardour_ui_ed.cc:141
+msgid "Cancel Solo"
+msgstr "Solo abbrechen"
+
+#: ardour_ui_ed.cc:146
 msgid "Open Video"
 msgstr "Video öffnen"
 
-#: ardour_ui_ed.cc:137
+#: ardour_ui_ed.cc:149
 msgid "Remove Video"
 msgstr "Video entfernen"
 
-#: ardour_ui_ed.cc:140
-msgid "Export To Video File"
-msgstr "Exportiere Videodatei"
+#: ardour_ui_ed.cc:152
+msgid "Export to Video File"
+msgstr "Exportiere Video-Datei"
 
-#: ardour_ui_ed.cc:144
+#: ardour_ui_ed.cc:156
 msgid "Snapshot (& keep working on current version) ..."
 msgstr "Schnappschuss (& an dieser Version weiterarbeiten)..."
 
-#: ardour_ui_ed.cc:148
+#: ardour_ui_ed.cc:160
 msgid "Snapshot (& switch to new version) ..."
 msgstr "Schnappschuss (& zur neuen Version wechseln) ..."
 
-#: ardour_ui_ed.cc:152
+#: ardour_ui_ed.cc:164
 msgid "Save As..."
 msgstr "Speichern unter..."
 
-#: ardour_ui_ed.cc:156 editor_actions.cc:1783 editor_markers.cc:896
-#: editor_snapshots.cc:124 mixer_strip.cc:1564 route_time_axis.cc:1685
+#: ardour_ui_ed.cc:168 editor_actions.cc:1790 editor_markers.cc:903
+#: editor_snapshots.cc:136 mixer_strip.cc:1578 route_time_axis.cc:1690
 msgid "Rename..."
 msgstr "Umbenennen..."
 
-#: ardour_ui_ed.cc:160
+#: ardour_ui_ed.cc:172
 msgid "Save Template..."
 msgstr "Als Vorlage Speichern..."
 
-#: ardour_ui_ed.cc:163
+#: ardour_ui_ed.cc:175
 msgid "Metadata"
 msgstr "Metadaten"
 
-#: ardour_ui_ed.cc:166
+#: ardour_ui_ed.cc:178
 msgid "Edit Metadata..."
 msgstr "Metadaten bearbeiten..."
 
-#: ardour_ui_ed.cc:169
+#: ardour_ui_ed.cc:181
 msgid "Import Metadata..."
 msgstr "Metadaten importieren..."
 
-#: ardour_ui_ed.cc:172
-msgid "Export To Audio File(s)..."
-msgstr "Exportiere Audiodatei(en)..."
+#: ardour_ui_ed.cc:184
+msgid "Export to Audio File(s)..."
+msgstr "Exportiere Audio-Datei(en)..."
 
-#: ardour_ui_ed.cc:175
+#: ardour_ui_ed.cc:187
 msgid "Stem export..."
 msgstr "Stems exportieren..."
 
-#: ardour_ui_ed.cc:178 editor_export_audio.cc:65
+#: ardour_ui_ed.cc:190 editor_export_audio.cc:66
 #: export_channel_selector.cc:190 export_channel_selector.cc:576
 #: export_dialog.cc:129 export_video_dialog.cc:80
 msgid "Export"
 msgstr "Exportieren"
 
-#: ardour_ui_ed.cc:181
+#: ardour_ui_ed.cc:193
 msgid "Clean-up Unused Sources..."
 msgstr "Nicht benutzte Dateien entfernen..."
 
-#: ardour_ui_ed.cc:185
+#: ardour_ui_ed.cc:197
+msgid "Reset Peak Files"
+msgstr "Peakdateien zurücksetzen"
+
+#: ardour_ui_ed.cc:201
 msgid "Flush Wastebasket"
 msgstr "Müll leeren"
 
-#: ardour_ui_ed.cc:192
+#: ardour_ui_ed.cc:208
 msgid "Quit"
 msgstr "Beenden"
 
-#: ardour_ui_ed.cc:193 automation_time_axis.cc:543 editor_actions.cc:654
-#: editor_markers.cc:895 location_ui.cc:57 plugin_selector.cc:86
-#: route_time_axis.cc:865
+#: ardour_ui_ed.cc:209 automation_time_axis.cc:543 editor_actions.cc:661
+#: editor_markers.cc:902 location_ui.cc:59 plugin_selector.cc:95
+#: route_time_axis.cc:866
 msgid "Hide"
 msgstr "Verbergen"
 
-#: ardour_ui_ed.cc:197
+#: ardour_ui_ed.cc:213
 msgid "Maximise Editor Space"
 msgstr "Editor maximieren"
 
-#: ardour_ui_ed.cc:198
+#: ardour_ui_ed.cc:214
 msgid "Maximise Mixer Space"
 msgstr "Mixerfenster maximieren"
 
-#: ardour_ui_ed.cc:199
+#: ardour_ui_ed.cc:215
 msgid "Show Toolbars"
 msgstr "Zeige Werkzeugleisten"
 
-#: ardour_ui_ed.cc:203
+#: ardour_ui_ed.cc:218
+msgid "Toggle Mixer List"
+msgstr "Mixerliste umschalten"
+
+#: ardour_ui_ed.cc:221
+msgid "Toggle Monitor Section Visibility"
+msgstr "Sichtbarkeit der Monitorsektion umschalten"
+
+#: ardour_ui_ed.cc:225
 msgid "Show more UI preferences"
 msgstr "Mehr UI-Einstellungen anzeigen"
 
-#: ardour_ui_ed.cc:205 mixer_ui.cc:1945 mixer_ui.cc:1951
+#: ardour_ui_ed.cc:227 mixer_ui.cc:2107 mixer_ui.cc:2113
 msgid "Window|Mixer"
 msgstr "Mixer"
 
-#: ardour_ui_ed.cc:206
+#: ardour_ui_ed.cc:228
 msgid "Toggle Editor+Mixer"
 msgstr "Editor+Mixer umschalten"
 
-#: ardour_ui_ed.cc:207 meterbridge.cc:217 meterbridge.cc:223
+#: ardour_ui_ed.cc:229 meterbridge.cc:216 meterbridge.cc:222
 msgid "Window|Meterbridge"
 msgstr "Meterbridge"
 
-#: ardour_ui_ed.cc:209
+#: ardour_ui_ed.cc:231
 msgid "Reattach All Tearoffs"
 msgstr "Alle Abreißmenüs wieder anheften"
 
-#: ardour_ui_ed.cc:211 midi_tracer.cc:45
+#: ardour_ui_ed.cc:233 midi_tracer.cc:45
 msgid "MIDI Tracer"
 msgstr "Midisignale verfolgen"
 
-#: ardour_ui_ed.cc:213
+#: ardour_ui_ed.cc:235
 msgid "Chat"
 msgstr "Chat"
 
-#: ardour_ui_ed.cc:215
+#: ardour_ui_ed.cc:237
 msgid "Help|Manual"
 msgstr "Handbuch"
 
-#: ardour_ui_ed.cc:216
-msgid "Reference"
-msgstr "Referenz"
+#: ardour_ui_ed.cc:238
+msgid "Manual|Reference"
+msgstr "Handbuch|Referenz"
 
-#: ardour_ui_ed.cc:217
-msgid "Report A Bug"
+#: ardour_ui_ed.cc:239
+msgid "Report a Bug"
 msgstr "Einen Fehler melden"
 
-#: ardour_ui_ed.cc:218
+#: ardour_ui_ed.cc:240
 msgid "Cheat Sheet"
 msgstr "Cheat Sheet"
 
-#: ardour_ui_ed.cc:219
+#: ardour_ui_ed.cc:241
 msgid "Ardour Website"
 msgstr "Ardour Website"
 
-#: ardour_ui_ed.cc:220
+#: ardour_ui_ed.cc:242
 msgid "Ardour Development"
 msgstr "Ardour Entwicklung"
 
-#: ardour_ui_ed.cc:221
+#: ardour_ui_ed.cc:243
 msgid "User Forums"
 msgstr "Userforen"
 
-#: ardour_ui_ed.cc:222
-msgid "How to report a bug"
+#: ardour_ui_ed.cc:244
+msgid "How to Report a Bug"
 msgstr "Wie man einen Fehler meldet"
 
-#: ardour_ui_ed.cc:224 plugin_ui.cc:419
+#: ardour_ui_ed.cc:246 plugin_ui.cc:419
 msgid "Save"
 msgstr "Speichern"
 
-#: ardour_ui_ed.cc:232 rc_option_editor.cc:1879 rc_option_editor.cc:1890
-#: rc_option_editor.cc:1901 rc_option_editor.cc:1912 rc_option_editor.cc:1921
-#: rc_option_editor.cc:1934 rc_option_editor.cc:1947 rc_option_editor.cc:1956
-#: rc_option_editor.cc:1966 rc_option_editor.cc:1968 rc_option_editor.cc:1977
-#: rc_option_editor.cc:1993 rc_option_editor.cc:2014 rc_option_editor.cc:2032
-#: rc_option_editor.cc:2034 rc_option_editor.cc:2050 rc_option_editor.cc:2053
-#: rc_option_editor.cc:2055 rc_option_editor.cc:2072 rc_option_editor.cc:2083
+#: ardour_ui_ed.cc:254 rc_option_editor.cc:1835 rc_option_editor.cc:1846
+#: rc_option_editor.cc:1857 rc_option_editor.cc:1868 rc_option_editor.cc:1877
+#: rc_option_editor.cc:1890 rc_option_editor.cc:1903 rc_option_editor.cc:1912
+#: rc_option_editor.cc:1922 rc_option_editor.cc:1939 rc_option_editor.cc:1941
+#: rc_option_editor.cc:1950 rc_option_editor.cc:1966 rc_option_editor.cc:1987
+#: rc_option_editor.cc:2005 rc_option_editor.cc:2007 rc_option_editor.cc:2024
+#: rc_option_editor.cc:2027 rc_option_editor.cc:2029 rc_option_editor.cc:2046
+#: rc_option_editor.cc:2057
 msgid "Transport"
 msgstr "Transport"
 
-#: ardour_ui_ed.cc:238
+#: ardour_ui_ed.cc:260 engine_dialog.cc:88
 msgid "Stop"
 msgstr "Stopp"
 
-#: ardour_ui_ed.cc:241
+#: ardour_ui_ed.cc:263
 msgid "Roll"
 msgstr "Wiedergabe"
 
-#: ardour_ui_ed.cc:245 ardour_ui_ed.cc:248
+#: ardour_ui_ed.cc:267 ardour_ui_ed.cc:270
 msgid "Start/Stop"
 msgstr "Start/Stopp"
 
-#: ardour_ui_ed.cc:251
+#: ardour_ui_ed.cc:273
 msgid "Start/Continue/Stop"
 msgstr "Start/Stopp"
 
-#: ardour_ui_ed.cc:254
+#: ardour_ui_ed.cc:276
 msgid "Stop and Forget Capture"
 msgstr "Stopp + Aufnahme verwerfen"
 
-#: ardour_ui_ed.cc:264
-msgid "Transition To Roll"
-msgstr "Vorwärts (normal)"
+#: ardour_ui_ed.cc:286
+msgid "Transition to Roll"
+msgstr "Ãœbergang zu Wiedergabe"
 
-#: ardour_ui_ed.cc:268
-msgid "Transition To Reverse"
-msgstr "Rückwärts (normal)"
+#: ardour_ui_ed.cc:290
+msgid "Transition to Reverse"
+msgstr "Übergang zu rückwärtiger Wiedergabe"
 
-#: ardour_ui_ed.cc:272
+#: ardour_ui_ed.cc:294
 msgid "Play Loop Range"
 msgstr "Schleife wiedergeben"
 
-#: ardour_ui_ed.cc:275
+#: ardour_ui_ed.cc:297
 msgid "Play Selection"
 msgstr "Auswahl abspielen"
 
-#: ardour_ui_ed.cc:278
+#: ardour_ui_ed.cc:300
 msgid "Play Selection w/Preroll"
 msgstr "Ausgewählten Bereich mit Vorlauf wiedergeben"
 
-#: ardour_ui_ed.cc:282
+#: ardour_ui_ed.cc:304
 msgid "Enable Record"
 msgstr "Aufnahme aktivieren"
 
-#: ardour_ui_ed.cc:285 ardour_ui_ed.cc:289
+#: ardour_ui_ed.cc:307 ardour_ui_ed.cc:311
 msgid "Start Recording"
 msgstr "Aufnahme starten"
 
-#: ardour_ui_ed.cc:293
+#: ardour_ui_ed.cc:315
 msgid "Rewind"
 msgstr "Rückwärts (beschleunigen)"
 
-#: ardour_ui_ed.cc:296
+#: ardour_ui_ed.cc:318
 msgid "Rewind (Slow)"
 msgstr "Rückwärts (langsam)"
 
-#: ardour_ui_ed.cc:299
+#: ardour_ui_ed.cc:321
 msgid "Rewind (Fast)"
 msgstr "Rückwärts (schnell)"
 
-#: ardour_ui_ed.cc:302
+#: ardour_ui_ed.cc:324
 msgid "Forward"
 msgstr "Vorwärts (beschleunigen)"
 
-#: ardour_ui_ed.cc:305
+#: ardour_ui_ed.cc:327
 msgid "Forward (Slow)"
 msgstr "Vorwärts (langsam)"
 
-#: ardour_ui_ed.cc:308
+#: ardour_ui_ed.cc:330
 msgid "Forward (Fast)"
 msgstr "Vorwärts (schnell)"
 
-#: ardour_ui_ed.cc:311
+#: ardour_ui_ed.cc:333
 msgid "Go to Zero"
 msgstr "Zum Nullpunkt springen"
 
-#: ardour_ui_ed.cc:314 ardour_ui_ed.cc:317
+#: ardour_ui_ed.cc:336 ardour_ui_ed.cc:339
 msgid "Go to Start"
 msgstr "Zum Anfang springen"
 
-#: ardour_ui_ed.cc:320
+#: ardour_ui_ed.cc:342
 msgid "Go to End"
 msgstr "Zum Ende springen"
 
-#: ardour_ui_ed.cc:323
+#: ardour_ui_ed.cc:345
 msgid "Go to Wall Clock"
 msgstr "Zur lokalen Uhrzeit springen"
 
-#: ardour_ui_ed.cc:328 ardour_ui_ed.cc:331
+#: ardour_ui_ed.cc:350 ardour_ui_ed.cc:353
 msgid "Numpad Decimal"
 msgstr "Nummernblock Dezimalpunkt"
 
-#: ardour_ui_ed.cc:334
+#: ardour_ui_ed.cc:356
 msgid "Numpad 0"
 msgstr "Nummernblock 0"
 
-#: ardour_ui_ed.cc:337
+#: ardour_ui_ed.cc:359
 msgid "Numpad 1"
 msgstr "Nummernblock 1"
 
-#: ardour_ui_ed.cc:340
+#: ardour_ui_ed.cc:362
 msgid "Numpad 2"
 msgstr "Nummernblock 2"
 
-#: ardour_ui_ed.cc:343
+#: ardour_ui_ed.cc:365
 msgid "Numpad 3"
 msgstr "Nummernblock 3"
 
-#: ardour_ui_ed.cc:346
+#: ardour_ui_ed.cc:368
 msgid "Numpad 4"
 msgstr "Nummernblock 4"
 
-#: ardour_ui_ed.cc:349
+#: ardour_ui_ed.cc:371
 msgid "Numpad 5"
 msgstr "Nummernblock 5"
 
-#: ardour_ui_ed.cc:352
+#: ardour_ui_ed.cc:374
 msgid "Numpad 6"
 msgstr "Nummernblock 6"
 
-#: ardour_ui_ed.cc:355
+#: ardour_ui_ed.cc:377
 msgid "Numpad 7"
 msgstr "Nummernblock 7"
 
-#: ardour_ui_ed.cc:358
+#: ardour_ui_ed.cc:380
 msgid "Numpad 8"
 msgstr "Nummernblock 8"
 
-#: ardour_ui_ed.cc:361
+#: ardour_ui_ed.cc:383
 msgid "Numpad 9"
 msgstr "Nummernblock 9"
 
-#: ardour_ui_ed.cc:365
+#: ardour_ui_ed.cc:387
 msgid "Focus On Clock"
 msgstr "Fokus auf Zeitanzeige setzen"
 
-#: ardour_ui_ed.cc:369 ardour_ui_ed.cc:378 audio_clock.cc:2114 editor.cc:259
-#: editor_actions.cc:578 editor_actions.cc:587 export_timespan_selector.cc:88
+#: ardour_ui_ed.cc:391 ardour_ui_ed.cc:400 audio_clock.cc:2116 editor.cc:261
+#: editor_actions.cc:585 editor_actions.cc:594 export_timespan_selector.cc:85
 #: session_option_editor.cc:41 session_option_editor.cc:61
 #: session_option_editor.cc:80 session_option_editor.cc:96
 #: session_option_editor.cc:109 session_option_editor.cc:122
@@ -2259,129 +2379,133 @@ msgstr "Fokus auf Zeitanzeige setzen"
 msgid "Timecode"
 msgstr "Timecode"
 
-#: ardour_ui_ed.cc:371 ardour_ui_ed.cc:380 editor_actions.cc:576
+#: ardour_ui_ed.cc:393 ardour_ui_ed.cc:402 editor_actions.cc:583
 msgid "Bars & Beats"
 msgstr "Takte & Schläge"
 
-#: ardour_ui_ed.cc:373 ardour_ui_ed.cc:382
+#: ardour_ui_ed.cc:395 ardour_ui_ed.cc:404
 msgid "Minutes & Seconds"
 msgstr "Minuten & Sekunden"
 
-#: ardour_ui_ed.cc:375 ardour_ui_ed.cc:384 audio_clock.cc:2118 editor.cc:260
-#: editor_actions.cc:577
+#: ardour_ui_ed.cc:397 ardour_ui_ed.cc:406 audio_clock.cc:2120 editor.cc:262
+#: editor_actions.cc:584
 msgid "Samples"
 msgstr "Samples"
 
-#: ardour_ui_ed.cc:387
+#: ardour_ui_ed.cc:409
 msgid "Punch In"
 msgstr "Punch In"
 
-#: ardour_ui_ed.cc:388 mixer_strip.cc:1881 mixer_strip.cc:2069 route_ui.cc:164
+#: ardour_ui_ed.cc:410 mixer_strip.cc:1901 mixer_strip.cc:2089 route_ui.cc:175
 #: time_info_box.cc:116
 msgid "In"
 msgstr "In"
 
-#: ardour_ui_ed.cc:391
+#: ardour_ui_ed.cc:413
 msgid "Punch Out"
 msgstr "Punch Out"
 
-#: ardour_ui_ed.cc:392 mixer_strip.cc:1893 time_info_box.cc:117
+#: ardour_ui_ed.cc:414 mixer_strip.cc:1913 time_info_box.cc:117
 msgid "Out"
 msgstr "Out"
 
-#: ardour_ui_ed.cc:395
+#: ardour_ui_ed.cc:417
 msgid "Punch In/Out"
 msgstr "Punch In/Out"
 
-#: ardour_ui_ed.cc:396
+#: ardour_ui_ed.cc:418
 msgid "In/Out"
 msgstr "In/Out"
 
-#: ardour_ui_ed.cc:399 rc_option_editor.cc:1845
+#: ardour_ui_ed.cc:421 rc_option_editor.cc:1801
 msgid "Click"
 msgstr "Klick"
 
-#: ardour_ui_ed.cc:402
+#: ardour_ui_ed.cc:424
 msgid "Auto Input"
 msgstr "Auto Input"
 
-#: ardour_ui_ed.cc:405
+#: ardour_ui_ed.cc:427
 msgid "Auto Play"
 msgstr "Auto Play"
 
-#: ardour_ui_ed.cc:416
+#: ardour_ui_ed.cc:438
 msgid "Sync Startup to Video"
 msgstr "Start mit Video synchronisieren"
 
-#: ardour_ui_ed.cc:418
+#: ardour_ui_ed.cc:440
 msgid "Time Master"
 msgstr "Time Master"
 
-#: ardour_ui_ed.cc:420
+#: ardour_ui_ed.cc:442
 msgid "Use External Positional Sync Source"
 msgstr "Benutze Externe Synchronisationsquelle"
 
-#: ardour_ui_ed.cc:425
+#: ardour_ui_ed.cc:447
 msgid "Toggle Record Enable Track %1"
 msgstr "Aufnahmebereitschaft auf Spur %1 umschalten"
 
-#: ardour_ui_ed.cc:432
+#: ardour_ui_ed.cc:454
 msgid "Percentage"
 msgstr "Prozent"
 
-#: ardour_ui_ed.cc:433 shuttle_control.cc:187
+#: ardour_ui_ed.cc:455 shuttle_control.cc:188
 msgid "Semitones"
 msgstr "Halbtöne"
 
-#: ardour_ui_ed.cc:437
+#: ardour_ui_ed.cc:459
 msgid "Send MTC"
 msgstr "MTC senden"
 
-#: ardour_ui_ed.cc:439
+#: ardour_ui_ed.cc:461
 msgid "Send MMC"
 msgstr "MMC senden"
 
-#: ardour_ui_ed.cc:441
+#: ardour_ui_ed.cc:463
 msgid "Use MMC"
 msgstr "Benutze MMC"
 
-#: ardour_ui_ed.cc:443 rc_option_editor.cc:2571
+#: ardour_ui_ed.cc:465 rc_option_editor.cc:2594
 msgid "Send MIDI Clock"
 msgstr "MIDI Clock senden"
 
-#: ardour_ui_ed.cc:445
+#: ardour_ui_ed.cc:467
 msgid "Send MIDI Feedback"
 msgstr "MIDI Feedback senden"
 
-#: ardour_ui_ed.cc:451
+#: ardour_ui_ed.cc:473
 msgid "Panic"
 msgstr "Panic"
 
-#: ardour_ui_ed.cc:542
+#: ardour_ui_ed.cc:567
 msgid "Wall Clock"
 msgstr "Uhrzeit"
 
-#: ardour_ui_ed.cc:544
+#: ardour_ui_ed.cc:569
 msgid "Disk Space"
 msgstr "Speicherplatz"
 
-#: ardour_ui_ed.cc:545
+#: ardour_ui_ed.cc:570
 msgid "DSP"
 msgstr "DSP"
 
-#: ardour_ui_ed.cc:546
+#: ardour_ui_ed.cc:571
 msgid "X-run"
 msgstr "X-run"
 
-#: ardour_ui_ed.cc:547
+#: ardour_ui_ed.cc:572
+msgid "Active Peak-file Work"
+msgstr "Peakdatei-Erstellung aktiv"
+
+#: ardour_ui_ed.cc:573
 msgid "Buffers"
 msgstr "Puffer"
 
-#: ardour_ui_ed.cc:549
+#: ardour_ui_ed.cc:575
 msgid "Timecode Format"
 msgstr "Timecode-Format"
 
-#: ardour_ui_ed.cc:550
+#: ardour_ui_ed.cc:576
 msgid "File Format"
 msgstr "Dateiformat"
 
@@ -2397,131 +2521,131 @@ msgstr ""
 msgid "Internal"
 msgstr "Intern"
 
-#: ardour_ui_options.cc:503
+#: ardour_ui_options.cc:509
 msgid "Enable/Disable external positional sync"
 msgstr "Aktiviere/Deaktiviere externe Positionssynchronisierung"
 
-#: ardour_ui_options.cc:505
+#: ardour_ui_options.cc:511
 msgid "Sync to JACK is not possible: video pull up/down is set"
 msgstr "Synchronisation ist nicht möglich: Video pull-up/down ist aktiviert"
 
-#: audio_clock.cc:1052 audio_clock.cc:1071
+#: audio_clock.cc:1051 audio_clock.cc:1070
 msgid "--pending--"
 msgstr "--wartend--"
 
-#: audio_clock.cc:1123
+#: audio_clock.cc:1122
 msgid "SR"
 msgstr "SR"
 
-#: audio_clock.cc:1129 audio_clock.cc:1133
+#: audio_clock.cc:1128 audio_clock.cc:1132
 msgid "Pull"
 msgstr "Ziehen"
 
-#: audio_clock.cc:1131
+#: audio_clock.cc:1130
 #, c-format
 msgid "%+.4f%%"
 msgstr "%+.4f%%"
 
-#: audio_clock.cc:1287 editor.cc:261 editor_actions.cc:139
-#: editor_actions.cc:570
+#: audio_clock.cc:1286 editor.cc:263 editor_actions.cc:140
+#: editor_actions.cc:577
 msgid "Tempo"
 msgstr "Tempo"
 
-#: audio_clock.cc:1291 editor.cc:262 editor_actions.cc:571
+#: audio_clock.cc:1290 editor.cc:264 editor_actions.cc:578
 msgid "Meter"
 msgstr "Taktart"
 
-#: audio_clock.cc:1869 audio_streamview.cc:116 editor_actions.cc:1101
+#: audio_clock.cc:1871 audio_streamview.cc:116 editor_actions.cc:1108
 #: session_metadata_dialog.cc:452 session_metadata_dialog.cc:500
 #: session_metadata_dialog.cc:556 session_metadata_dialog.cc:845
-#: streamview.cc:470
+#: streamview.cc:469
 msgid "programming error: %1"
 msgstr "Programmierfehler: %1"
 
-#: audio_clock.cc:2002 audio_clock.cc:2030
+#: audio_clock.cc:2004 audio_clock.cc:2032
 msgid "programming error: %1 %2"
 msgstr "Programmierfehler: %1 %2"
 
-#: audio_clock.cc:2116 editor.cc:258 export_timespan_selector.cc:98
+#: audio_clock.cc:2118 editor.cc:260 export_timespan_selector.cc:95
 msgid "Bars:Beats"
 msgstr "Takte:Schläge"
 
-#: audio_clock.cc:2117 export_timespan_selector.cc:93
+#: audio_clock.cc:2119 export_timespan_selector.cc:90
 msgid "Minutes:Seconds"
 msgstr "Minuten:Sekunden"
 
-#: audio_clock.cc:2122
-msgid "Set From Playhead"
-msgstr "Ab Positionszeiger"
+#: audio_clock.cc:2124
+msgid "Set from Playhead"
+msgstr "Vom Wiedergabezeiger übernehmen"
 
-#: audio_clock.cc:2123
+#: audio_clock.cc:2125
 msgid "Locate to This Time"
 msgstr "Positionszeiger hierhin setzen"
 
-#: audio_clock.cc:2126
+#: audio_clock.cc:2128
 msgid "Copy to clipboard"
 msgstr "In die Zwischenablage kopieren"
 
-#: audio_region_editor.cc:64 control_point_dialog.cc:49 rhythm_ferret.cc:124
+#: audio_region_editor.cc:65 control_point_dialog.cc:49 rhythm_ferret.cc:124
 #: rhythm_ferret.cc:129 rhythm_ferret.cc:134
 msgid "dB"
 msgstr "dB"
 
-#: audio_region_editor.cc:67
+#: audio_region_editor.cc:68
 msgid "Region gain:"
 msgstr "Regionen-Lautstärke:"
 
-#: audio_region_editor.cc:77 export_format_dialog.cc:43
+#: audio_region_editor.cc:78 export_format_dialog.cc:43
 msgid "dBFS"
 msgstr "dBFS"
 
-#: audio_region_editor.cc:80
+#: audio_region_editor.cc:81
 msgid "Peak amplitude:"
 msgstr "Spitzenamplitude"
 
-#: audio_region_editor.cc:91
+#: audio_region_editor.cc:92
 msgid "Calculating..."
 msgstr "Berechne..."
 
-#: audio_region_view.cc:1254
+#: audio_region_view.cc:1371
 msgid "add gain control point"
 msgstr "Lautstärkekurve bearbeiten"
 
-#: automation_controller.cc:287 automation_controller.cc:303
+#: automation_controller.cc:290 automation_controller.cc:306
 msgid "Select Note..."
 msgstr "Note selektieren..."
 
-#: automation_controller.cc:294
+#: automation_controller.cc:297
 msgid "Halve"
 msgstr "Halbiere"
 
-#: automation_controller.cc:297
+#: automation_controller.cc:300
 msgid "Double"
 msgstr "Verdopple"
 
-#: automation_controller.cc:308
+#: automation_controller.cc:311
 msgid "Set to %1 beat"
 msgid_plural "Set to %1 beats"
 msgstr[0] "Setze auf %1 Schlag"
 msgstr[1] "Setze auf %1 Schläge"
 
-#: automation_line.cc:287 editor_drag.cc:4129
+#: automation_line.cc:285 editor_drag.cc:4255
 msgid "automation event move"
 msgstr "Automationspunkt bewegen"
 
-#: automation_line.cc:884 region_gain_line.cc:75
+#: automation_line.cc:881 region_gain_line.cc:75
 msgid "remove control point"
 msgstr "Automationspunkt entfernen"
 
-#: automation_line.cc:1008
+#: automation_line.cc:1006
 msgid "Ignoring illegal points on AutomationLine \"%1\""
 msgstr "Unzulässige Automationspunkte werden ignoriert: \"%1\""
 
-#: automation_region_view.cc:190 automation_time_axis.cc:644
+#: automation_region_view.cc:193 automation_time_axis.cc:647
 msgid "add automation event"
 msgstr "Automationspunkt einfügen"
 
-#: automation_streamview.cc:95
+#: automation_streamview.cc:94
 msgid "unable to display automation region for control without list"
 msgstr ""
 "die Automationsspur für diesen Parameter kann ohne Liste nicht dargestellt "
@@ -2536,33 +2660,33 @@ msgid "hide track"
 msgstr "Diese Spur verbergen"
 
 #: automation_time_axis.cc:308 automation_time_axis.cc:360
-#: automation_time_axis.cc:554 gain_meter.cc:222 generic_pluginui.cc:524
-#: generic_pluginui.cc:818 panner_ui.cc:149
+#: automation_time_axis.cc:554 gain_meter.cc:222 generic_pluginui.cc:526
+#: generic_pluginui.cc:820 panner_ui.cc:151
 msgid "Automation|Manual"
 msgstr "Manuell"
 
 #: automation_time_axis.cc:310 automation_time_axis.cc:371
-#: automation_time_axis.cc:559 editor.cc:1916 editor.cc:1994
-#: editor_actions.cc:122 editor_actions.cc:1932 gain_meter.cc:225
-#: generic_pluginui.cc:100 generic_pluginui.cc:527 generic_pluginui.cc:820
-#: midi_time_axis.cc:1607 midi_time_axis.cc:1610 midi_time_axis.cc:1613
-#: panner_ui.cc:152
+#: automation_time_axis.cc:559 editor.cc:1928 editor.cc:2006
+#: editor_actions.cc:123 editor_actions.cc:1939 gain_meter.cc:225
+#: generic_pluginui.cc:102 generic_pluginui.cc:529 generic_pluginui.cc:822
+#: midi_time_axis.cc:1614 midi_time_axis.cc:1617 midi_time_axis.cc:1620
+#: panner_ui.cc:154
 msgid "Play"
 msgstr "Wiedergabe"
 
 #: automation_time_axis.cc:312 automation_time_axis.cc:382
-#: automation_time_axis.cc:564 gain_meter.cc:228 generic_pluginui.cc:102
-#: generic_pluginui.cc:530 generic_pluginui.cc:822 panner_ui.cc:155
+#: automation_time_axis.cc:564 gain_meter.cc:228 generic_pluginui.cc:104
+#: generic_pluginui.cc:532 generic_pluginui.cc:824 panner_ui.cc:157
 msgid "Write"
 msgstr "Schreiben"
 
 #: automation_time_axis.cc:314 automation_time_axis.cc:393
-#: automation_time_axis.cc:569 gain_meter.cc:231 generic_pluginui.cc:104
-#: generic_pluginui.cc:533 generic_pluginui.cc:824 panner_ui.cc:158
+#: automation_time_axis.cc:569 gain_meter.cc:231 generic_pluginui.cc:106
+#: generic_pluginui.cc:535 generic_pluginui.cc:826 panner_ui.cc:160
 msgid "Touch"
 msgstr "Ändern"
 
-#: automation_time_axis.cc:404 generic_pluginui.cc:536 meter_patterns.cc:116
+#: automation_time_axis.cc:404 generic_pluginui.cc:538 meter_patterns.cc:118
 msgid "???"
 msgstr "???"
 
@@ -2570,7 +2694,8 @@ msgstr "???"
 msgid "clear automation"
 msgstr "Automation zurücksetzen"
 
-#: automation_time_axis.cc:545
+#: automation_time_axis.cc:545 rc_option_editor.cc:2770
+#: rc_option_editor.cc:2775 rc_option_editor.cc:2821 rc_option_editor.cc:2826
 msgid "Clear"
 msgstr "Leeren"
 
@@ -2586,7 +2711,7 @@ msgstr "Diskret"
 msgid "Linear"
 msgstr "Linear"
 
-#: automation_time_axis.cc:604 rhythm_ferret.cc:109 shuttle_control.cc:206
+#: automation_time_axis.cc:604 rhythm_ferret.cc:109 shuttle_control.cc:207
 msgid "Mode"
 msgstr "Modus"
 
@@ -2602,31 +2727,31 @@ msgstr "Bundle editieren"
 msgid "Direction:"
 msgstr "Richtung:"
 
-#: bundle_manager.cc:206 bundle_manager.cc:210 engine_dialog.cc:881
-#: mixer_strip.cc:165 mixer_strip.cc:379 mixer_strip.cc:2302
-#: rc_option_editor.cc:2828
+#: bundle_manager.cc:206 bundle_manager.cc:210 engine_dialog.cc:949
+#: mixer_strip.cc:168 mixer_strip.cc:382 mixer_strip.cc:2347
+#: rc_option_editor.cc:2944
 msgid "Input"
 msgstr "Eingang"
 
 #: bundle_manager.cc:207 bundle_manager.cc:212 bundle_manager.cc:246
-#: engine_dialog.cc:883 mixer_strip.cc:169 mixer_strip.cc:383
-#: mixer_strip.cc:2305 monitor_section.cc:329 monitor_section.cc:333
-#: rc_option_editor.cc:2832
+#: engine_dialog.cc:951 mixer_strip.cc:172 mixer_strip.cc:386
+#: mixer_strip.cc:2350 monitor_section.cc:288 monitor_section.cc:292
+#: rc_option_editor.cc:2948
 msgid "Output"
 msgstr "Ausgang"
 
-#: bundle_manager.cc:265 editor.cc:1958 editor_actions.cc:94
-#: editor_actions.cc:104 rc_option_editor.cc:1539 rc_option_editor.cc:1546
+#: bundle_manager.cc:265 editor.cc:1970 editor_actions.cc:95
+#: editor_actions.cc:105 rc_option_editor.cc:2782 rc_option_editor.cc:2796
 msgid "Edit"
 msgstr "Bearbeiten"
 
-#: bundle_manager.cc:266 editor.cc:5921 editor.cc:5949 editor_actions.cc:345
-#: editor_actions.cc:346 plugin_ui.cc:420 processor_box.cc:2525
+#: bundle_manager.cc:266 editor.cc:5948 editor.cc:5978 editor_actions.cc:346
+#: editor_actions.cc:347 plugin_ui.cc:420 processor_box.cc:2723
 msgid "Delete"
 msgstr "Löschen"
 
-#: bundle_manager.cc:272 bundle_manager.cc:439 editor_route_groups.cc:97
-#: editor_routes.cc:207 midi_list_editor.cc:107 session_metadata_dialog.cc:646
+#: bundle_manager.cc:272 bundle_manager.cc:439 editor_route_groups.cc:98
+#: editor_routes.cc:208 midi_list_editor.cc:107 session_metadata_dialog.cc:646
 msgid "Name"
 msgstr "Name"
 
@@ -2658,6 +2783,30 @@ msgstr "Automationspunkt"
 msgid "Value"
 msgstr "Wert"
 
+#: duplicate_routes_dialog.cc:35
+msgid "Duplicate Tracks & Busses"
+msgstr "Spuren und Busse duplizieren"
+
+#: duplicate_routes_dialog.cc:36
+msgid "Copy playlists"
+msgstr "Wiedergabelisten kopieren"
+
+#: duplicate_routes_dialog.cc:37
+msgid "Create new (empty) playlists"
+msgstr "Neue (leere) Wiedergabelisten erzeugen"
+
+#: duplicate_routes_dialog.cc:38
+msgid "Share playlists"
+msgstr "Wiedergabelisten teilen"
+
+#: duplicate_routes_dialog.cc:41
+msgid "Duplicate each track/bus this number of times:"
+msgstr "Alle Spuren/Busse so oft duplizieren:"
+
+#: duplicate_routes_dialog.cc:176
+msgid "1 or more tracks/busses could not be duplicated"
+msgstr "1 oder mehrere Spuren/Busse konnten nicht dupliziert werden"
+
 #: edit_note_dialog.cc:42
 msgid "Note"
 msgstr "Note"
@@ -2699,9 +2848,9 @@ msgstr "Velocity"
 msgid "Time"
 msgstr "Zeitpunkt"
 
-#: edit_note_dialog.cc:98 editor_regions.cc:115
-#: export_timespan_selector.cc:378 export_timespan_selector.cc:440
-#: location_ui.cc:320 midi_list_editor.cc:115 time_info_box.cc:108
+#: edit_note_dialog.cc:98 editor_regions.cc:118
+#: export_timespan_selector.cc:375 export_timespan_selector.cc:437
+#: location_ui.cc:322 midi_list_editor.cc:115 time_info_box.cc:108
 msgid "Length"
 msgstr "Länge"
 
@@ -2709,586 +2858,582 @@ msgstr "Länge"
 msgid "edit note"
 msgstr "Note bearbeiten"
 
-#: editor.cc:148
+#: editor.cc:150
 msgid "CD Frames"
 msgstr "CD-Frames"
 
-#: editor.cc:149
+#: editor.cc:151
 msgid "TC Frames"
 msgstr "TC Frames"
 
-#: editor.cc:150
+#: editor.cc:152
 msgid "TC Seconds"
 msgstr "TC Sekunden"
 
-#: editor.cc:151
+#: editor.cc:153
 msgid "TC Minutes"
 msgstr "TC Minuten"
 
-#: editor.cc:152
+#: editor.cc:154
 msgid "Seconds"
 msgstr "Sekunden"
 
-#: editor.cc:153
+#: editor.cc:155
 msgid "Minutes"
 msgstr "Minuten"
 
-#: editor.cc:154 quantize_dialog.cc:37 quantize_dialog.cc:141
+#: editor.cc:156 quantize_dialog.cc:37 quantize_dialog.cc:141
 msgid "Beats/128"
 msgstr "Schläge/128"
 
-#: editor.cc:155 quantize_dialog.cc:38 quantize_dialog.cc:143
+#: editor.cc:157 quantize_dialog.cc:38 quantize_dialog.cc:143
 msgid "Beats/64"
 msgstr "Schläge/64"
 
-#: editor.cc:156 quantize_dialog.cc:39 quantize_dialog.cc:145
+#: editor.cc:158 quantize_dialog.cc:39 quantize_dialog.cc:145
 msgid "Beats/32"
 msgstr "Schläge/32"
 
-#: editor.cc:157
+#: editor.cc:159
 msgid "Beats/28"
 msgstr "Schläge/28"
 
-#: editor.cc:158
+#: editor.cc:160
 msgid "Beats/24"
 msgstr "Schläge/24"
 
-#: editor.cc:159
+#: editor.cc:161
 msgid "Beats/20"
 msgstr "Schläge/20"
 
-#: editor.cc:160 quantize_dialog.cc:40 quantize_dialog.cc:147
+#: editor.cc:162 quantize_dialog.cc:40 quantize_dialog.cc:147
 msgid "Beats/16"
 msgstr "Schläge/16"
 
-#: editor.cc:161
+#: editor.cc:163
 msgid "Beats/14"
 msgstr "Schläge/14"
 
-#: editor.cc:162
+#: editor.cc:164
 msgid "Beats/12"
 msgstr "Schläge/12"
 
-#: editor.cc:163
+#: editor.cc:165
 msgid "Beats/10"
 msgstr "Schläge/10"
 
-#: editor.cc:164 quantize_dialog.cc:41 quantize_dialog.cc:149
+#: editor.cc:166 quantize_dialog.cc:41 quantize_dialog.cc:149
 msgid "Beats/8"
 msgstr "Schläge/8"
 
-#: editor.cc:165
+#: editor.cc:167
 msgid "Beats/7"
 msgstr "Schläge/7"
 
-#: editor.cc:166
+#: editor.cc:168
 msgid "Beats/6"
 msgstr "Schläge/6"
 
-#: editor.cc:167
+#: editor.cc:169
 msgid "Beats/5"
 msgstr "Schläge/5"
 
-#: editor.cc:168 quantize_dialog.cc:42 quantize_dialog.cc:151
+#: editor.cc:170 quantize_dialog.cc:42 quantize_dialog.cc:151
 msgid "Beats/4"
 msgstr "Schläge/4"
 
-#: editor.cc:169 quantize_dialog.cc:43 quantize_dialog.cc:153
+#: editor.cc:171 quantize_dialog.cc:43 quantize_dialog.cc:153
 msgid "Beats/3"
 msgstr "Schläge/3"
 
-#: editor.cc:170 quantize_dialog.cc:44 quantize_dialog.cc:155
+#: editor.cc:172 quantize_dialog.cc:44 quantize_dialog.cc:155
 msgid "Beats/2"
 msgstr "Schläge/2"
 
-#: editor.cc:171 quantize_dialog.cc:45 quantize_dialog.cc:157
+#: editor.cc:173 quantize_dialog.cc:45 quantize_dialog.cc:157
 msgid "Beats"
 msgstr "Schläge"
 
-#: editor.cc:172
+#: editor.cc:174
 msgid "Bars"
 msgstr "Takte"
 
-#: editor.cc:173
+#: editor.cc:175
 msgid "Marks"
 msgstr "Marker"
 
-#: editor.cc:174
+#: editor.cc:176
 msgid "Region starts"
 msgstr "Regionen-Anfang"
 
-#: editor.cc:175
+#: editor.cc:177
 msgid "Region ends"
 msgstr "Regionen-Ende"
 
-#: editor.cc:176
+#: editor.cc:178
 msgid "Region syncs"
 msgstr "Regionen-Sync"
 
-#: editor.cc:177
+#: editor.cc:179
 msgid "Region bounds"
 msgstr "Regionengrenzen"
 
-#: editor.cc:182 editor_actions.cc:519
+#: editor.cc:184 editor_actions.cc:526
 msgid "No Grid"
 msgstr "Raster aus"
 
-#: editor.cc:183 editor_actions.cc:520
+#: editor.cc:185 editor_actions.cc:527
 msgid "Grid"
 msgstr "Einrasten"
 
-#: editor.cc:184 editor_actions.cc:521
+#: editor.cc:186 editor_actions.cc:528
 msgid "Magnetic"
 msgstr "Magnetisch"
 
-#: editor.cc:189 editor.cc:207 editor_actions.cc:121 editor_actions.cc:502
+#: editor.cc:191 editor.cc:209 editor_actions.cc:122 editor_actions.cc:509
 msgid "Playhead"
 msgstr "Positionszeiger"
 
-#: editor.cc:190 editor_actions.cc:504
+#: editor.cc:192 editor_actions.cc:511
 msgid "Marker"
 msgstr "Marker"
 
-#: editor.cc:191 editor.cc:208 editor_actions.cc:503
+#: editor.cc:193 editor.cc:210 editor_actions.cc:510
 msgid "Mouse"
 msgstr "Maus"
 
-#: editor.cc:196 editor_actions.cc:511
+#: editor.cc:198 editor_actions.cc:518
 msgid "Slide"
 msgstr "Slide"
 
-#: editor.cc:197
+#: editor.cc:199
 msgid "Splice"
 msgstr "Splice"
 
-#: editor.cc:198 editor_actions.cc:510
+#: editor.cc:200 editor_actions.cc:517
 msgid "Ripple"
 msgstr "Ripple"
 
-#: editor.cc:199 editor_actions.cc:1801 editor_markers.cc:898
-#: editor_rulers.cc:260 location_ui.cc:58
+#: editor.cc:201 editor_actions.cc:1808 editor_markers.cc:905
+#: editor_rulers.cc:259 location_ui.cc:60
 msgid "Lock"
 msgstr "Lock"
 
-#: editor.cc:204 mono_panner_editor.cc:42
+#: editor.cc:206 mono_panner_editor.cc:42
 msgid "Left"
 msgstr "Links"
 
-#: editor.cc:205 mono_panner_editor.cc:47
+#: editor.cc:207 mono_panner_editor.cc:47
 msgid "Right"
 msgstr "Rechts"
 
-#: editor.cc:206
+#: editor.cc:208
 msgid "Center"
 msgstr "Mitte"
 
-#: editor.cc:209 editor.cc:3248
+#: editor.cc:211
 msgid "Edit point"
 msgstr "Arbeitspunkt"
 
-#: editor.cc:215
+#: editor.cc:217
 msgid "Mushy"
 msgstr "Matschig"
 
-#: editor.cc:216
+#: editor.cc:218
 msgid "Smooth"
 msgstr "Klar"
 
-#: editor.cc:217
+#: editor.cc:219
 msgid "Balanced multitimbral mixture"
 msgstr "Ausgewogene multitimbrale Mischung"
 
-#: editor.cc:218
+#: editor.cc:220
 msgid "Unpitched percussion with stable notes"
 msgstr "Ungestimmte Perkussion mit stabilen Tönen"
 
-#: editor.cc:219
+#: editor.cc:221
 msgid "Crisp monophonic instrumental"
 msgstr "Klare monophone Instrumentalmusik"
 
-#: editor.cc:220
+#: editor.cc:222
 msgid "Unpitched solo percussion"
 msgstr "Ungestimmte Perkussion (solo)"
 
-#: editor.cc:221
+#: editor.cc:223
 msgid "Resample without preserving pitch"
 msgstr "Resampeln, ohne die Tonhöhe zu erhalten"
 
-#: editor.cc:257
+#: editor.cc:259
 msgid "Mins:Secs"
 msgstr "Min:Sek"
 
-#: editor.cc:263
+#: editor.cc:265
 msgid "Location Markers"
 msgstr "Positionsmarker"
 
-#: editor.cc:264
+#: editor.cc:266
 msgid "Range Markers"
 msgstr "Bereiche"
 
-#: editor.cc:265
+#: editor.cc:267
 msgid "Loop/Punch Ranges"
 msgstr "Schleifen/Punchbereiche"
 
-#: editor.cc:266 editor_actions.cc:574
+#: editor.cc:268 editor_actions.cc:581
 msgid "CD Markers"
 msgstr "CD-Marker"
 
-#: editor.cc:267
+#: editor.cc:269
 msgid "Video Timeline"
 msgstr "Video Zeitleiste"
 
-#: editor.cc:284
+#: editor.cc:286
 msgid "mode"
 msgstr "Modus"
 
-#: editor.cc:462 editor_actions.cc:114 editor_actions.cc:573
+#: editor.cc:465 editor_actions.cc:115 editor_actions.cc:580
 msgid "Markers"
 msgstr "Marker"
 
-#: editor.cc:580 rc_option_editor.cc:2413
+#: editor.cc:583 rc_option_editor.cc:2393
 msgid "Regions"
 msgstr "Regionen"
 
-#: editor.cc:581
+#: editor.cc:584
 msgid "Tracks & Busses"
 msgstr "Spuren & Busse"
 
-#: editor.cc:582
+#: editor.cc:585
 msgid "Snapshots"
 msgstr "Schnappschüsse"
 
-#: editor.cc:583
+#: editor.cc:586
 msgid "Track & Bus Groups"
 msgstr "Spuren & Bus-Gruppen"
 
-#: editor.cc:584
+#: editor.cc:587
 msgid "Ranges & Marks"
 msgstr "Bereiche & Marker"
 
-#: editor.cc:731 editor.cc:5773 rc_option_editor.cc:2090
-#: rc_option_editor.cc:2098 rc_option_editor.cc:2106 rc_option_editor.cc:2114
-#: rc_option_editor.cc:2138 rc_option_editor.cc:2150 rc_option_editor.cc:2161
-#: rc_option_editor.cc:2163 rc_option_editor.cc:2171 rc_option_editor.cc:2179
-#: rc_option_editor.cc:2199 rc_option_editor.cc:2211 rc_option_editor.cc:2213
-#: rc_option_editor.cc:2215 rc_option_editor.cc:2223 rc_option_editor.cc:2231
-#: rc_option_editor.cc:2246 rc_option_editor.cc:2250 rc_option_editor.cc:2274
+#: editor.cc:734 editor.cc:5800 rc_option_editor.cc:2061
+#: rc_option_editor.cc:2075 rc_option_editor.cc:2079 rc_option_editor.cc:2087
+#: rc_option_editor.cc:2095 rc_option_editor.cc:2104 rc_option_editor.cc:2113
+#: rc_option_editor.cc:2121 rc_option_editor.cc:2129 rc_option_editor.cc:2139
+#: rc_option_editor.cc:2141 rc_option_editor.cc:2165 rc_option_editor.cc:2177
+#: rc_option_editor.cc:2188 rc_option_editor.cc:2206 rc_option_editor.cc:2208
+#: rc_option_editor.cc:2211 rc_option_editor.cc:2220 rc_option_editor.cc:2238
+#: rc_option_editor.cc:2250 rc_option_editor.cc:2252
 msgid "Editor"
 msgstr "Editor"
 
-#: editor.cc:1335 editor.cc:4757 editor_actions.cc:134 editor_actions.cc:1877
+#: editor.cc:1348 editor.cc:4783 editor_actions.cc:135 editor_actions.cc:1884
 msgid "Loop"
 msgstr "Schleife"
 
-#: editor.cc:1341 editor.cc:4784 editor_actions.cc:135 time_info_box.cc:68
+#: editor.cc:1354 editor.cc:4810 editor_actions.cc:136 time_info_box.cc:68
 msgid "Punch"
 msgstr "Punch"
 
-#: editor.cc:1453 rc_option_editor.cc:2132
+#: editor.cc:1466 rc_option_editor.cc:2159
 msgid "Linear (for highly correlated material)"
 msgstr "Linear (für stark korreliertes Material)"
 
-#: editor.cc:1463 rc_option_editor.cc:2133
+#: editor.cc:1476 rc_option_editor.cc:2160
 msgid "Constant power"
 msgstr "Konstante Energie"
 
-#: editor.cc:1472 rc_option_editor.cc:2134
+#: editor.cc:1485 rc_option_editor.cc:2161
 msgid "Symmetric"
 msgstr "Symmetrisch"
 
-#: editor.cc:1482 rc_option_editor.cc:2135
+#: editor.cc:1495 rc_option_editor.cc:2162
 msgid "Slow"
 msgstr "Langsam"
 
-#: editor.cc:1491 rc_option_editor.cc:2136 sfdb_ui.cc:1770 sfdb_ui.cc:1880
+#: editor.cc:1504 rc_option_editor.cc:2163 sfdb_ui.cc:1767 sfdb_ui.cc:1878
 msgid "Fast"
 msgstr "Schnell"
 
-#: editor.cc:1513 editor.cc:1538
+#: editor.cc:1526 editor.cc:1551
 msgid "Deactivate"
 msgstr "Deaktivieren"
 
-#: editor.cc:1515 editor.cc:1540
+#: editor.cc:1528 editor.cc:1553
 msgid "Activate"
 msgstr "Aktivieren"
 
-#: editor.cc:1641 editor.cc:1649 editor_ops.cc:3933
+#: editor.cc:1654 editor.cc:1662 editor_ops.cc:3855
 msgid "Freeze"
 msgstr "Einfrieren"
 
-#: editor.cc:1645
+#: editor.cc:1658
 msgid "Unfreeze"
 msgstr "Auftauen"
 
-#: editor.cc:1784
+#: editor.cc:1797
 msgid "Selected Regions"
 msgstr "Ausgewählte Regionen"
 
-#: editor.cc:1828 editor_markers.cc:933
+#: editor.cc:1841 editor_markers.cc:940
 msgid "Play Range"
 msgstr "Bereich wiedergeben"
 
-#: editor.cc:1829 editor_markers.cc:936
+#: editor.cc:1842 editor_markers.cc:943
 msgid "Loop Range"
 msgstr "Bereich in Schleife wiedergeben"
 
-#: editor.cc:1832 editor_markers.cc:943
+#: editor.cc:1845 editor_markers.cc:950
 msgid "Zoom to Range"
 msgstr "Auf Bereich zoomen"
 
-#: editor.cc:1841 editor_actions.cc:376
+#: editor.cc:1854 editor_actions.cc:383
 msgid "Move Range Start to Previous Region Boundary"
 msgstr "Anfang des Bereiches zur vorherigen Regiongrenze verschieben"
 
-#: editor.cc:1848 editor_actions.cc:383
+#: editor.cc:1861 editor_actions.cc:390
 msgid "Move Range Start to Next Region Boundary"
 msgstr "Anfang des Bereiches zur nächsten Regiongrenze verschieben"
 
-#: editor.cc:1855 editor_actions.cc:390
+#: editor.cc:1868 editor_actions.cc:397
 msgid "Move Range End to Previous Region Boundary"
 msgstr "Ende des Bereiches zur vorherigen Regiongrenze verschieben"
 
-#: editor.cc:1862 editor_actions.cc:397
+#: editor.cc:1875 editor_actions.cc:404
 msgid "Move Range End to Next Region Boundary"
 msgstr "Ende des Bereiches zur nächsten Regiongrenze verschieben"
 
-#: editor.cc:1868 editor_actions.cc:133 editor_actions.cc:332
+#: editor.cc:1881 editor_actions.cc:134 editor_actions.cc:333
 msgid "Separate"
 msgstr "Teilen"
 
-#: editor.cc:1869
+#: editor.cc:1882
 msgid "Convert to Region in Region List"
 msgstr "In Region umwanden (in Regionenliste hinzufügen)"
 
-#: editor.cc:1872 editor_markers.cc:963
+#: editor.cc:1885 editor_markers.cc:970
 msgid "Select All in Range"
 msgstr "Alles im Bereich auswählen"
 
-#: editor.cc:1875 editor_actions.cc:304
+#: editor.cc:1888 editor_actions.cc:305
 msgid "Set Loop from Selection"
 msgstr "Schleife aus Auswahl bilden"
 
-#: editor.cc:1876 editor_actions.cc:305
+#: editor.cc:1889 editor_actions.cc:306
 msgid "Set Punch from Selection"
 msgstr "Punch aus Auswahl bilden"
 
-#: editor.cc:1877 editor_actions.cc:306
+#: editor.cc:1890 editor_actions.cc:307
 msgid "Set Session Start/End from Selection"
 msgstr "Projektstart/ende auf Auswahl setzen"
 
-#: editor.cc:1880
+#: editor.cc:1893
 msgid "Add Range Markers"
 msgstr "Bereichsmarker einfügen"
 
-#: editor.cc:1883
+#: editor.cc:1896
 msgid "Crop Region to Range"
 msgstr "Region auf Bereich kürzen"
 
-#: editor.cc:1884
-msgid "Fill Range with Region"
-msgstr "Bereich mit Region füllen"
-
-#: editor.cc:1885 editor_actions.cc:318
+#: editor.cc:1897 editor_actions.cc:319
 msgid "Duplicate Range"
 msgstr "Bereich duplizieren"
 
-#: editor.cc:1888
+#: editor.cc:1900
 msgid "Consolidate Range"
 msgstr "Bereich als neue Region pre-Mixer"
 
-#: editor.cc:1889
-msgid "Consolidate Range With Processing"
+#: editor.cc:1901
+msgid "Consolidate Range with Processing"
 msgstr "Bereich zu neuer Region (mit Signalverarbeitung)"
 
-#: editor.cc:1890
+#: editor.cc:1902
 msgid "Bounce Range to Region List"
 msgstr "Auswahl zur Regionenliste bouncen"
 
-#: editor.cc:1891
-msgid "Bounce Range to Region List With Processing"
-msgstr "Auswahl zur Regionenliste bouncen (mit Signalverarbeitung)"
+#: editor.cc:1903
+msgid "Bounce Range to Region List with Processing"
+msgstr "Bereich zur Regionenliste bouncen (mit Signalverarbeitung)"
 
-#: editor.cc:1892 editor_markers.cc:946
+#: editor.cc:1904 editor_markers.cc:953
 msgid "Export Range..."
 msgstr "Bereich exportieren..."
 
-#: editor.cc:1894
+#: editor.cc:1906
 msgid "Export Video Range..."
 msgstr "Videobereich exportieren..."
 
-#: editor.cc:1910 editor.cc:1992 editor_actions.cc:310
-msgid "Play From Edit Point"
+#: editor.cc:1922 editor.cc:2004 editor_actions.cc:311
+msgid "Play from Edit Point"
 msgstr "Wiedergabe ab Arbeitspunkt"
 
-#: editor.cc:1911 editor.cc:1993
-msgid "Play From Start"
-msgstr "Wiedergabe ab Anfang"
+#: editor.cc:1923 editor.cc:2005
+msgid "Play from Start"
+msgstr "Wiedergabe ab Beginn"
 
-#: editor.cc:1912
+#: editor.cc:1924
 msgid "Play Region"
 msgstr "Region wiedergeben"
 
-#: editor.cc:1914
+#: editor.cc:1926
 msgid "Loop Region"
 msgstr "Region in Schleife wiedergeben"
 
-#: editor.cc:1924 editor.cc:2002
+#: editor.cc:1936 editor.cc:2014
 msgid "Select All in Track"
 msgstr "Alles in der Spur auswählen"
 
-#: editor.cc:1925 editor.cc:2003 editor_actions.cc:194
+#: editor.cc:1937 editor.cc:2015 editor_actions.cc:195
 msgid "Select All Objects"
 msgstr "Alle Objekte auswählen"
 
-#: editor.cc:1926 editor.cc:2004
+#: editor.cc:1938 editor.cc:2016
 msgid "Invert Selection in Track"
 msgstr "Auswahl in der Spur umkehren"
 
-#: editor.cc:1927 editor.cc:2005 editor_actions.cc:197
+#: editor.cc:1939 editor.cc:2017 editor_actions.cc:198
 msgid "Invert Selection"
 msgstr "Auswahl umkehren"
 
-#: editor.cc:1929
+#: editor.cc:1941 editor_actions.cc:200
 msgid "Set Range to Loop Range"
 msgstr "Bereich als Schleife auswählen"
 
-#: editor.cc:1930 editor_actions.cc:200
+#: editor.cc:1942 editor_actions.cc:201
 msgid "Set Range to Punch Range"
 msgstr "Bereich als Punchbereich"
 
-#: editor.cc:1931 editor_actions.cc:201
+#: editor.cc:1943 editor_actions.cc:202
 msgid "Set Range to Selected Regions"
 msgstr "Bereich auf ausgewählte Regionen setzen"
 
-#: editor.cc:1933 editor.cc:2007 editor_actions.cc:203 editor_actions.cc:204
+#: editor.cc:1945 editor.cc:2019 editor_actions.cc:204 editor_actions.cc:205
 msgid "Select All After Edit Point"
 msgstr "Alle Regionen nach dem Arbeitspunkt auswählen"
 
-#: editor.cc:1934 editor.cc:2008 editor_actions.cc:205 editor_actions.cc:206
+#: editor.cc:1946 editor.cc:2020 editor_actions.cc:206 editor_actions.cc:207
 msgid "Select All Before Edit Point"
 msgstr "Alle Regionen vor dem Arbeitspunkt auswählen"
 
-#: editor.cc:1935 editor.cc:2009
+#: editor.cc:1947 editor.cc:2021
 msgid "Select All After Playhead"
 msgstr "Alle Regionen nach dem Positionszeiger auswählen"
 
-#: editor.cc:1936 editor.cc:2010
+#: editor.cc:1948 editor.cc:2022
 msgid "Select All Before Playhead"
 msgstr "Alle Regionen vor dem Positionszeiger auswählen"
 
-#: editor.cc:1937
+#: editor.cc:1949
 msgid "Select All Between Playhead and Edit Point"
 msgstr "Alle zwischen Positionszeiger und Arbeitspunkt auswählen"
 
-#: editor.cc:1938
+#: editor.cc:1950
 msgid "Select All Within Playhead and Edit Point"
 msgstr "Alles zwischen Positionszeiger und Arbeitspunkt auswählen"
 
-#: editor.cc:1939
+#: editor.cc:1951
 msgid "Select Range Between Playhead and Edit Point"
 msgstr "Wähle Bereich zwischen Positionszeiger und Arbeitspunkt aus"
 
-#: editor.cc:1941 editor.cc:2012 editor_actions.cc:131 editor_actions.cc:132
+#: editor.cc:1953 editor.cc:2024 editor_actions.cc:132 editor_actions.cc:133
 msgid "Select"
 msgstr "Auswahl"
 
-#: editor.cc:1949 editor.cc:2020 editor_actions.cc:344 processor_box.cc:2518
+#: editor.cc:1961 editor.cc:2032 editor_actions.cc:345 processor_box.cc:2719
 msgid "Cut"
 msgstr "Ausschneiden"
 
-#: editor.cc:1950 editor.cc:2021 editor_actions.cc:348 processor_box.cc:2521
+#: editor.cc:1962 editor.cc:2033 editor_actions.cc:349 processor_box.cc:2721
 msgid "Copy"
 msgstr "Kopieren"
 
-#: editor.cc:1951 editor.cc:2022 editor_actions.cc:349 processor_box.cc:2529
+#: editor.cc:1963 editor.cc:2034 editor_actions.cc:350 processor_box.cc:2726
 msgid "Paste"
 msgstr "Einfügen"
 
-#: editor.cc:1955 editor_actions.cc:91
+#: editor.cc:1967 editor_actions.cc:92
 msgid "Align"
 msgstr "Ausrichten"
 
-#: editor.cc:1956
+#: editor.cc:1968
 msgid "Align Relative"
 msgstr "Relativ ausrichten"
 
-#: editor.cc:1963
+#: editor.cc:1975
 msgid "Insert Selected Region"
 msgstr "Ausgewählte Region einfügen"
 
-#: editor.cc:1964
+#: editor.cc:1976
 msgid "Insert Existing Media"
 msgstr "Vorhandenes Material importieren"
 
-#: editor.cc:1973 editor.cc:2029
+#: editor.cc:1985 editor.cc:2041
 msgid "Nudge Entire Track Later"
 msgstr "Gesamte Spur schrittweise nach hinten"
 
-#: editor.cc:1974 editor.cc:2030
+#: editor.cc:1986 editor.cc:2042
 msgid "Nudge Track After Edit Point Later"
 msgstr "Spur nach Arbeitspunkt schrittweise nach hinten"
 
-#: editor.cc:1975 editor.cc:2031
+#: editor.cc:1987 editor.cc:2043
 msgid "Nudge Entire Track Earlier"
 msgstr "Gesamte Spur schrittweise nach vorne"
 
-#: editor.cc:1976 editor.cc:2032
+#: editor.cc:1988 editor.cc:2044
 msgid "Nudge Track After Edit Point Earlier"
 msgstr "Spur nach Arbeitspunkt schrittweise nach vorne"
 
-#: editor.cc:1978 editor.cc:2034
+#: editor.cc:1990 editor.cc:2046
 msgid "Nudge"
 msgstr "Verschieben"
 
-#: editor.cc:2249
+#: editor.cc:2261
 msgid ""
 "Playhead position stored with a negative value - ignored (use zero instead)"
 msgstr ""
 "Positionzeiger mit negativer Position - ignoriert (benutze stattdessen Null)"
 
-#: editor.cc:3027 editor.cc:3724 editor.cc:3795 midi_channel_selector.cc:157
+#: editor.cc:3039 editor.cc:3738 editor.cc:3809 midi_channel_selector.cc:157
 #: midi_channel_selector.cc:395 midi_channel_selector.cc:431
 msgid "All"
 msgstr "Alle"
 
-#: editor.cc:3227
-msgid "Smart Mode (add Range functions to Grab mode)"
+#: editor.cc:3239
+msgid "Smart Mode (add range functions to Grab Mode)"
 msgstr "Smart-Modus (zusätzliche Bereichsfunktionen im Greifmodus)"
 
-#: editor.cc:3228
+#: editor.cc:3240
 msgid "Grab Mode (select/move objects)"
 msgstr "Greifmodus (Objekte auswählen/bewegen)"
 
-#: editor.cc:3229
+#: editor.cc:3241
 msgid "Cut Mode (split regions)"
 msgstr "Schneidemodus (Regionen teilen)"
 
-#: editor.cc:3230
+#: editor.cc:3242
 msgid "Range Mode (select time ranges)"
 msgstr "Bereichsmodus (Zeitbereiche auswählen)"
 
-#: editor.cc:3231
+#: editor.cc:3243
 msgid "Draw Mode (draw and edit gain/notes/automation)"
 msgstr "Zeichenmodus (zeichne und editiere Lautstärken/Noten/Automationen)"
 
-#: editor.cc:3232
+#: editor.cc:3244
 msgid "Stretch Mode (time-stretch audio and midi regions, preserving pitch)"
 msgstr ""
 "Streckmodus (Audio- und MIDI-Regionen zeitstrecken, ohne die Tonhöhe zu "
 "ändern)"
 
-#: editor.cc:3233
+#: editor.cc:3245
 msgid "Audition Mode (listen to regions)"
 msgstr "Vorhörmodus (Regionen anhören)"
 
-#: editor.cc:3234
+#: editor.cc:3246
 msgid "Internal Edit Mode (edit notes and automation points)"
 msgstr ""
 "Interner Bearbeitungsmodus (Noten und Automationspunkte innerhalb der "
-"Regionen "
-"editieren)"
+"Regionen editieren)"
 
-#: editor.cc:3235
+#: editor.cc:3247
 msgid ""
 "Groups: click to (de)activate\n"
 "Context-click for other operations"
@@ -3296,59 +3441,63 @@ msgstr ""
 "Gruppen: Klicken zum (De)aktivieren\n"
 "Rechtsklick für Optionen"
 
-#: editor.cc:3236
+#: editor.cc:3248
 msgid "Nudge Region/Selection Later"
 msgstr "Region/Auswahl schrittweise nach hinten"
 
-#: editor.cc:3237
+#: editor.cc:3249
 msgid "Nudge Region/Selection Earlier"
 msgstr "Region/Auswahl schrittweise nach vorne"
 
-#: editor.cc:3238 editor_actions.cc:269
+#: editor.cc:3250 editor_actions.cc:270
 msgid "Zoom In"
 msgstr "Vergrößern"
 
-#: editor.cc:3239 editor_actions.cc:268
+#: editor.cc:3251 editor_actions.cc:269
 msgid "Zoom Out"
 msgstr "Verkleinern"
 
-#: editor.cc:3240
+#: editor.cc:3252
 msgid "Zoom to Time Scale"
 msgstr "Zu einer Zeitspanne zoomen"
 
-#: editor.cc:3241 editor.cc:3746 editor_actions.cc:270
+#: editor.cc:3253 editor.cc:3760 editor_actions.cc:271
 msgid "Zoom to Session"
 msgstr "Auf ganzes Projekt zoomen"
 
-#: editor.cc:3242
-msgid "Zoom focus"
-msgstr "Zoom-Mittelpunkt"
+#: editor.cc:3254 editor_actions.cc:113 editor_actions.cc:146
+msgid "Zoom Focus"
+msgstr "Zoom Fokus"
 
-#: editor.cc:3243
+#: editor.cc:3255
 msgid "Expand Tracks"
 msgstr "Spuren vergrößern"
 
-#: editor.cc:3244
+#: editor.cc:3256
 msgid "Shrink Tracks"
 msgstr "Spuren verkleinern"
 
-#: editor.cc:3245
+#: editor.cc:3257
 msgid "Number of visible tracks"
 msgstr "Anzahl der sichtbaren Spuren"
 
-#: editor.cc:3246
+#: editor.cc:3258
 msgid "Snap/Grid Units"
 msgstr "Rastereinheiten"
 
-#: editor.cc:3247
+#: editor.cc:3259
 msgid "Snap/Grid Mode"
 msgstr "Einrastmodus"
 
-#: editor.cc:3249
+#: editor.cc:3260 editor_actions.cc:99
+msgid "Edit Point"
+msgstr "Arbeitspunkt"
+
+#: editor.cc:3261
 msgid "Edit Mode"
 msgstr "Bearbeitungsmodus"
 
-#: editor.cc:3250
+#: editor.cc:3262
 msgid ""
 "Nudge Clock\n"
 "(controls distance used to nudge regions and selections)"
@@ -3357,124 +3506,124 @@ msgstr ""
 "(bestimmt den Abstand für das schrittweise Verschieben von Regionen und "
 "Bereichen)"
 
-#: editor.cc:3518 editor_actions.cc:320
+#: editor.cc:3530 editor_actions.cc:321
 msgid "Command|Undo"
 msgstr "Rückgängig"
 
-#: editor.cc:3520
+#: editor.cc:3532
 msgid "Command|Undo (%1)"
 msgstr "Rückgängig (%1)"
 
-#: editor.cc:3527 editor_actions.cc:322 editor_actions.cc:323
-#: editor_actions.cc:324
+#: editor.cc:3539 editor_actions.cc:323 editor_actions.cc:324
+#: editor_actions.cc:325
 msgid "Redo"
 msgstr "Wiederherstellen"
 
-#: editor.cc:3529
+#: editor.cc:3542
 msgid "Redo (%1)"
 msgstr "Wiederherstellen (%1)"
 
-#: editor.cc:3548 editor.cc:3572 editor_actions.cc:110 editor_actions.cc:1858
+#: editor.cc:3562 editor.cc:3586 editor_actions.cc:111 editor_actions.cc:1865
 msgid "Duplicate"
 msgstr "Duplizieren"
 
-#: editor.cc:3549
+#: editor.cc:3563
 msgid "Number of duplications:"
 msgstr "Anzahl der Duplikate:"
 
-#: editor.cc:3723 route_group_dialog.cc:51 time_info_box.cc:67
+#: editor.cc:3737 route_group_dialog.cc:51 time_info_box.cc:67
 msgid "Selection"
 msgstr "Auswahl"
 
-#: editor.cc:3726
+#: editor.cc:3740
 msgid "Fit 1 track"
 msgstr "1 Spur einpassen"
 
-#: editor.cc:3727
+#: editor.cc:3741
 msgid "Fit 2 tracks"
 msgstr "2 Spuren einpassen"
 
-#: editor.cc:3728
+#: editor.cc:3742
 msgid "Fit 4 tracks"
 msgstr "4 Spuren einpassen"
 
-#: editor.cc:3729
+#: editor.cc:3743
 msgid "Fit 8 tracks"
 msgstr "8 Spuren einpassen"
 
-#: editor.cc:3730
+#: editor.cc:3744
 msgid "Fit 16 tracks"
 msgstr "16 Spuren einpassen"
 
-#: editor.cc:3731
+#: editor.cc:3745
 msgid "Fit 24 tracks"
 msgstr "24 Spuren einpassen"
 
-#: editor.cc:3732
+#: editor.cc:3746
 msgid "Fit 32 tracks"
 msgstr "32 Spuren einpassen"
 
-#: editor.cc:3733
+#: editor.cc:3747
 msgid "Fit 48 tracks"
 msgstr "48 Spuren einpassen"
 
-#: editor.cc:3734
+#: editor.cc:3748
 msgid "Fit All tracks"
 msgstr "Alle Spuren einpassen"
 
-#: editor.cc:3735
+#: editor.cc:3749
 msgid "Fit Selection"
 msgstr "Passe Auswahl ein"
 
-#: editor.cc:3737
+#: editor.cc:3751
 msgid "Zoom to 10 ms"
 msgstr "Zoome auf 10 ms"
 
-#: editor.cc:3738
+#: editor.cc:3752
 msgid "Zoom to 100 ms"
 msgstr "Zoome auf 100 ms"
 
-#: editor.cc:3739
+#: editor.cc:3753
 msgid "Zoom to 1 sec"
 msgstr "Zoome auf 1 Sek."
 
-#: editor.cc:3740
+#: editor.cc:3754
 msgid "Zoom to 10 sec"
 msgstr "Zoome auf 10 Sek."
 
-#: editor.cc:3741
+#: editor.cc:3755
 msgid "Zoom to 1 min"
 msgstr "Zoome auf 1 Min."
 
-#: editor.cc:3742
+#: editor.cc:3756
 msgid "Zoom to 10 min"
 msgstr "Zoome auf 10 Min."
 
-#: editor.cc:3743
+#: editor.cc:3757
 msgid "Zoom to 1 hour"
 msgstr "Zoome auf 1 Stunde"
 
-#: editor.cc:3744
+#: editor.cc:3758
 msgid "Zoom to 8 hours"
 msgstr "Zoome auf 8 Stunden"
 
-#: editor.cc:3745
+#: editor.cc:3759
 msgid "Zoom to 24 hours"
 msgstr "Zoome auf 24 Stunden"
 
-#: editor.cc:3747
+#: editor.cc:3761
 msgid "Zoom to Range/Region Selection"
 msgstr "Zoome auf Bereichs-/Regionenauswahl"
 
-#: editor.cc:3817
+#: editor.cc:3831
 msgid "*"
 msgstr "*"
 
-#: editor.cc:4137
+#: editor.cc:4151
 msgid "Playlist Deletion"
 msgstr "Löschen von Wiedergabelisten"
 
-#: editor.cc:4138
+#: editor.cc:4152
 msgid ""
 "Playlist %1 is currently unused.\n"
 "If it is kept, its audio files will not be cleaned.\n"
@@ -3486,1316 +3635,1330 @@ msgstr ""
 "Falls sie gelöscht wird, werden die ausschließlich von ihr verwendeten "
 "Audiodateien gelöscht."
 
-#: editor.cc:4148
+#: editor.cc:4162
+msgid "Delete All Unused"
+msgstr "Alle unbenutzten löschen"
+
+#: editor.cc:4163
 msgid "Delete Playlist"
 msgstr "Wiedergabeliste löschen"
 
-#: editor.cc:4149
+#: editor.cc:4164
 msgid "Keep Playlist"
 msgstr "Wiedergabeliste behalten"
 
-#: editor.cc:4150 editor_audio_import.cc:597 editor_ops.cc:6407
-#: engine_dialog.cc:2679 sfdb_freesound_mootcher.cc:69 processor_box.cc:2286
-#: processor_box.cc:2311
+#: editor.cc:4165
+msgid "Keep Remaining"
+msgstr "Ãœbrige behalten"
+
+#: editor.cc:4166 editor_audio_import.cc:597 editor_ops.cc:6456
+#: engine_dialog.cc:2909 sfdb_freesound_mootcher.cc:69 processor_box.cc:2487
+#: processor_box.cc:2512
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: editor.cc:4292
+#: editor.cc:4318
 msgid "new playlists"
 msgstr "Neue Wiedergabelisten"
 
-#: editor.cc:4308
+#: editor.cc:4334
 msgid "copy playlists"
 msgstr "Wiedergabelisten kopieren"
 
-#: editor.cc:4323
+#: editor.cc:4349
 msgid "clear playlists"
 msgstr "Wiedergabelisten zurücksetzen"
 
-#: editor.cc:5068
+#: editor.cc:5095
 msgid "Please wait while %1 loads visual data."
 msgstr "Bitte warten Sie, während %1 die Daten zur Anzeige des Projekts lädt."
 
-#: editor.cc:5920 editor.cc:5951 editor_markers.cc:978 panner_ui.cc:410
-#: processor_box.cc:2549
+#: editor.cc:5947 editor.cc:5982 editor_markers.cc:985 panner_ui.cc:412
+#: processor_box.cc:2746
 msgid "Edit..."
 msgstr "Bearbeiten..."
 
-#: editor.cc:5953 editor_actions.cc:1953
+#: editor.cc:5988 editor_actions.cc:1844
+msgid "Transpose..."
+msgstr "Transponieren..."
+
+#: editor.cc:5992 editor_actions.cc:1960
 msgid "Legatize"
 msgstr "überbinden (Legato)"
 
-#: editor.cc:5955 editor_actions.cc:1952
+#: editor.cc:5998 editor_actions.cc:1959
 msgid "Quantize..."
 msgstr "Quantisieren.."
 
-#: editor.cc:5957 editor_actions.cc:1955
+#: editor.cc:6001 editor_actions.cc:1962
 msgid "Remove Overlap"
 msgstr "Ãœberlappung entfernen (Legato)"
 
-#: editor.cc:5959 editor_actions.cc:1954
+#: editor.cc:6007 editor_actions.cc:1961
 msgid "Transform..."
 msgstr "Transformiere..."
 
-#: editor_actions.cc:92
+#: editor_actions.cc:93
 msgid "Autoconnect"
 msgstr "Automatisch verbinden"
 
-#: editor_actions.cc:93
+#: editor_actions.cc:94
 msgid "Crossfades"
 msgstr "Crossfades"
 
-#: editor_actions.cc:95
+#: editor_actions.cc:96
 msgid "Move Selected Marker"
 msgstr "Ausgewählten Positionsmarker verschieben"
 
-#: editor_actions.cc:96
+#: editor_actions.cc:97
 msgid "Select Range Operations"
 msgstr "Bereichs"
 
-#: editor_actions.cc:97
+#: editor_actions.cc:98
 msgid "Select Regions"
 msgstr "Region auswählen"
 
-#: editor_actions.cc:98
-msgid "Edit Point"
-msgstr "Arbeitspunkt"
-
-#: editor_actions.cc:99
+#: editor_actions.cc:100
 msgid "Fade"
 msgstr "Fade"
 
-#: editor_actions.cc:100
+#: editor_actions.cc:101
 msgid "Latch"
 msgstr "Latch"
 
-#: editor_actions.cc:101 editor_regions.cc:112 region_editor.cc:46
+#: editor_actions.cc:102 editor_regions.cc:115 region_editor.cc:48
 msgid "Region"
 msgstr "Region"
 
-#: editor_actions.cc:102
+#: editor_actions.cc:103
 msgid "Layering"
 msgstr "Layering"
 
-#: editor_actions.cc:103 editor_regions.cc:113 stereo_panner_editor.cc:44
+#: editor_actions.cc:104 editor_regions.cc:116 stereo_panner_editor.cc:44
 msgid "Position"
 msgstr "Position"
 
-#: editor_actions.cc:105 gain_meter.cc:158 gain_meter.cc:827 panner_ui.cc:176
-#: panner_ui.cc:635 route_time_axis.cc:528
+#: editor_actions.cc:106 gain_meter.cc:158 gain_meter.cc:827 panner_ui.cc:178
+#: panner_ui.cc:637 route_time_axis.cc:529
 msgid "Trim"
 msgstr "Anpassen"
 
-#: editor_actions.cc:106 editor_actions.cc:126 route_group_dialog.cc:46
+#: editor_actions.cc:107 editor_actions.cc:127 route_group_dialog.cc:46
 msgid "Gain"
 msgstr "Lautstärke"
 
-#: editor_actions.cc:107 editor_actions.cc:572
+#: editor_actions.cc:108 editor_actions.cc:579
 msgid "Ranges"
 msgstr "Bereiche"
 
-#: editor_actions.cc:108 editor_actions.cc:1854 session_option_editor.cc:135
+#: editor_actions.cc:109 editor_actions.cc:1861 session_option_editor.cc:135
 #: session_option_editor.cc:144 session_option_editor.cc:151
+#: session_option_editor.cc:158 session_option_editor.cc:165
 msgid "Fades"
 msgstr "Fades"
 
-#: editor_actions.cc:111
+#: editor_actions.cc:112
 msgid "Link"
 msgstr "Verknüpfen"
 
-#: editor_actions.cc:112 editor_actions.cc:145
-msgid "Zoom Focus"
-msgstr "Zoom Fokus"
-
-#: editor_actions.cc:113
+#: editor_actions.cc:114
 msgid "Locate to Markers"
 msgstr "Positionszeiger zu Marker setzen"
 
-#: editor_actions.cc:115
+#: editor_actions.cc:116
 msgid "Meter falloff"
 msgstr "Abfall der Pegelanzeigen"
 
-#: editor_actions.cc:116
+#: editor_actions.cc:117
 msgid "Meter hold"
 msgstr "Pegelanzeige halten"
 
-#: editor_actions.cc:117 session_option_editor.cc:321
+#: editor_actions.cc:118 session_option_editor.cc:342
 msgid "MIDI Options"
 msgstr "MIDI Optionen"
 
-#: editor_actions.cc:118
+#: editor_actions.cc:119
 msgid "Misc Options"
 msgstr "Sonstiges"
 
-#: editor_actions.cc:119 rc_option_editor.cc:2283 route_group_dialog.cc:54
-#: session_option_editor.cc:243 session_option_editor.cc:250
+#: editor_actions.cc:120 rc_option_editor.cc:2261 route_group_dialog.cc:54
+#: session_option_editor.cc:264 session_option_editor.cc:271
 msgid "Monitoring"
 msgstr "Monitoring"
 
-#: editor_actions.cc:120
+#: editor_actions.cc:121
 msgid "Active Mark"
 msgstr "Aktiver Marker"
 
-#: editor_actions.cc:123
+#: editor_actions.cc:124
 msgid "Primary Clock"
 msgstr "Erste Zeitanzeige"
 
-#: editor_actions.cc:124
+#: editor_actions.cc:125
 msgid "Pullup / Pulldown"
 msgstr "Pull-Up / Pull-Down"
 
-#: editor_actions.cc:125
+#: editor_actions.cc:126
 msgid "Region operations"
 msgstr "Region(en)"
 
-#: editor_actions.cc:127 ruler_dialog.cc:28
+#: editor_actions.cc:128 ruler_dialog.cc:28
 msgid "Rulers"
 msgstr "Markierungsleisten"
 
-#: editor_actions.cc:128
+#: editor_actions.cc:129
 msgid "Views"
 msgstr "Ansichten"
 
-#: editor_actions.cc:129
+#: editor_actions.cc:130
 msgid "Scroll"
 msgstr "Scrollen"
 
-#: editor_actions.cc:130
+#: editor_actions.cc:131
 msgid "Secondary Clock"
 msgstr "Zweite Zeitanzeige"
 
-#: editor_actions.cc:137
+#: editor_actions.cc:138
 msgid "Subframes"
 msgstr "Subframes"
 
-#: editor_actions.cc:140
+#: editor_actions.cc:141
 msgid "Timecode fps"
 msgstr "Timecode FPS"
 
-#: editor_actions.cc:141 route_time_axis.cc:586
+#: editor_actions.cc:142 route_time_axis.cc:587
 msgid "Height"
 msgstr "Höhe"
 
-#: editor_actions.cc:143
+#: editor_actions.cc:144
 msgid "Tools"
 msgstr "Werkzeuge"
 
-#: editor_actions.cc:144
+#: editor_actions.cc:145
 msgid "View"
 msgstr "Ansicht"
 
-#: editor_actions.cc:146
+#: editor_actions.cc:147
 msgid "Zoom"
 msgstr "Zoom"
 
-#: editor_actions.cc:152
+#: editor_actions.cc:153
 msgid "Break drag or deselect all"
 msgstr "Ziehen abbrechen oder alles deselektieren"
 
-#: editor_actions.cc:157
+#: editor_actions.cc:158
 msgid "Session|Lock"
 msgstr "Sperren"
 
-#: editor_actions.cc:159
+#: editor_actions.cc:160
 msgid "Show Editor Mixer"
 msgstr "Mixer-Panel zeigen"
 
-#: editor_actions.cc:160
+#: editor_actions.cc:161
 msgid "Show Editor List"
 msgstr "Seitenleiste anzeigen"
 
-#: editor_actions.cc:162
+#: editor_actions.cc:163
 msgid "Playhead to Next Region Boundary"
 msgstr "Positionszeiger zur nächsten Regiongrenze"
 
-#: editor_actions.cc:163
+#: editor_actions.cc:164
 msgid "Playhead to Next Region Boundary (No Track Selection)"
 msgstr "Positionszeiger zur nächsten Regiongrenze (ohne Spurauswahl)"
 
-#: editor_actions.cc:164
+#: editor_actions.cc:165
 msgid "Playhead to Previous Region Boundary"
 msgstr "Positionszeiger zur vorherigen Regiongrenze"
 
-#: editor_actions.cc:165
+#: editor_actions.cc:166
 msgid "Playhead to Previous Region Boundary (No Track Selection)"
 msgstr "Positionszeiger zur vorherigen Regiongrenze (ohne Spurauswahl)"
 
-#: editor_actions.cc:167
+#: editor_actions.cc:168
 msgid "Playhead to Next Region Start"
 msgstr "Positionszeiger zum Anfang der nächsten Region"
 
-#: editor_actions.cc:168
+#: editor_actions.cc:169
 msgid "Playhead to Next Region End"
 msgstr "Positionszeiger zum Ende der nächsten Region"
 
-#: editor_actions.cc:169
+#: editor_actions.cc:170
 msgid "Playhead to Next Region Sync"
 msgstr "Positionszeiger zum Einrastpunkt der nächsten Region"
 
-#: editor_actions.cc:171
+#: editor_actions.cc:172
 msgid "Playhead to Previous Region Start"
 msgstr "Positionszeiger zum Anfang der vorherigen Region"
 
-#: editor_actions.cc:172
+#: editor_actions.cc:173
 msgid "Playhead to Previous Region End"
 msgstr "Positionszeiger zum Ende der vorherigen Region"
 
-#: editor_actions.cc:173
+#: editor_actions.cc:174
 msgid "Playhead to Previous Region Sync"
 msgstr "Positionszeiger zum Einrastpunkt der vorherigen Region"
 
-#: editor_actions.cc:175
+#: editor_actions.cc:176
 msgid "To Next Region Boundary"
 msgstr "Zur nächsten Regiongrenze"
 
-#: editor_actions.cc:176
+#: editor_actions.cc:177
 msgid "To Next Region Boundary (No Track Selection)"
 msgstr "Zur nächsten Regiongrenze (ohne Spurauswahl)"
 
-#: editor_actions.cc:177
+#: editor_actions.cc:178
 msgid "To Previous Region Boundary"
 msgstr "Zur vorherigen Regiongrenze"
 
-#: editor_actions.cc:178
+#: editor_actions.cc:179
 msgid "To Previous Region Boundary (No Track Selection)"
 msgstr "Zur vorherigen Regiongrenze  (ohne Spurauswahl)"
 
-#: editor_actions.cc:180
+#: editor_actions.cc:181
 msgid "To Next Region Start"
 msgstr "Zum nächsten Regionen-Anfang"
 
-#: editor_actions.cc:181
+#: editor_actions.cc:182
 msgid "To Next Region End"
 msgstr "Zum nächsten Regionen-Ende"
 
-#: editor_actions.cc:182
+#: editor_actions.cc:183
 msgid "To Next Region Sync"
 msgstr "Zum nächsten Regionen-Synchronisationspunkt"
 
-#: editor_actions.cc:184
+#: editor_actions.cc:185
 msgid "To Previous Region Start"
 msgstr "Zum vorherigen Anfang einer Region"
 
-#: editor_actions.cc:185
+#: editor_actions.cc:186
 msgid "To Previous Region End"
 msgstr "Zum vorherigen Ende einer Region"
 
-#: editor_actions.cc:186
+#: editor_actions.cc:187
 msgid "To Previous Region Sync"
 msgstr "Zum vorherigen Synchronisationspunkt einer Region"
 
-#: editor_actions.cc:188
+#: editor_actions.cc:189
 msgid "To Range Start"
 msgstr "Zum Anfang des Auswahlbereichs"
 
-#: editor_actions.cc:189
+#: editor_actions.cc:190
 msgid "To Range End"
 msgstr "Zum Ende des Auswahlbereichs"
 
-#: editor_actions.cc:191
+#: editor_actions.cc:192
 msgid "Playhead to Range Start"
 msgstr "Positionszeiger zum Anfang des Auswahlbereichs"
 
-#: editor_actions.cc:192
+#: editor_actions.cc:193
 msgid "Playhead to Range End"
 msgstr "Positionszeiger zum Ende des Auswahlbereichs"
 
-#: editor_actions.cc:195
+#: editor_actions.cc:196
 msgid "Select All Tracks"
 msgstr "Alle Spuren auswählen"
 
-#: editor_actions.cc:196 export_timespan_selector.cc:61 processor_box.cc:2535
+#: editor_actions.cc:197 export_timespan_selector.cc:59 processor_box.cc:2732
 msgid "Deselect All"
 msgstr "Nichts auswählen"
 
-#: editor_actions.cc:199
-msgid "Set Range in Loop Range"
-msgstr "Bereich auf Schleife setzen"
-
-#: editor_actions.cc:208
+#: editor_actions.cc:209
 msgid "Select All Overlapping Edit Range"
 msgstr "Alle Regionen des Bearbeitungsbereichs auswählen "
 
-#: editor_actions.cc:209
+#: editor_actions.cc:210
 msgid "Select All Inside Edit Range"
 msgstr "Alles inerhalb des Bearbeitungsbereichs auswählen"
 
-#: editor_actions.cc:211
+#: editor_actions.cc:212
 msgid "Select Edit Range"
 msgstr "Editierbereich auswählen"
 
-#: editor_actions.cc:213
+#: editor_actions.cc:214
 msgid "Select All in Punch Range"
 msgstr "Alle Regionen im Punchbereich auswählen"
 
-#: editor_actions.cc:214
+#: editor_actions.cc:215
 msgid "Select All in Loop Range"
 msgstr "Alle Regionen innerhalb der Schleife auswählen"
 
-#: editor_actions.cc:216
+#: editor_actions.cc:217
 msgid "Select Next Track or Bus"
 msgstr "Nächste Spur/Bus auswählen"
 
-#: editor_actions.cc:217
+#: editor_actions.cc:218
 msgid "Select Previous Track or Bus"
 msgstr "Vorherige Spur/Bus auswählen"
 
-#: editor_actions.cc:219
+#: editor_actions.cc:220
 msgid "Toggle Record Enable"
 msgstr "Aufnahmebereitschaft umschalten"
 
-#: editor_actions.cc:221
+#: editor_actions.cc:222
 msgid "Toggle Solo"
 msgstr "Solo umschalten"
 
-#: editor_actions.cc:223
+#: editor_actions.cc:224
 msgid "Toggle Mute"
 msgstr "Mute umschalten"
 
-#: editor_actions.cc:225
+#: editor_actions.cc:226
 msgid "Toggle Solo Isolate"
 msgstr "Isoliertes Solo umschalten"
 
-#: editor_actions.cc:230
+#: editor_actions.cc:231
 msgid "Save View %1"
 msgstr "Ansicht %1 speichern"
 
-#: editor_actions.cc:236
+#: editor_actions.cc:237
 msgid "Go to View %1"
 msgstr "Ansicht %1 aufrufen"
 
-#: editor_actions.cc:242
+#: editor_actions.cc:243
 msgid "Locate to Mark %1"
 msgstr "Positionszeiger zu Marker %1 setzen"
 
-#: editor_actions.cc:246 editor_actions.cc:247
+#: editor_actions.cc:247 editor_actions.cc:248
 msgid "Jump to Next Mark"
 msgstr "Zu nächstem Marker springen"
 
-#: editor_actions.cc:248 editor_actions.cc:249
+#: editor_actions.cc:249 editor_actions.cc:250
 msgid "Jump to Previous Mark"
 msgstr "Zur vorherigen Marker springen"
 
-#: editor_actions.cc:251
+#: editor_actions.cc:252
 msgid "Set Session Start from Playhead"
 msgstr "Projektbeginn auf Positionszeiger setzen"
 
-#: editor_actions.cc:252
+#: editor_actions.cc:253
 msgid "Set Session End from Playhead"
 msgstr "Projektende auf Positionszeiger setzen"
 
-#: editor_actions.cc:254 editor_actions.cc:255
+#: editor_actions.cc:255 editor_actions.cc:256
 msgid "Add Mark from Playhead"
 msgstr "Marker am Positionszeiger setzen"
 
-#: editor_actions.cc:257 editor_actions.cc:258
+#: editor_actions.cc:258 editor_actions.cc:259
 msgid "Remove Mark at Playhead"
 msgstr "Marker beim Positionszeiger entfernen"
 
-#: editor_actions.cc:260
+#: editor_actions.cc:261
 msgid "Nudge Next Later"
 msgstr "Nächste Region schrittweise nach hinten"
 
-#: editor_actions.cc:261
+#: editor_actions.cc:262
 msgid "Nudge Next Earlier"
 msgstr "Nächste Region schrittweise nach vorne"
 
-#: editor_actions.cc:263
+#: editor_actions.cc:264
 msgid "Nudge Playhead Forward"
 msgstr "Positionszeiger vorwärts"
 
-#: editor_actions.cc:264
+#: editor_actions.cc:265
 msgid "Nudge Playhead Backward"
 msgstr "Positionszeiger rückwärts"
 
-#: editor_actions.cc:265
-msgid "Playhead To Next Grid"
+#: editor_actions.cc:266
+msgid "Playhead to Next Grid"
 msgstr "Positionszeiger zum nächsten Rasterpunkt"
 
-#: editor_actions.cc:266
-msgid "Playhead To Previous Grid"
+#: editor_actions.cc:267
+msgid "Playhead to Previous Grid"
 msgstr "Positionszeiger zum vorherigen Rasterpunkt"
 
-#: editor_actions.cc:271
+#: editor_actions.cc:272
 msgid "Zoom to Selection"
 msgstr "Zoome zu Auswahl"
 
-#: editor_actions.cc:272
+#: editor_actions.cc:273
 msgid "Toggle Zoom State"
-msgstr "Letzten Zoom wählen"
+msgstr "Zoomstatus umschalten"
 
-#: editor_actions.cc:274
+#: editor_actions.cc:275
 msgid "Expand Track Height"
 msgstr "Spurhöhe vergrößern"
 
-#: editor_actions.cc:275
+#: editor_actions.cc:276
 msgid "Shrink Track Height"
 msgstr "Spurhöhe verkleinern"
 
-#: editor_actions.cc:277
+#: editor_actions.cc:278
 msgid "Move Selected Tracks Up"
 msgstr "Ausgewählte Spuren nach oben verschieben"
 
-#: editor_actions.cc:279
+#: editor_actions.cc:280
 msgid "Move Selected Tracks Down"
 msgstr "Ausgewählte Spuren nach unten verschieben"
 
-#: editor_actions.cc:282
+#: editor_actions.cc:283
 msgid "Scroll Tracks Up"
 msgstr "Spuren nach oben scrollen"
 
-#: editor_actions.cc:284
+#: editor_actions.cc:285
 msgid "Scroll Tracks Down"
 msgstr "Spuren nach unten scrollen"
 
-#: editor_actions.cc:286
+#: editor_actions.cc:287
 msgid "Step Tracks Up"
 msgstr "Spuren langsam nach oben scrollen"
 
-#: editor_actions.cc:288
+#: editor_actions.cc:289
 msgid "Step Tracks Down"
 msgstr "Spuren langsam nach unten scrollen"
 
-#: editor_actions.cc:291
+#: editor_actions.cc:292
 msgid "Scroll Backward"
 msgstr "Nach rechts scrollen"
 
-#: editor_actions.cc:292
+#: editor_actions.cc:293
 msgid "Scroll Forward"
 msgstr "Nach links scrollen"
 
-#: editor_actions.cc:293
+#: editor_actions.cc:294
 msgid "Center Playhead"
 msgstr "Positionszeiger zentrieren"
 
-#: editor_actions.cc:294
+#: editor_actions.cc:295
 msgid "Center Edit Point"
 msgstr "Arbeitspunkt zentrieren"
 
-#: editor_actions.cc:296
+#: editor_actions.cc:297
 msgid "Playhead Forward"
 msgstr "Positionszeiger vorwärts"
 
-#: editor_actions.cc:297
+#: editor_actions.cc:298
 msgid "Playhead Backward"
 msgstr "Positionszeiger rückwärts"
 
-#: editor_actions.cc:299
+#: editor_actions.cc:300
 msgid "Playhead to Active Mark"
 msgstr "Positionszeiger zur aktiven Markierung"
 
-#: editor_actions.cc:300
+#: editor_actions.cc:301
 msgid "Active Mark to Playhead"
 msgstr "Aktiven Marker zum Positionszeiger verschieben"
 
-#: editor_actions.cc:302
+#: editor_actions.cc:303
 msgid "Use Skip Ranges"
 msgstr "Benutze Sprungbereiche"
 
-#: editor_actions.cc:309
+#: editor_actions.cc:310
 msgid "Play Selected Regions"
 msgstr "Ausgewählte Regionen wiedergeben"
 
-#: editor_actions.cc:311
+#: editor_actions.cc:312
 msgid "Play from Edit Point and Return"
 msgstr "Wiedergabe ab Arbeitspunkt & Zurück"
 
-#: editor_actions.cc:313
+#: editor_actions.cc:314
 msgid "Play Edit Range"
 msgstr "Editierbereich wiedergeben"
 
-#: editor_actions.cc:315
+#: editor_actions.cc:316
 msgid "Playhead to Mouse"
 msgstr "Positionszeiger zur Mausposition"
 
-#: editor_actions.cc:316
+#: editor_actions.cc:317
 msgid "Active Marker to Mouse"
 msgstr "Aktiven Marker zur Mausposition"
 
-#: editor_actions.cc:326
+#: editor_actions.cc:327
 msgid "Undo Selection Change"
 msgstr "Auswahländerung rückgängig machen"
 
-#: editor_actions.cc:327
+#: editor_actions.cc:328
 msgid "Redo Selection Change"
 msgstr "Auswahländerung wiederherstellen"
 
-#: editor_actions.cc:329
+#: editor_actions.cc:330
 msgid "Export Audio"
 msgstr "Audio exportieren"
 
-#: editor_actions.cc:330 export_dialog.cc:396
+#: editor_actions.cc:331 export_dialog.cc:394
 msgid "Export Range"
 msgstr "Bereich exportieren"
 
-#: editor_actions.cc:335
+#: editor_actions.cc:336
 msgid "Separate Using Punch Range"
 msgstr "an Punch-Bereichsgrenzen teilen"
 
-#: editor_actions.cc:338
+#: editor_actions.cc:339
 msgid "Separate Using Loop Range"
 msgstr "an Schleifengrenzen teilen"
 
-#: editor_actions.cc:341 editor_actions.cc:363
+#: editor_actions.cc:342 editor_actions.cc:364
 msgid "Crop"
 msgstr "Auf Bereich zuschneiden"
 
-#: editor_actions.cc:351
+#: editor_actions.cc:352
 msgid "Fade Range Selection"
 msgstr "Bereichsauswahl faden"
 
-#: editor_actions.cc:353
+#: editor_actions.cc:354
 msgid "Set Tempo from Edit Range = Bar"
 msgstr "Editierbereich = Taktlänge setzen"
 
-#: editor_actions.cc:355
+#: editor_actions.cc:356
 msgid "Log"
 msgstr "Log"
 
-#: editor_actions.cc:358 editor_actions.cc:360
+#: editor_actions.cc:359 editor_actions.cc:361
 msgid "Move to Next Transient"
 msgstr "Zum nächsten Transienten bewegen"
 
-#: editor_actions.cc:359 editor_actions.cc:361
+#: editor_actions.cc:360 editor_actions.cc:362
 msgid "Move to Previous Transient"
 msgstr "Zum vorigen Transienten bewegen"
 
-#: editor_actions.cc:365 editor_actions.cc:368
+#: editor_actions.cc:366 editor_actions.cc:375
 msgid "Start Range"
 msgstr "Bereich beginnen"
 
-#: editor_actions.cc:366 editor_actions.cc:369
+#: editor_actions.cc:367 editor_actions.cc:376
 msgid "Finish Range"
 msgstr "Bereich beenden"
 
-#: editor_actions.cc:401
+#: editor_actions.cc:369
+msgid "Start Punch Range"
+msgstr "Beginne Punchbereich"
+
+#: editor_actions.cc:370
+msgid "Finish Punch Range"
+msgstr "Beende Punchbereich"
+
+#: editor_actions.cc:372
+msgid "Start Loop Range"
+msgstr "Beginne Schleifenbereich"
+
+#: editor_actions.cc:373
+msgid "Finish Loop Range"
+msgstr "Beende Schleifenbereich"
+
+#: editor_actions.cc:408
 msgid "Follow Playhead"
 msgstr "Positionszeiger folgen"
 
-#: editor_actions.cc:402
+#: editor_actions.cc:409
 msgid "Remove Last Capture"
 msgstr "Letzte Aufnahme entfernen"
 
-#: editor_actions.cc:404
+#: editor_actions.cc:411
 msgid "Stationary Playhead"
 msgstr "stehender Positionszeiger"
 
-#: editor_actions.cc:406 insert_remove_time_dialog.cc:32
+#: editor_actions.cc:413 insert_remove_time_dialog.cc:32
 msgid "Insert Time"
 msgstr "Stille Einfügen"
 
-#: editor_actions.cc:408 insert_remove_time_dialog.cc:32
+#: editor_actions.cc:415 insert_remove_time_dialog.cc:32
 msgid "Remove Time"
 msgstr "Zeit entfernen"
 
-#: editor_actions.cc:413
+#: editor_actions.cc:420
 msgid "Toggle Active"
 msgstr "Spur De/Aktivieren"
 
-#: editor_actions.cc:415 editor_actions.cc:1780 editor_markers.cc:914
-#: editor_markers.cc:979 editor_snapshots.cc:122 mixer_strip.cc:1603
-#: route_time_axis.cc:867
+#: editor_actions.cc:422 editor_actions.cc:1787 editor_markers.cc:921
+#: editor_markers.cc:986 editor_snapshots.cc:134 mixer_strip.cc:1621
+#: route_time_axis.cc:872
 msgid "Remove"
 msgstr "Löschen"
 
-#: editor_actions.cc:420
+#: editor_actions.cc:427
 msgid "Fit Selection (Vertical)"
 msgstr "Auswahl einpassen (vertikal)"
 
-#: editor_actions.cc:422 time_axis_view.cc:1382
+#: editor_actions.cc:429 time_axis_view.cc:1380
 msgid "Largest"
 msgstr "Am größten"
 
-#: editor_actions.cc:425 time_axis_view.cc:1383
+#: editor_actions.cc:432 time_axis_view.cc:1381
 msgid "Larger"
 msgstr "Größer"
 
-#: editor_actions.cc:428 editor_rulers.cc:249 time_axis_view.cc:1384
+#: editor_actions.cc:435 editor_rulers.cc:248 time_axis_view.cc:1382
 msgid "Large"
 msgstr "Groß"
 
-#: editor_actions.cc:434 editor_rulers.cc:253 time_axis_view.cc:1386
+#: editor_actions.cc:441 editor_rulers.cc:252 time_axis_view.cc:1384
 msgid "Small"
 msgstr "Klein"
 
-#: editor_actions.cc:438
+#: editor_actions.cc:445
 msgid "Sound Selected MIDI Notes"
 msgstr "ausgewählte Noten abspielen"
 
-#: editor_actions.cc:443
+#: editor_actions.cc:450
 msgid "Zoom Focus Left"
 msgstr "Am linken Rand ausrichten"
 
-#: editor_actions.cc:444
+#: editor_actions.cc:451
 msgid "Zoom Focus Right"
 msgstr "Am rechten Rand ausrichten"
 
-#: editor_actions.cc:445
+#: editor_actions.cc:452
 msgid "Zoom Focus Center"
 msgstr "Zentriert ausrichten"
 
-#: editor_actions.cc:446
+#: editor_actions.cc:453
 msgid "Zoom Focus Playhead"
 msgstr "Am Positionszeiger ausrichten"
 
-#: editor_actions.cc:447
+#: editor_actions.cc:454
 msgid "Zoom Focus Mouse"
 msgstr "Zoom Fokus zur Maus"
 
-#: editor_actions.cc:448
+#: editor_actions.cc:455
 msgid "Zoom Focus Edit Point"
 msgstr "Zoom Fokus zu Arbeitspunkt"
 
-#: editor_actions.cc:450
+#: editor_actions.cc:457
 msgid "Next Zoom Focus"
 msgstr "Zoom FokusNächster "
 
-#: editor_actions.cc:456
+#: editor_actions.cc:463
 msgid "Smart Object Mode"
 msgstr "Smarter Objektmodus"
 
-#: editor_actions.cc:459
+#: editor_actions.cc:466
 msgid "Smart"
 msgstr "Smart"
 
-#: editor_actions.cc:462
+#: editor_actions.cc:469
 msgid "Object Tool"
 msgstr "Objektwerkzeug"
 
-#: editor_actions.cc:467
+#: editor_actions.cc:474
 msgid "Range Tool"
 msgstr "Bereich-Werkzeug (Range)"
 
-#: editor_actions.cc:472
+#: editor_actions.cc:479
 msgid "Note Drawing Tool"
 msgstr "Noten-Malwerkzeug"
 
-#: editor_actions.cc:477
+#: editor_actions.cc:484
 msgid "Audition Tool"
 msgstr "Vorhör-Werkzeug"
 
-#: editor_actions.cc:482
+#: editor_actions.cc:489
 msgid "Time FX Tool"
 msgstr "TimeFX-Werkzeug"
 
-#: editor_actions.cc:487
+#: editor_actions.cc:494
 msgid "Content Tool"
 msgstr "Inhaltswerkzeug"
 
-#: editor_actions.cc:493
+#: editor_actions.cc:500
 msgid "Cut Tool"
 msgstr "Schneidewerkzeug"
 
-#: editor_actions.cc:499
+#: editor_actions.cc:506
 msgid "Step Mouse Mode"
 msgstr "Schritt-Mausmodus"
 
-#: editor_actions.cc:506
+#: editor_actions.cc:513
 msgid "Change Edit Point"
 msgstr "Arbeitspunkt ändern"
 
-#: editor_actions.cc:507
+#: editor_actions.cc:514
 msgid "Change Edit Point Including Marker"
 msgstr "Arbeitspunkt ändern (auch auf Marker wechseln)"
 
-#: editor_actions.cc:512
+#: editor_actions.cc:519
 msgid "EditMode|Lock"
 msgstr "Sperren"
 
-#: editor_actions.cc:513
+#: editor_actions.cc:520
 msgid "Cycle Edit Mode"
 msgstr "Bearbeitungsmodus weiterschalten"
 
-#: editor_actions.cc:515
+#: editor_actions.cc:522
 msgid "Snap to"
 msgstr "Einrasten"
 
-#: editor_actions.cc:516
+#: editor_actions.cc:523
 msgid "Snap Mode"
 msgstr "Einrastmodus"
 
-#: editor_actions.cc:523
+#: editor_actions.cc:530
 msgid "Next Snap Mode"
 msgstr "Nächster Einrastmodus"
 
-#: editor_actions.cc:524
+#: editor_actions.cc:531
 msgid "Next Snap Choice"
 msgstr "Nächste Einrastmöglichkeit"
 
-#: editor_actions.cc:525
+#: editor_actions.cc:532
 msgid "Next Musical Snap Choice"
 msgstr "Nächster Einrastmöglichkeit (musikalisch)"
 
-#: editor_actions.cc:526
+#: editor_actions.cc:533
 msgid "Previous Snap Choice"
 msgstr "Vorige Einrastmöglichkeit"
 
-#: editor_actions.cc:527
+#: editor_actions.cc:534
 msgid "Previous Musical Snap Choice"
 msgstr " Vorige Einrastmöglichkeit (musikalisch)"
 
-#: editor_actions.cc:532
+#: editor_actions.cc:539
 msgid "Snap to CD Frame"
 msgstr "An CD-Frames einrasten"
 
-#: editor_actions.cc:533
+#: editor_actions.cc:540
 msgid "Snap to Timecode Frame"
 msgstr "An Timecode-Frames einrasten"
 
-#: editor_actions.cc:534
+#: editor_actions.cc:541
 msgid "Snap to Timecode Seconds"
 msgstr "An Timecode-Sekunden einrasten"
 
-#: editor_actions.cc:535
+#: editor_actions.cc:542
 msgid "Snap to Timecode Minutes"
 msgstr "An Timecode-Minuten einrasten"
 
-#: editor_actions.cc:536
+#: editor_actions.cc:543
 msgid "Snap to Seconds"
 msgstr "An Sekunden einrasten"
 
-#: editor_actions.cc:537
+#: editor_actions.cc:544
 msgid "Snap to Minutes"
 msgstr "An Minuten einrasten"
 
-#: editor_actions.cc:539
+#: editor_actions.cc:546
 msgid "Snap to One Twenty Eighths"
 msgstr "An Schläge/28 einrasten"
 
-#: editor_actions.cc:540
+#: editor_actions.cc:547
 msgid "Snap to Sixty Fourths"
 msgstr "An Schläge/128 einrasten"
 
-#: editor_actions.cc:541
+#: editor_actions.cc:548
 msgid "Snap to Thirty Seconds"
 msgstr "An Schläge/32 einrasten"
 
-#: editor_actions.cc:542
+#: editor_actions.cc:549
 msgid "Snap to Twenty Eighths"
 msgstr "An Schläge/28 einrasten"
 
-#: editor_actions.cc:543
+#: editor_actions.cc:550
 msgid "Snap to Twenty Fourths"
 msgstr "An Schläge/24 einrasten"
 
-#: editor_actions.cc:544
+#: editor_actions.cc:551
 msgid "Snap to Twentieths"
 msgstr "An Schläge/20 einrasten"
 
-#: editor_actions.cc:545
+#: editor_actions.cc:552
 msgid "Snap to Sixteenths"
 msgstr "An Schläge/16 einrasten"
 
-#: editor_actions.cc:546
+#: editor_actions.cc:553
 msgid "Snap to Fourteenths"
 msgstr "An Schläge/14 einrasten"
 
-#: editor_actions.cc:547
+#: editor_actions.cc:554
 msgid "Snap to Twelfths"
 msgstr "An Schläge/12 einrasten"
 
-#: editor_actions.cc:548
+#: editor_actions.cc:555
 msgid "Snap to Tenths"
 msgstr "An Schläge/10 einrasten"
 
-#: editor_actions.cc:549
+#: editor_actions.cc:556
 msgid "Snap to Eighths"
 msgstr "An Schläge/8 einrasten"
 
-#: editor_actions.cc:550
+#: editor_actions.cc:557
 msgid "Snap to Sevenths"
 msgstr "An Schläge/7 einrasten"
 
-#: editor_actions.cc:551
+#: editor_actions.cc:558
 msgid "Snap to Sixths"
 msgstr "An Schläge/6 einrasten"
 
-#: editor_actions.cc:552
+#: editor_actions.cc:559
 msgid "Snap to Fifths"
 msgstr "An Schläge/5 einrasten"
 
-#: editor_actions.cc:553
+#: editor_actions.cc:560
 msgid "Snap to Quarters"
 msgstr "An Schläge/4 einrasten"
 
-#: editor_actions.cc:554
+#: editor_actions.cc:561
 msgid "Snap to Thirds"
 msgstr "An Triolen einrasten"
 
-#: editor_actions.cc:555
+#: editor_actions.cc:562
 msgid "Snap to Halves"
 msgstr "An Schläge/2 einrasten"
 
-#: editor_actions.cc:557
+#: editor_actions.cc:564
 msgid "Snap to Beat"
 msgstr "An Schlägen einrasten"
 
-#: editor_actions.cc:558
+#: editor_actions.cc:565
 msgid "Snap to Bar"
 msgstr "An Takten einrasten"
 
-#: editor_actions.cc:559
+#: editor_actions.cc:566
 msgid "Snap to Mark"
 msgstr "An Markern einrasten"
 
-#: editor_actions.cc:560
+#: editor_actions.cc:567
 msgid "Snap to Region Start"
 msgstr "An Regionenanfang einrasten"
 
-#: editor_actions.cc:561
+#: editor_actions.cc:568
 msgid "Snap to Region End"
 msgstr "An Regionenende einrasten"
 
-#: editor_actions.cc:562
+#: editor_actions.cc:569
 msgid "Snap to Region Sync"
 msgstr "An Regionen-Synchronisationspunkt einrasten"
 
-#: editor_actions.cc:563
+#: editor_actions.cc:570
 msgid "Snap to Region Boundary"
 msgstr "An Regionengrenzen einrasten"
 
-#: editor_actions.cc:565
+#: editor_actions.cc:572
 msgid "Show Marker Lines"
 msgstr "Markerlinien anzeigen"
 
-#: editor_actions.cc:575
+#: editor_actions.cc:582
 msgid "Loop/Punch"
 msgstr "Schleifen/Punchbereiche"
 
-#: editor_actions.cc:579
+#: editor_actions.cc:586
 msgid "Min:Sec"
 msgstr "Min:Sek"
 
-#: editor_actions.cc:581 editor_actions.cc:584 editor_rulers.cc:271
+#: editor_actions.cc:588 editor_actions.cc:591 editor_rulers.cc:270
 msgid "Video Monitor"
 msgstr "Videomonitor"
 
-#: editor_actions.cc:583 rc_option_editor.cc:2734
+#: editor_actions.cc:590 rc_option_editor.cc:2720
 msgid "Video"
 msgstr "Video"
 
-#: editor_actions.cc:586
+#: editor_actions.cc:593
 msgid "Always on Top"
 msgstr "Immer oben"
 
-#: editor_actions.cc:588
+#: editor_actions.cc:595
 msgid "Frame number"
 msgstr "Framenummer"
 
-#: editor_actions.cc:589
+#: editor_actions.cc:596
 msgid "Timecode Background"
 msgstr "Timecode-Hintergrund"
 
-#: editor_actions.cc:590
+#: editor_actions.cc:597
 msgid "Fullscreen"
 msgstr "Vollbild"
 
-#: editor_actions.cc:591
+#: editor_actions.cc:598
 msgid "Letterbox"
 msgstr "Letterbox"
 
-#: editor_actions.cc:592
+#: editor_actions.cc:599
 msgid "Original Size"
 msgstr "Originalgröße"
 
-#: editor_actions.cc:649
+#: editor_actions.cc:656
 msgid "Sort"
 msgstr "Sortieren"
 
-#: editor_actions.cc:660 editor_routes.cc:484 mixer_ui.cc:1212
+#: editor_actions.cc:667 editor_routes.cc:485 mixer_ui.cc:1259
 msgid "Show All"
 msgstr "Alles anzeigen"
 
-#: editor_actions.cc:661
+#: editor_actions.cc:668
 msgid "Show Automatic Regions"
 msgstr "Automatische Regionen anzeigen"
 
-#: editor_actions.cc:663
+#: editor_actions.cc:670
 msgid "Ascending"
 msgstr "aufsteigend"
 
-#: editor_actions.cc:665
+#: editor_actions.cc:672
 msgid "Descending"
 msgstr "absteigend"
 
-#: editor_actions.cc:668
+#: editor_actions.cc:675
 msgid "By Region Name"
 msgstr "nach Name der Region"
 
-#: editor_actions.cc:670
+#: editor_actions.cc:677
 msgid "By Region Length"
 msgstr "nach Länge der Region"
 
-#: editor_actions.cc:672
+#: editor_actions.cc:679
 msgid "By Region Position"
 msgstr "nach Position der Region"
 
-#: editor_actions.cc:674
+#: editor_actions.cc:681
 msgid "By Region Timestamp"
 msgstr "nach Zeitstempel der Region"
 
-#: editor_actions.cc:676
+#: editor_actions.cc:683
 msgid "By Region Start in File"
 msgstr "nach Anfang der Region in der Datei"
 
-#: editor_actions.cc:678
+#: editor_actions.cc:685
 msgid "By Region End in File"
 msgstr "nach Ende der Region in der Datei"
 
-#: editor_actions.cc:680
+#: editor_actions.cc:687
 msgid "By Source File Name"
 msgstr "nach Namen der Quelldatei"
 
-#: editor_actions.cc:682
+#: editor_actions.cc:689
 msgid "By Source File Length"
 msgstr "nach Länge der Quelldatei"
 
-#: editor_actions.cc:684
+#: editor_actions.cc:691
 msgid "By Source File Creation Date"
 msgstr "nach Erstellungsdatum der Quelldatei"
 
-#: editor_actions.cc:686
+#: editor_actions.cc:693
 msgid "By Source Filesystem"
 msgstr "nach Dateisystem der Quelle"
 
-#: editor_actions.cc:689
+#: editor_actions.cc:696
 msgid "Remove Unused"
 msgstr "Ungenutzte entfernen"
 
-#: editor_actions.cc:691
+#: editor_actions.cc:698
 msgid "Import PT session"
 msgstr "PT Projekt importieren"
 
-#: editor_actions.cc:696 editor_audio_import.cc:282 editor_pt_import.cc:148
+#: editor_actions.cc:703 editor_audio_import.cc:282 editor_pt_import.cc:148
 #: session_import_dialog.cc:75 session_import_dialog.cc:95
-#: session_metadata_dialog.cc:418 editor_videotimeline.cc:91
+#: session_metadata_dialog.cc:418 sfdb_ui.cc:558 editor_videotimeline.cc:91
 msgid "Import"
 msgstr "Importieren"
 
-#: editor_actions.cc:699
+#: editor_actions.cc:706
 msgid "Import to Region List..."
 msgstr "In Regionenliste importieren"
 
-#: editor_actions.cc:702 session_import_dialog.cc:44
-msgid "Import From Session"
+#: editor_actions.cc:709 session_import_dialog.cc:44
+#: session_import_dialog.cc:65
+msgid "Import from Session"
 msgstr "Aus Projekt importieren"
 
-#: editor_actions.cc:706
+#: editor_actions.cc:713
 msgid "Bring all media into session folder"
 msgstr "Alle Medien in Projektordner kopieren"
 
-#: editor_actions.cc:709
+#: editor_actions.cc:716
 msgid "Show Summary"
 msgstr "Projektübersicht anzeigen"
 
-#: editor_actions.cc:711
+#: editor_actions.cc:718
 msgid "Show Group Tabs"
 msgstr "Gruppierungsleiste anzeigen"
 
-#: editor_actions.cc:713
+#: editor_actions.cc:720
 msgid "Show Measure Lines"
 msgstr "Zeige Taktlinien"
 
-#: editor_actions.cc:717
+#: editor_actions.cc:724
 msgid "Show Logo"
 msgstr "Zeige Logo"
 
-#: editor_actions.cc:721
+#: editor_actions.cc:728
 msgid "Toggle MIDI Input Active for Editor-Selected Tracks/Busses"
 msgstr "MIDI Eingang für im Editor ausgewählte Spuren/Busse de/aktivieren"
 
-#: editor_actions.cc:744
+#: editor_actions.cc:751
 msgid "Loaded editor bindings from %1"
 msgstr "Editor-Tastenkürzel aus %1 geladen"
 
-#: editor_actions.cc:746
+#: editor_actions.cc:753
 msgid "Could not find editor.bindings in search path %1"
 msgstr "Konnte editor.bindings im Suchpfad %1 nicht finden"
 
-#: editor_actions.cc:1090 editor_actions.cc:1486 editor_actions.cc:1497
-#: editor_actions.cc:1550 editor_actions.cc:1561 editor_actions.cc:1608
-#: editor_actions.cc:1618 editor_regions.cc:1571
+#: editor_actions.cc:1097 editor_actions.cc:1493 editor_actions.cc:1504
+#: editor_actions.cc:1557 editor_actions.cc:1568 editor_actions.cc:1615
+#: editor_actions.cc:1625 editor_regions.cc:1574
 msgid "programming error: %1: %2"
 msgstr "Programmierfehler: %1: %2"
 
-#: editor_actions.cc:1786
+#: editor_actions.cc:1793
 msgid "Raise"
 msgstr "Nach oben"
 
-#: editor_actions.cc:1789
+#: editor_actions.cc:1796
 msgid "Raise to Top"
 msgstr "Ganz nach oben"
 
-#: editor_actions.cc:1792
+#: editor_actions.cc:1799
 msgid "Lower"
 msgstr "Nach unten"
 
-#: editor_actions.cc:1795
+#: editor_actions.cc:1802
 msgid "Lower to Bottom"
 msgstr "Ganz nach unten"
 
-#: editor_actions.cc:1798
+#: editor_actions.cc:1805
 msgid "Move to Original Position"
 msgstr "Zur Ursprungsposition verschieben"
 
-#: editor_actions.cc:1803
+#: editor_actions.cc:1810
 msgid "Lock to Video"
 msgstr "an Video koppeln"
 
-#: editor_actions.cc:1808 editor_markers.cc:905
+#: editor_actions.cc:1815 editor_markers.cc:912
 msgid "Glue to Bars and Beats"
 msgstr "An Takte und Schläge binden"
 
-#: editor_actions.cc:1813
+#: editor_actions.cc:1820
 msgid "Remove Sync"
 msgstr "Synchronisationspunkt entfernen"
 
-#: editor_actions.cc:1816 mixer_strip.cc:2068 monitor_section.cc:278
-#: monitor_section.cc:368 route_time_axis.cc:255 route_time_axis.cc:537
+#: editor_actions.cc:1823 mixer_strip.cc:2088 monitor_section.cc:243
+#: monitor_section.cc:313 route_time_axis.cc:256 route_time_axis.cc:538
 msgid "Mute"
 msgstr "Mute"
 
-#: editor_actions.cc:1819
+#: editor_actions.cc:1826
 msgid "Normalize..."
 msgstr "Normalisieren..."
 
-#: editor_actions.cc:1822
+#: editor_actions.cc:1829
 msgid "Reverse"
 msgstr "Umkehren"
 
-#: editor_actions.cc:1825
+#: editor_actions.cc:1832
 msgid "Make Mono Regions"
 msgstr "In Mono-Regionen umwandeln"
 
-#: editor_actions.cc:1828
+#: editor_actions.cc:1835
 msgid "Boost Gain"
 msgstr "Lautstärke erhöhen"
 
-#: editor_actions.cc:1831
+#: editor_actions.cc:1838
 msgid "Cut Gain"
 msgstr "Lautstärke reduzieren"
 
-#: editor_actions.cc:1834
+#: editor_actions.cc:1841
 msgid "Pitch Shift..."
 msgstr "Tonhöhe ändern..."
 
-#: editor_actions.cc:1837
-msgid "Transpose..."
-msgstr "Transponieren..."
-
-#: editor_actions.cc:1840
+#: editor_actions.cc:1847
 msgid "Opaque"
 msgstr "Deckend"
 
-#: editor_actions.cc:1844 editor_regions.cc:117
+#: editor_actions.cc:1851 editor_regions.cc:120
 msgid "Fade In"
 msgstr "Fade In"
 
-#: editor_actions.cc:1849 editor_regions.cc:118
+#: editor_actions.cc:1856 editor_regions.cc:121
 msgid "Fade Out"
 msgstr "Fade Out"
 
-#: editor_actions.cc:1864
+#: editor_actions.cc:1871
 msgid "Multi-Duplicate..."
 msgstr "Mehrfach duplizieren..."
 
-#: editor_actions.cc:1869
+#: editor_actions.cc:1876
 msgid "Fill Track"
 msgstr "Spur auffüllen"
 
-#: editor_actions.cc:1873 editor_markers.cc:993
+#: editor_actions.cc:1880 editor_markers.cc:1000
 msgid "Set Loop Range"
 msgstr "Schleife erstellen"
 
-#: editor_actions.cc:1880
+#: editor_actions.cc:1887
 msgid "Set Punch"
 msgstr "Punchbereich erstellen"
 
-#: editor_actions.cc:1884
+#: editor_actions.cc:1891
 msgid "Add Single Range Marker"
 msgstr "Einzelnen Bereichsmarker einfügen"
 
-#: editor_actions.cc:1889
+#: editor_actions.cc:1896
 msgid "Add Range Marker Per Region"
 msgstr "Einen Bereichsmarker pro Region einfügen"
 
-#: editor_actions.cc:1893
-msgid "Snap Position To Grid"
+#: editor_actions.cc:1900
+msgid "Snap Position to Grid"
 msgstr "Positionszeiger einrasten"
 
-#: editor_actions.cc:1896
+#: editor_actions.cc:1903
 msgid "Close Gaps"
 msgstr "Lücken schließen"
 
-#: editor_actions.cc:1899
+#: editor_actions.cc:1906
 msgid "Rhythm Ferret..."
 msgstr "Rhythm Ferret..."
 
-#: editor_actions.cc:1902
+#: editor_actions.cc:1909
 msgid "Export..."
 msgstr "Exportieren..."
 
-#: editor_actions.cc:1908
+#: editor_actions.cc:1915
 msgid "Separate Under"
 msgstr "Bereich unter aktueller Region entfernen"
 
-#: editor_actions.cc:1912 editor_actions.cc:1913
+#: editor_actions.cc:1919 editor_actions.cc:1920
 msgid "Set Fade In Length"
 msgstr "Fade-In bis Positionszeiger"
 
-#: editor_actions.cc:1914 editor_actions.cc:1915
+#: editor_actions.cc:1921 editor_actions.cc:1922
 msgid "Set Fade Out Length"
 msgstr "Fade-Out ab Positionszeiger"
 
-#: editor_actions.cc:1917
+#: editor_actions.cc:1924
 msgid "Set Tempo from Region = Bar"
 msgstr "Regionlänge = Taktlänge setzen"
 
-#: editor_actions.cc:1922
+#: editor_actions.cc:1929
 msgid "Split at Percussion Onsets"
 msgstr "Regionen an perkussiven Schlägen teilen"
 
-#: editor_actions.cc:1927
+#: editor_actions.cc:1934
 msgid "List Editor..."
 msgstr "Eventlisteneditor..."
 
-#: editor_actions.cc:1930
+#: editor_actions.cc:1937
 msgid "Properties..."
 msgstr "Eigenschaften..."
 
-#: editor_actions.cc:1934
+#: editor_actions.cc:1941
 msgid "Bounce (with processing)"
 msgstr "Bounce (mit Signalverarbeitung)"
 
-#: editor_actions.cc:1935
+#: editor_actions.cc:1942
 msgid "Bounce (without processing)"
 msgstr "Bounce (ohne Signalverarbeitung)"
 
-#: editor_actions.cc:1936
+#: editor_actions.cc:1943
 msgid "Combine"
 msgstr "Verbinden (combine)"
 
-#: editor_actions.cc:1937
+#: editor_actions.cc:1944
 msgid "Uncombine"
 msgstr "Trennen (uncombine)"
 
-#: editor_actions.cc:1939
+#: editor_actions.cc:1946
 msgid "Spectral Analysis..."
 msgstr "FFT-Analyse"
 
-#: editor_actions.cc:1941
+#: editor_actions.cc:1948
 msgid "Reset Envelope"
 msgstr "Lautstärkekurve zurücksetzen"
 
-#: editor_actions.cc:1943
+#: editor_actions.cc:1950
 msgid "Reset Gain"
 msgstr "Lautstärke zurücksetzen"
 
-#: editor_actions.cc:1948
+#: editor_actions.cc:1955
 msgid "Envelope Active"
 msgstr "Lautstärkekurve ist aktiv"
 
-#: editor_actions.cc:1956 editor_actions.cc:1957
+#: editor_actions.cc:1963 editor_actions.cc:1964
 msgid "Insert Patch Change..."
 msgstr "Patch Change einfügen..."
 
-#: editor_actions.cc:1958
+#: editor_actions.cc:1965
 msgid "Unlink from other copies"
 msgstr "Von anderen Kopien entkoppeln"
 
-#: editor_actions.cc:1959
+#: editor_actions.cc:1966
 msgid "Strip Silence..."
 msgstr "Stille entfernen..."
 
-#: editor_actions.cc:1960
+#: editor_actions.cc:1967
 msgid "Set Range Selection"
 msgstr "Bereich auswählen"
 
-#: editor_actions.cc:1962 editor_actions.cc:1963
+#: editor_actions.cc:1969 editor_actions.cc:1970
 msgid "Nudge Later"
 msgstr "Schritt nach hinten"
 
-#: editor_actions.cc:1964 editor_actions.cc:1965
+#: editor_actions.cc:1971 editor_actions.cc:1972
 msgid "Nudge Earlier"
 msgstr "Schritt nach vorne"
 
-#: editor_actions.cc:1967
+#: editor_actions.cc:1974
 msgid "Sequence Regions"
 msgstr "Regionen aneinanderreihen"
 
-#: editor_actions.cc:1972
+#: editor_actions.cc:1979
 msgid "Nudge Later by Capture Offset"
 msgstr "Schritt nach hinten um Aufnahme-Offset"
 
-#: editor_actions.cc:1979
+#: editor_actions.cc:1986
 msgid "Nudge Earlier by Capture Offset"
 msgstr "Schritt nach vorne um Aufnahme-Offset"
 
-#: editor_actions.cc:1983
+#: editor_actions.cc:1990
 msgid "Trim to Loop"
 msgstr "Auf Schleife kürzen"
 
-#: editor_actions.cc:1984
+#: editor_actions.cc:1991
 msgid "Trim to Punch"
 msgstr "Auf Punchbereich kürzen"
 
-#: editor_actions.cc:1986
+#: editor_actions.cc:1993
 msgid "Trim to Previous"
 msgstr "Zur vorherigen Region aufschließen"
 
-#: editor_actions.cc:1987
+#: editor_actions.cc:1994
 msgid "Trim to Next"
 msgstr "Zur nächsten Region aufschließen"
 
-#: editor_actions.cc:1994
-msgid "Insert Region From Region List"
-msgstr "Region von Regionenliste hinzufügen"
+#: editor_actions.cc:2001
+msgid "Insert Region from Region List"
+msgstr "Region aus Regionenliste einfügen"
 
-#: editor_actions.cc:2000
+#: editor_actions.cc:2007
 msgid "Set Sync Position"
 msgstr "Synchronisationspunkt setzen"
 
-#: editor_actions.cc:2001
+#: editor_actions.cc:2008
 msgid "Place Transient"
 msgstr "Transienten setzen"
 
-#: editor_actions.cc:2002
+#: editor_actions.cc:2009
 msgid "Split/Separate"
 msgstr "Teilen/Auftrennen"
 
-#: editor_actions.cc:2003
+#: editor_actions.cc:2010
 msgid "Trim Start at Edit Point"
 msgstr "Anfang der Region am Arbeitspunkt abschneiden"
 
-#: editor_actions.cc:2004
+#: editor_actions.cc:2011
 msgid "Trim End at Edit Point"
 msgstr "Ende der Region am Arbeitspunkt abschneiden"
 
-#: editor_actions.cc:2009
+#: editor_actions.cc:2016
 msgid "Align Start"
 msgstr "Anfang ausrichten"
 
-#: editor_actions.cc:2016
+#: editor_actions.cc:2023
 msgid "Align Start Relative"
 msgstr "Anfang relativ ausrichten"
 
-#: editor_actions.cc:2020
+#: editor_actions.cc:2027
 msgid "Align End"
 msgstr "Ende ausrichten"
 
-#: editor_actions.cc:2025
+#: editor_actions.cc:2032
 msgid "Align End Relative"
 msgstr "Ende relativ ausrichten"
 
-#: editor_actions.cc:2032
+#: editor_actions.cc:2039
 msgid "Align Sync"
 msgstr "Synchronisationspunkt ausrichten"
 
-#: editor_actions.cc:2039
+#: editor_actions.cc:2046
 msgid "Align Sync Relative"
 msgstr "Synchronisationspunkt relativ ausrichten"
 
-#: editor_actions.cc:2043 editor_actions.cc:2046
+#: editor_actions.cc:2050 editor_actions.cc:2053
 msgid "Choose Top..."
 msgstr "Oberste Region auswählen..."
 
@@ -4898,213 +5061,230 @@ msgstr ""
 "\n"
 "Fortfahren..."
 
-#: editor_canvas_events.cc:1311 editor_drag.cc:1402
+#: editor_canvas_events.cc:1308 editor_drag.cc:1418
 msgid "Could not create new track after region placed in the drop zone"
 msgstr ""
 "Konnte keine neue Spur erzeugen, nachdem die Region in der Drop Zone "
 "platziert wurde"
 
-#: editor_drag.cc:1294
+#: editor_drag.cc:1310
 msgid "fixed time region drag"
 msgstr "Region zeitgleich verschieben"
 
-#: editor_drag.cc:2228
+#: editor_drag.cc:2245
 msgid "Ripple drag"
 msgstr "Wellenmodus-Ziehen"
 
-#: editor_drag.cc:2389 midi_region_view.cc:2850
+#: editor_drag.cc:2307
+msgid "create region"
+msgstr "Region erzeugen"
+
+#: editor_drag.cc:2426 midi_region_view.cc:2834
 msgid "resize notes"
 msgstr "Notenlänge ändern"
 
-#: editor_drag.cc:2584
+#: editor_drag.cc:2609 editor_drag.cc:2644
+msgid ""
+"One or more Audio Regions\n"
+"are both Locked and\n"
+"Locked to Video.\n"
+"The video cannot me moved."
+msgstr ""
+"Eine oder mehrere Audioregionen\n"
+"sind sowohl gesperrt als auch\n"
+"an das Video gekoppelt.\n"
+"Das Video kann nicht bewegt werden."
+
+#: editor_drag.cc:2679
 msgid "Video Start:"
 msgstr "Videostart"
 
-#: editor_drag.cc:2586
+#: editor_drag.cc:2681
 msgid "Diff:"
 msgstr "Diff:"
 
-#: editor_drag.cc:2605
+#: editor_drag.cc:2703
 msgid "Move Video"
 msgstr "Bewege Video"
 
-#: editor_drag.cc:3113
+#: editor_drag.cc:3212
 msgid "copy meter mark"
 msgstr "Taktmarker kopieren"
 
-#: editor_drag.cc:3121
+#: editor_drag.cc:3220
 msgid "move meter mark"
 msgstr "Taktwechsel bewegen"
 
-#: editor_drag.cc:3244
-msgid "copy tempo mark"
-msgstr "Tempomarker kopieren"
-
-#: editor_drag.cc:3252
+#: editor_drag.cc:3308
 msgid "move tempo mark"
 msgstr "Tempowechsel bewegen"
 
-#: editor_drag.cc:3504
+#: editor_drag.cc:3345
+msgid "copy tempo mark"
+msgstr "Tempomarker kopieren"
+
+#: editor_drag.cc:3609
 msgid "change fade in length"
 msgstr "Ändere Fade-In Länge"
 
-#: editor_drag.cc:3629
+#: editor_drag.cc:3734
 msgid "change fade out length"
 msgstr "Fade-Out verändern"
 
-#: editor_drag.cc:3991
+#: editor_drag.cc:4110
 msgid "move marker"
 msgstr "Marker bewegen"
 
-#: editor_drag.cc:4239 editor_drag.cc:5622
+#: editor_drag.cc:4373 editor_drag.cc:5694
 msgid "automation range move"
 msgstr "Automationsbereich bewegen"
 
-#: editor_drag.cc:4596
+#: editor_drag.cc:4747
 msgid "An error occurred while executing time stretch operation"
 msgstr "Beim Ausführen der Timestretch-Operation trat ein Fehler auf"
 
-#: editor_drag.cc:5057
+#: editor_drag.cc:5208
 msgid "programming_error: %1"
 msgstr "Programmierfehler: %1"
 
-#: editor_drag.cc:5126 editor_drag.cc:5136
+#: editor_drag.cc:5277 editor_drag.cc:5287
 msgid "new skip marker"
 msgstr "neuer Sprungmarker"
 
-#: editor_drag.cc:5127
+#: editor_drag.cc:5278
 msgid "skip"
 msgstr "Sprung"
 
-#: editor_drag.cc:5131 location_ui.cc:56
+#: editor_drag.cc:5282 location_ui.cc:58
 msgid "CD"
 msgstr "CD"
 
-#: editor_drag.cc:5132
+#: editor_drag.cc:5283
 msgid "new CD marker"
 msgstr "neuer CD Marker"
 
-#: editor_drag.cc:5137 editor_route_groups.cc:437 mixer_ui.cc:1513
+#: editor_drag.cc:5288 editor_route_groups.cc:438 mixer_ui.cc:1594
 msgid "unnamed"
 msgstr "unbenannt"
 
-#: editor_drag.cc:5443
+#: editor_drag.cc:5601
 msgid "Automation range drag created for invalid region type"
 msgstr "Automationsbereichs-Ziehen für ungültigen Regionstyp erzeugt"
 
-#: editor_route_groups.cc:96
+#: editor_route_groups.cc:97
 msgid "Col"
 msgstr "Spalte"
 
-#: editor_route_groups.cc:96
+#: editor_route_groups.cc:97
 msgid "Group Tab Color"
 msgstr "Farbe des Gruppen-Reiters"
 
-#: editor_route_groups.cc:97
+#: editor_route_groups.cc:98
 msgid "Name of Group"
 msgstr "Gruppenname"
 
-#: editor_route_groups.cc:98 editor_routes.cc:208
+#: editor_route_groups.cc:99 editor_routes.cc:209
 msgid "Visible|V"
 msgstr "V"
 
-#: editor_route_groups.cc:98
+#: editor_route_groups.cc:99
 msgid "Group is visible?"
 msgstr "Gruppe sichtbar?"
 
-#: editor_route_groups.cc:99
+#: editor_route_groups.cc:100
 msgid "On"
 msgstr "An"
 
-#: editor_route_groups.cc:99
+#: editor_route_groups.cc:100
 msgid "Group is enabled?"
 msgstr "Ist die Gruppe aktiviert?"
 
-#: editor_route_groups.cc:100
+#: editor_route_groups.cc:101
 msgid "Group|G"
 msgstr "G"
 
-#: editor_route_groups.cc:100
+#: editor_route_groups.cc:101
 msgid "Sharing Gain?"
 msgstr "Lautstärke teilen?"
 
-#: editor_route_groups.cc:101
+#: editor_route_groups.cc:102
 msgid "Relative|Rel"
 msgstr "Rel"
 
-#: editor_route_groups.cc:101
+#: editor_route_groups.cc:102
 msgid "Relative Gain Changes?"
 msgstr "Relative Lautstärke-Änderungen"
 
-#: editor_route_groups.cc:102 editor_regions.cc:121 editor_routes.cc:212
-#: mixer_strip.cc:2094 meter_strip.cc:367 route_time_axis.cc:2741
-#: time_axis_view.cc:1201
+#: editor_route_groups.cc:103 editor_regions.cc:124 editor_routes.cc:213
+#: mixer_strip.cc:2117 meter_strip.cc:367 route_time_axis.cc:2750
+#: time_axis_view.cc:1199
 msgid "Mute|M"
 msgstr "M"
 
-#: editor_route_groups.cc:102
+#: editor_route_groups.cc:103
 msgid "Sharing Mute?"
 msgstr "Stummschaltung teilen?"
 
-#: editor_route_groups.cc:103 editor_routes.cc:213 mixer_strip.cc:2104
-#: meter_strip.cc:375 route_time_axis.cc:2738
+#: editor_route_groups.cc:104 editor_routes.cc:214 mixer_strip.cc:2130
+#: meter_strip.cc:375 route_time_axis.cc:2747
 msgid "Solo|S"
 msgstr "S"
 
-#: editor_route_groups.cc:103
+#: editor_route_groups.cc:104
 msgid "Sharing Solo?"
 msgstr "Solo teilen?"
 
-#: editor_route_groups.cc:104 midi_time_axis.cc:1623 midi_time_axis.cc:1626
-#: midi_time_axis.cc:1629
+#: editor_route_groups.cc:105 midi_time_axis.cc:1630 midi_time_axis.cc:1633
+#: midi_time_axis.cc:1636
 msgid "Rec"
 msgstr "Rec"
 
-#: editor_route_groups.cc:104
+#: editor_route_groups.cc:105
 msgid "Sharing Record-enable Status?"
 msgstr "Aufnahmebereitschaft teilen?"
 
-#: editor_route_groups.cc:105
+#: editor_route_groups.cc:106
 msgid "Monitoring|Mon"
 msgstr "Mon"
 
-#: editor_route_groups.cc:105
+#: editor_route_groups.cc:106
 msgid "Sharing Monitoring Choice?"
 msgstr "Monitoring-Wahl teilen?"
 
-#: editor_route_groups.cc:106
+#: editor_route_groups.cc:107
 msgid "Selection|Sel"
 msgstr "Sel"
 
-#: editor_route_groups.cc:106
+#: editor_route_groups.cc:107
 msgid "Sharing Selected/Editing Status?"
 msgstr "Auswahl-/Editierzustand teilen?"
 
-#: editor_route_groups.cc:107 editor_routes.cc:209
+#: editor_route_groups.cc:108 editor_routes.cc:210
 msgid "Active|A"
 msgstr "A"
 
-#: editor_route_groups.cc:107
+#: editor_route_groups.cc:108
 msgid "Sharing Active Status?"
 msgstr "Einschaltzustand teilen?"
 
-#: editor_export_audio.cc:92 editor_markers.cc:733 editor_markers.cc:820
-#: editor_markers.cc:1005 editor_markers.cc:1023 editor_markers.cc:1041
-#: editor_markers.cc:1060 editor_markers.cc:1079 editor_markers.cc:1109
-#: editor_markers.cc:1140 editor_markers.cc:1170 editor_markers.cc:1198
-#: editor_markers.cc:1229 editor_markers.cc:1254 editor_markers.cc:1305
-#: editor_markers.cc:1349 editor_markers.cc:1375 editor_markers.cc:1569
-#: editor_mouse.cc:2140
+#: editor_export_audio.cc:93 editor_markers.cc:733 editor_markers.cc:827
+#: editor_markers.cc:1012 editor_markers.cc:1030 editor_markers.cc:1048
+#: editor_markers.cc:1067 editor_markers.cc:1086 editor_markers.cc:1116
+#: editor_markers.cc:1147 editor_markers.cc:1177 editor_markers.cc:1205
+#: editor_markers.cc:1236 editor_markers.cc:1261 editor_markers.cc:1312
+#: editor_markers.cc:1356 editor_markers.cc:1382 editor_markers.cc:1576
+#: editor_mouse.cc:2248
 msgid "programming error: marker canvas item has no marker object pointer!"
 msgstr "Programmierfehler: marker canvas item has no marker object pointer!"
 
-#: editor_export_audio.cc:145 editor_export_audio.cc:150
-msgid "File Exists!"
-msgstr "Datei existiert!"
+#: editor_export_audio.cc:114
+msgid "Confirm MIDI File Overwrite"
+msgstr "Bestätige das Überschreiben der MIDI-Datei"
 
-#: editor_export_audio.cc:153
-msgid "Overwrite Existing File"
-msgstr "Vorhandenes Material überschreiben"
+#: editor_export_audio.cc:115 utils_videotl.cc:73
+msgid "A file with the same name already exists. Do you want to overwrite it?"
+msgstr ""
+"Eine Datei mit diesem Namen existiert bereits. Wollen Sie sie überschreiben?"
 
 #: editor_group_tabs.cc:176
 msgid "Fit to Window"
@@ -5122,20 +5302,20 @@ msgstr "Ende"
 msgid "mark"
 msgstr "Marker"
 
-#: editor_markers.cc:650 editor_ops.cc:2100 editor_ops.cc:2122
-#: editor_ops.cc:2238 editor_ops.cc:2275 location_ui.cc:1023
+#: editor_markers.cc:650 editor_ops.cc:2102 editor_ops.cc:2124
+#: editor_ops.cc:2240 editor_ops.cc:2277 location_ui.cc:1025
 msgid "add marker"
 msgstr "Marker hinzufügen"
 
-#: editor_markers.cc:682 editor_markers.cc:1449
+#: editor_markers.cc:682 editor_markers.cc:1456
 msgid "set loop range"
 msgstr "Loopbereich festlegen"
 
-#: editor_markers.cc:698 editor_markers.cc:1455
+#: editor_markers.cc:698 editor_markers.cc:1462
 msgid "set punch range"
 msgstr "Punchbereich festlegen"
 
-#: editor_markers.cc:715 editor_ops.cc:4169
+#: editor_markers.cc:715 editor_ops.cc:4092
 msgid "range"
 msgstr "Bereich"
 
@@ -5143,107 +5323,107 @@ msgstr "Bereich"
 msgid "new range marker"
 msgstr "Neuer Bereich"
 
-#: editor_markers.cc:751 editor_ops.cc:2206 location_ui.cc:859
+#: editor_markers.cc:751 editor_ops.cc:2208 location_ui.cc:861
 msgid "remove marker"
 msgstr "Marker entfernen"
 
-#: editor_markers.cc:887
+#: editor_markers.cc:894
 msgid "Locate to Here"
 msgstr "Hierhin setzen"
 
-#: editor_markers.cc:888
+#: editor_markers.cc:895
 msgid "Play from Here"
 msgstr "Wiedergabe ab hier"
 
-#: editor_markers.cc:889
+#: editor_markers.cc:896
 msgid "Move Mark to Playhead"
 msgstr "Marker zum Positionszeiger verschieben"
 
-#: editor_markers.cc:893
+#: editor_markers.cc:900
 msgid "Create Range to Next Marker"
 msgstr "Bereich bis zum nächsten Marker erstellen"
 
-#: editor_markers.cc:934
+#: editor_markers.cc:941
 msgid "Locate to Marker"
 msgstr "Positionszeiger zu Marker setzen"
 
-#: editor_markers.cc:935
+#: editor_markers.cc:942
 msgid "Play from Marker"
 msgstr "Wiedergabe ab Marker"
 
-#: editor_markers.cc:938
+#: editor_markers.cc:945
 msgid "Set Marker from Playhead"
 msgstr "Marker beim Positionszeiger erzeugen"
 
-#: editor_markers.cc:940
+#: editor_markers.cc:947
 msgid "Set Range from Selection"
 msgstr "Bereich aus Auswahl bilden"
 
-#: editor_markers.cc:950
+#: editor_markers.cc:957
 msgid "Hide Range"
 msgstr "Bereich verbergen"
 
-#: editor_markers.cc:951
+#: editor_markers.cc:958
 msgid "Rename Range..."
 msgstr "Bereich umbenennen..."
 
-#: editor_markers.cc:955
+#: editor_markers.cc:962
 msgid "Remove Range"
 msgstr "Bereich entfernen"
 
-#: editor_markers.cc:962
+#: editor_markers.cc:969
 msgid "Separate Regions in Range"
 msgstr "Regionen an Bereichsgrenzen teilen"
 
-#: editor_markers.cc:965
+#: editor_markers.cc:972
 msgid "Select Range"
 msgstr "Bereich auswählen"
 
-#: editor_markers.cc:994
+#: editor_markers.cc:1001
 msgid "Set Punch Range"
 msgstr "Punchbereich erstellen"
 
-#: editor_markers.cc:1400 editor_ops.cc:2055
+#: editor_markers.cc:1407 editor_ops.cc:2057
 msgid "New Name:"
 msgstr "Neuer Name: "
 
-#: editor_markers.cc:1403
+#: editor_markers.cc:1410
 msgid "Rename Mark"
 msgstr "Marker umbenennen"
 
-#: editor_markers.cc:1405
+#: editor_markers.cc:1412
 msgid "Rename Range"
 msgstr "Bereich umbenennen"
 
-#: editor_markers.cc:1412 editor_mouse.cc:2157 processor_box.cc:2060
-#: processor_box.cc:2531 route_time_axis.cc:1107 route_ui.cc:1574
+#: editor_markers.cc:1419 editor_mouse.cc:2265 processor_box.cc:2261
+#: processor_box.cc:2728 route_time_axis.cc:1112 route_ui.cc:1616
 msgid "Rename"
 msgstr "Umbenennen"
 
-#: editor_markers.cc:1425
+#: editor_markers.cc:1432
 msgid "rename marker"
 msgstr "Marker umbenennen"
 
-#: editor_mixer.cc:90
+#: editor_mixer.cc:91
 msgid "This screen is not tall enough to display the editor mixer"
 msgstr ""
 "Dieser Bildschirm ist nicht hoch genug, um den Editor-Mixer darzustellen"
 
-#: editor_mouse.cc:1235 editor_mouse.cc:1253 editor_tempodisplay.cc:270
+#: editor_mouse.cc:1343 editor_mouse.cc:1361 editor_tempodisplay.cc:270
 msgid ""
 "programming error: tempo marker canvas item has no marker object pointer!"
 msgstr ""
 "Programmierfehler: tempo marker canvas item has no marker object pointer!"
 
-#: editor_mouse.cc:1240 editor_tempodisplay.cc:275
+#: editor_mouse.cc:1348 editor_tempodisplay.cc:275
 msgid "programming error: marker for tempo is not a tempo marker!"
 msgstr "Programmierfehler: marker for tempo is not a tempo marker!"
 
-#: editor_mouse.cc:1258 editor_tempodisplay.cc:375
+#: editor_mouse.cc:1366 editor_tempodisplay.cc:375
 msgid "programming error: marker for meter is not a meter marker!"
 msgstr "Programmierfehler: marker for meter is not a meter marker!"
 
-#: editor_mouse.cc:1905 editor_mouse.cc:1930 editor_mouse.cc:1943
+#: editor_mouse.cc:2013 editor_mouse.cc:2038 editor_mouse.cc:2051
 msgid ""
 "programming error: control point canvas item has no control point object "
 "pointer!"
@@ -5251,179 +5431,179 @@ msgstr ""
 "Programmierfehler: control point canvas item has no control point object "
 "pointer!"
 
-#: editor_mouse.cc:2078
+#: editor_mouse.cc:2186
 msgid "start point trim"
 msgstr "Startpunkt ändern"
 
-#: editor_mouse.cc:2103
-msgid "End point trim"
-msgstr "Endpunkt verändern"
+#: editor_mouse.cc:2211
+msgid "end point trim"
+msgstr "Endpunkt ändern"
 
-#: editor_mouse.cc:2155
+#: editor_mouse.cc:2263
 msgid "Name for region:"
 msgstr "Name für Region:"
 
-#: editor_ops.cc:165
+#: editor_ops.cc:167
 msgid "split"
 msgstr "teile"
 
-#: editor_ops.cc:339
+#: editor_ops.cc:341
 msgid "alter selection"
 msgstr "Auswahl ändern"
 
-#: editor_ops.cc:381
+#: editor_ops.cc:383
 msgid "nudge regions forward"
 msgstr "Regionen Schritt vorwärts"
 
-#: editor_ops.cc:435 editor_ops.cc:526
+#: editor_ops.cc:437 editor_ops.cc:528
 msgid "nudge location forward"
 msgstr "Position Schritt vorwärts"
 
-#: editor_ops.cc:466
+#: editor_ops.cc:468
 msgid "nudge regions backward"
 msgstr "Regionen Schritt nach hinten"
 
-#: editor_ops.cc:558
+#: editor_ops.cc:560
 msgid "nudge forward"
 msgstr "Schritt vorwärts"
 
-#: editor_ops.cc:582
+#: editor_ops.cc:584
 msgid "nudge backward"
 msgstr "Schritt nach hinten"
 
-#: editor_ops.cc:647
+#: editor_ops.cc:649
 msgid "sequence regions"
 msgstr "Regionen aneinanderreihen"
 
-#: editor_ops.cc:709
+#: editor_ops.cc:711
 msgid "build_region_boundary_cache called with snap_type = %1"
 msgstr "build_region_boundary_cache wurde mit snap_type = %1 aufgerufen"
 
-#: editor_ops.cc:2057
+#: editor_ops.cc:2059
 msgid "New Location Marker"
 msgstr "Neuer Positionsmarker"
 
-#: editor_ops.cc:2148 editor_ops.cc:2172
+#: editor_ops.cc:2150 editor_ops.cc:2174
 msgid "Set session start"
 msgstr "Projektstart setzen"
 
-#: editor_ops.cc:2238
+#: editor_ops.cc:2240
 msgid "add markers"
 msgstr "Marker hinzufügen"
 
-#: editor_ops.cc:2334
+#: editor_ops.cc:2336
 msgid "clear markers"
 msgstr "Marker zurücksetzen"
 
-#: editor_ops.cc:2349
+#: editor_ops.cc:2351
 msgid "clear ranges"
 msgstr "Bereiche zurücksetzen"
 
-#: editor_ops.cc:2365
+#: editor_ops.cc:2367
 msgid "clear locations"
 msgstr "Positionen zurücksetzen"
 
-#: editor_ops.cc:2428
+#: editor_ops.cc:2430
 msgid "insert region"
 msgstr "Region einfügen"
 
-#: editor_ops.cc:2619
+#: editor_ops.cc:2621
 msgid "raise regions"
 msgstr "Regionen weiter nach oben"
 
-#: editor_ops.cc:2621
+#: editor_ops.cc:2623
 msgid "raise region"
 msgstr "Region weiter nach oben"
 
-#: editor_ops.cc:2627
+#: editor_ops.cc:2629
 msgid "raise regions to top"
 msgstr "Regionen ganz nach oben"
 
-#: editor_ops.cc:2629
+#: editor_ops.cc:2631
 msgid "raise region to top"
 msgstr "Region ganz nach oben"
 
-#: editor_ops.cc:2635
+#: editor_ops.cc:2637
 msgid "lower regions"
 msgstr "Regionen weiter nach unten"
 
-#: editor_ops.cc:2637 editor_ops.cc:2645
+#: editor_ops.cc:2639 editor_ops.cc:2647
 msgid "lower region"
 msgstr "Region weiter nach unten"
 
-#: editor_ops.cc:2643
+#: editor_ops.cc:2645
 msgid "lower regions to bottom"
 msgstr "Regionen ganz nach unten"
 
-#: editor_ops.cc:2728
+#: editor_ops.cc:2730
 msgid "Rename Region"
 msgstr "Region umbenennen"
 
-#: editor_ops.cc:2730 processor_box.cc:2058 route_ui.cc:1572
+#: editor_ops.cc:2732 processor_box.cc:2259 route_ui.cc:1614
 msgid "New name:"
 msgstr "Neuer Name: "
 
-#: editor_ops.cc:3047
+#: editor_ops.cc:3030
 msgid "separate"
 msgstr "Teilen"
 
-#: editor_ops.cc:3159
+#: editor_ops.cc:3142
 msgid "separate region under"
 msgstr "Bereich unter aktueller Region entfernen"
 
-#: editor_ops.cc:3305
+#: editor_ops.cc:3294
 msgid "trim to selection"
 msgstr "Auf Auswahl kürzen"
 
-#: editor_ops.cc:3454
+#: editor_ops.cc:3376
 msgid "set sync point"
 msgstr "Einrastpunkt definieren"
 
-#: editor_ops.cc:3478
+#: editor_ops.cc:3400
 msgid "remove region sync"
 msgstr "Synchronisationspunkt löschen"
 
-#: editor_ops.cc:3500
+#: editor_ops.cc:3422
 msgid "move regions to original position"
 msgstr "Regionen zu ihrer Ursprungsposition verschieben"
 
-#: editor_ops.cc:3502
+#: editor_ops.cc:3424
 msgid "move region to original position"
 msgstr "Region zu ihrer Ursprungsposition verschieben"
 
-#: editor_ops.cc:3523
+#: editor_ops.cc:3445
 msgid "align selection"
 msgstr "Auswahl ausrichten"
 
-#: editor_ops.cc:3597
+#: editor_ops.cc:3519
 msgid "align selection (relative)"
 msgstr "Auswahl relativ ausrichten"
 
-#: editor_ops.cc:3631
+#: editor_ops.cc:3553
 msgid "align region"
 msgstr "Region ausrichten"
 
-#: editor_ops.cc:3682
+#: editor_ops.cc:3604
 msgid "trim front"
 msgstr "vorne abschneiden"
 
-#: editor_ops.cc:3682
+#: editor_ops.cc:3604
 msgid "trim back"
 msgstr "hinten Abschneiden"
 
-#: editor_ops.cc:3712
+#: editor_ops.cc:3634
 msgid "trim to loop"
 msgstr "Auf Schleife kürzen"
 
-#: editor_ops.cc:3722
+#: editor_ops.cc:3644
 msgid "trim to punch"
 msgstr "Auf Punchbereich kürzen"
 
-#: editor_ops.cc:3844
+#: editor_ops.cc:3766
 msgid "trim to region"
 msgstr "Auf Region kürzen"
 
-#: editor_ops.cc:3903
+#: editor_ops.cc:3825
 msgid ""
 "This track/bus cannot be frozen because the signal adds or loses channels "
 "before reaching the outputs.\n"
@@ -5435,11 +5615,11 @@ msgstr ""
 "Typischerweise wird dies durch ein Plugin verursacht, das Stereo aus einer "
 "Monoquelle oder umgekehrt erzeugt."
 
-#: editor_ops.cc:3906
+#: editor_ops.cc:3828
 msgid "Cannot freeze"
 msgstr "Einfrieren nicht möglich"
 
-#: editor_ops.cc:3912
+#: editor_ops.cc:3834
 msgid ""
 "<b>%1</b>\n"
 "\n"
@@ -5453,23 +5633,23 @@ msgstr ""
 "\n"
 "Einfrieren wird das Signal nur bis zum ersten Send/Insert/Return verarbeiten."
 
-#: editor_ops.cc:3916
+#: editor_ops.cc:3838
 msgid "Freeze anyway"
 msgstr "Trotzdem einfrieren"
 
-#: editor_ops.cc:3917
+#: editor_ops.cc:3839
 msgid "Don't freeze"
 msgstr "Nicht einfrieren"
 
-#: editor_ops.cc:3918
+#: editor_ops.cc:3840
 msgid "Freeze Limits"
 msgstr "Einfrier-Grenzen"
 
-#: editor_ops.cc:3933
+#: editor_ops.cc:3855
 msgid "Cancel Freeze"
 msgstr "Einfrieren abbrechen"
 
-#: editor_ops.cc:3963
+#: editor_ops.cc:3885
 msgid ""
 "You can't perform this operation because the processing of the signal will "
 "cause one or more of the tracks to end up with a region with more channels "
@@ -5484,47 +5664,47 @@ msgstr ""
 "Sie können dies ohne Signalverarbeitung tun, das ist aber eine andere "
 "Operation."
 
-#: editor_ops.cc:3967
+#: editor_ops.cc:3889
 msgid "Cannot bounce"
 msgstr "Kann nicht bouncen"
 
-#: editor_ops.cc:4018
+#: editor_ops.cc:3940
 msgid "bounce range"
 msgstr "Bereich bouncen"
 
-#: editor_ops.cc:4085
+#: editor_ops.cc:4007
 msgid "delete"
 msgstr "Löschen"
 
-#: editor_ops.cc:4088
+#: editor_ops.cc:4010
 msgid "cut"
 msgstr "Ausschneiden"
 
-#: editor_ops.cc:4091
+#: editor_ops.cc:4013
 msgid "copy"
 msgstr "Kopieren"
 
-#: editor_ops.cc:4094
+#: editor_ops.cc:4016
 msgid "clear"
 msgstr "Leeren"
 
-#: editor_ops.cc:4142
+#: editor_ops.cc:4065
 msgid "objects"
 msgstr "Objekte"
 
-#: editor_ops.cc:4352 editor_ops.cc:4437
+#: editor_ops.cc:4275 editor_ops.cc:4360
 msgid "remove region"
 msgstr "Region(en) löschen"
 
-#: editor_ops.cc:4862
+#: editor_ops.cc:4787
 msgid "duplicate selection"
 msgstr "Auswahl duplizieren"
 
-#: editor_ops.cc:4948
+#: editor_ops.cc:4873
 msgid "nudge track"
 msgstr "Spur verschieben"
 
-#: editor_ops.cc:4975
+#: editor_ops.cc:4900
 msgid ""
 "Do you really want to destroy the last capture?\n"
 "(This is destructive and cannot be undone)"
@@ -5532,141 +5712,157 @@ msgstr ""
 "Wollen Sie wirklich die letzte Aufnahme rückgängig machen?\n"
 "(Dies ist destruktiv und kann nicht rückgängig gemacht werden!)"
 
-#: editor_ops.cc:4978 editor_ops.cc:7078 editor_regions.cc:462
-#: editor_snapshots.cc:159
+#: editor_ops.cc:4903 editor_ops.cc:7127 editor_regions.cc:465
+#: editor_snapshots.cc:171
 msgid "No, do nothing."
 msgstr "Nein, nichts machen."
 
-#: editor_ops.cc:4979
+#: editor_ops.cc:4904
 msgid "Yes, destroy it."
 msgstr "Ja, entfernen."
 
-#: editor_ops.cc:4981
+#: editor_ops.cc:4906
 msgid "Destroy last capture"
 msgstr "Lösche letzte Aufnahme"
 
-#: editor_ops.cc:5057
+#: editor_ops.cc:4982
 msgid "normalize"
 msgstr "Normalisieren"
 
-#: editor_ops.cc:5155
+#: editor_ops.cc:5080
 msgid "reverse regions"
 msgstr "Regionen umkehren"
 
-#: editor_ops.cc:5189
+#: editor_ops.cc:5116
 msgid "strip silence"
 msgstr "Stille entfernen"
 
-#: editor_ops.cc:5270
+#: editor_ops.cc:5197
 msgid "Fork Region(s)"
 msgstr "Region(en) abzweigen"
 
-#: editor_ops.cc:5277
+#: editor_ops.cc:5204
 msgid "Could not unlink %1"
 msgstr "Konnte die Bindung von %1 nicht lösen"
 
-#: editor_ops.cc:5517
+#: editor_ops.cc:5465
 msgid "reset region gain"
 msgstr "Lautstärkekurve zurücksetzen"
 
-#: editor_ops.cc:5575
+#: editor_ops.cc:5523
 msgid "region gain envelope active"
 msgstr "Lautstärkekurve aktiv"
 
-#: editor_ops.cc:5600
+#: editor_ops.cc:5548
 msgid "toggle region lock"
 msgstr "Regionensperre umschalten"
 
-#: editor_ops.cc:5624
+#: editor_ops.cc:5572
 msgid "Toggle Video Lock"
 msgstr "Videosperre umschalten"
 
-#: editor_ops.cc:5648
+#: editor_ops.cc:5596
 msgid "region lock style"
 msgstr "Art der Regionensperre"
 
-#: editor_ops.cc:5673
+#: editor_ops.cc:5621
 msgid "change region opacity"
 msgstr "Regionen-Deckkraft ändern"
 
-#: editor_ops.cc:5766
+#: editor_ops.cc:5714
 msgid "fade range"
 msgstr "Bereich faden"
 
-#: editor_ops.cc:5804
+#: editor_ops.cc:5752
 msgid "set fade in length"
 msgstr "Ändere Fade-In Länge"
 
-#: editor_ops.cc:5811
+#: editor_ops.cc:5759
 msgid "set fade out length"
 msgstr "Ändere Fade-Out Länge"
 
-#: editor_ops.cc:5876
+#: editor_ops.cc:5824
 msgid "set fade in shape"
 msgstr "Fade-In Kurve bearbeiten"
 
-#: editor_ops.cc:5911
+#: editor_ops.cc:5859
 msgid "set fade out shape"
 msgstr "Fade-Out Kurve ändern"
 
-#: editor_ops.cc:5947
+#: editor_ops.cc:5895
 msgid "set fade in active"
 msgstr "Fade-In aktivieren"
 
-#: editor_ops.cc:5981
+#: editor_ops.cc:5929
 msgid "set fade out active"
 msgstr "Fade-Out aktivieren"
 
-#: editor_ops.cc:6041
+#: editor_ops.cc:5989
 msgid "toggle fade active"
 msgstr "Fade umschalten"
 
-#: editor_ops.cc:6227
+#: editor_ops.cc:6179
 msgid "set loop range from selection"
 msgstr "Schleife aus Auswahl erstellen"
 
-#: editor_ops.cc:6241
+#: editor_ops.cc:6193
 msgid "set loop range from region"
 msgstr "Schleife aus Region erstellen"
 
-#: editor_ops.cc:6260
+#: editor_ops.cc:6212
 msgid "set punch range from selection"
 msgstr "Punchbereich aus Auswahl erstellen"
 
-#: editor_ops.cc:6284
+#: editor_ops.cc:6236
 msgid "set session start/end from selection"
 msgstr "Projektstart/ende auf Auswahl setzen"
 
-#: editor_ops.cc:6299
+#: editor_ops.cc:6272
+msgid "set punch start from EP"
+msgstr "Punchbeginn von Arbeitspunkt"
+
+#: editor_ops.cc:6300
+msgid "set punch end from EP"
+msgstr "Punchende von Arbeitspunkt"
+
+#: editor_ops.cc:6333
+msgid "set loop start from EP"
+msgstr "Schleifenbeginn von Arbeitspunkt"
+
+#: editor_ops.cc:6361
+msgid "set loop end from EP"
+msgstr "Schleifenende von Arbeitspunkt"
+
+#: editor_ops.cc:6372
 msgid "set punch range from region"
 msgstr "Punchbereich aus Region erstellen"
 
-#: editor_ops.cc:6408
+#: editor_ops.cc:6457
 msgid "Add new marker"
 msgstr "Marker hinzufügen"
 
-#: editor_ops.cc:6409
+#: editor_ops.cc:6458
 msgid "Set global tempo"
 msgstr "Globales tempo setzen"
 
-#: editor_ops.cc:6412
+#: editor_ops.cc:6461
 msgid "Define one bar"
 msgstr "Einen Takt definieren"
 
-#: editor_ops.cc:6413
+#: editor_ops.cc:6462
 msgid "Do you want to set the global tempo or add a new tempo marker?"
 msgstr ""
 "Möchten Sie das globale Tempo ändern oder einen neuen Tempo-Marker setzen?"
 
-#: editor_ops.cc:6439
+#: editor_ops.cc:6488
 msgid "set tempo from region"
 msgstr "Tempo anhand von Region setzen"
 
-#: editor_ops.cc:6469
+#: editor_ops.cc:6518
 msgid "split regions"
 msgstr "Region teilen (Split)"
 
-#: editor_ops.cc:6511
+#: editor_ops.cc:6560
 msgid ""
 "You are about to split\n"
 "%1\n"
@@ -5676,11 +5872,11 @@ msgstr ""
 "Sie versuchen %1 in %2 Teile zu teilen.\n"
 "Das könnte sehr lange dauern."
 
-#: editor_ops.cc:6518
+#: editor_ops.cc:6567
 msgid "Call for the Ferret!"
 msgstr "Call for the Ferret!"
 
-#: editor_ops.cc:6519
+#: editor_ops.cc:6568
 msgid ""
 "Press OK to continue with this split operation\n"
 "or ask the Ferret dialog to tune the analysis"
@@ -5688,52 +5884,52 @@ msgstr ""
 "Drücken Sie OK um mit der aufteiloperation (Split) fortzufahren\n"
 "oder versuchen sie im Ferret-Fenster die Analyse zu verbessern."
 
-#: editor_ops.cc:6521
+#: editor_ops.cc:6570
 msgid "Press OK to continue with this split operation"
 msgstr "Drücken Sie OK um mit der aufteiloperation (Split) fortzufahren"
 
-#: editor_ops.cc:6524
+#: editor_ops.cc:6573
 msgid "Excessive split?"
 msgstr "Übermäßige Aufteilung?"
 
-#: editor_ops.cc:6676
+#: editor_ops.cc:6725
 msgid "place transient"
 msgstr "Transienten platzieren"
 
-#: editor_ops.cc:6711
+#: editor_ops.cc:6760
 msgid "snap regions to grid"
 msgstr "Regionen an Raster einrasten"
 
-#: editor_ops.cc:6750
+#: editor_ops.cc:6799
 msgid "Close Region Gaps"
 msgstr "Regionenlücken schließen"
 
-#: editor_ops.cc:6755
+#: editor_ops.cc:6804
 msgid "Crossfade length"
 msgstr "Länge des Crossfades"
 
-#: editor_ops.cc:6764 editor_ops.cc:6775 rhythm_ferret.cc:119
+#: editor_ops.cc:6813 editor_ops.cc:6824 rhythm_ferret.cc:119
 #: session_option_editor.cc:141
 msgid "ms"
 msgstr "ms"
 
-#: editor_ops.cc:6766
+#: editor_ops.cc:6815
 msgid "Pull-back length"
 msgstr "Öffnungslänge vorne"
 
-#: editor_ops.cc:6779
+#: editor_ops.cc:6828
 msgid "Ok"
 msgstr "Ok"
 
-#: editor_ops.cc:6794
+#: editor_ops.cc:6843
 msgid "close region gaps"
 msgstr "Schließe Lücken zwischen Regionen"
 
-#: editor_ops.cc:7036
+#: editor_ops.cc:7085
 msgid "That would be bad news ...."
 msgstr "Lieber nicht!"
 
-#: editor_ops.cc:7041
+#: editor_ops.cc:7090
 msgid ""
 "Removing the master or monitor bus is such a bad idea\n"
 "that %1 is not going to allow it.\n"
@@ -5749,19 +5945,19 @@ msgstr ""
 "bearbeitet werden. \"allow-special-bus-removal\" muss\n"
 "dazu auf \"yes\" gesetzt werden."
 
-#: editor_ops.cc:7057 route_ui.cc:1938
+#: editor_ops.cc:7106 route_ui.cc:2009
 msgid "track"
 msgid_plural "tracks"
 msgstr[0] "Spur"
 msgstr[1] "Spuren"
 
-#: editor_ops.cc:7058 route_ui.cc:1938
+#: editor_ops.cc:7107 route_ui.cc:2009
 msgid "bus"
 msgid_plural "busses"
 msgstr[0] "Bus"
 msgstr[1] "Busse"
 
-#: editor_ops.cc:7062
+#: editor_ops.cc:7111
 msgid ""
 "Do you really want to remove %1 %2 and %3 %4?\n"
 "(You may also lose the playlists associated with the %2)\n"
@@ -5774,7 +5970,7 @@ msgstr ""
 "Dies kann nicht rückgängig gemacht werden, und die Projektdatei wird "
 "überschrieben werden!"
 
-#: editor_ops.cc:7067
+#: editor_ops.cc:7116
 msgid ""
 "Do you really want to remove %1 %2?\n"
 "(You may also lose the playlists associated with the %2)\n"
@@ -5787,7 +5983,7 @@ msgstr ""
 "Dies kann nicht rückgängig gemacht werden, und die Projektdatei wird "
 "überschrieben werden!"
 
-#: editor_ops.cc:7073
+#: editor_ops.cc:7122
 msgid ""
 "Do you really want to remove %1 %2?\n"
 "\n"
@@ -5798,145 +5994,145 @@ msgstr ""
 "Diese Aktion kann nicht rückgängig gemacht werden, und die Projektdatei wird "
 "überschrieben werden"
 
-#: editor_ops.cc:7080
+#: editor_ops.cc:7129
 msgid "Yes, remove them."
 msgstr "Ja, entfernen."
 
-#: editor_ops.cc:7082 editor_snapshots.cc:160
+#: editor_ops.cc:7131 editor_snapshots.cc:172
 msgid "Yes, remove it."
 msgstr "Ja, entfernen."
 
-#: editor_ops.cc:7087 editor_ops.cc:7089
+#: editor_ops.cc:7136 editor_ops.cc:7138
 msgid "Remove %1"
 msgstr "Entferne %1"
 
-#: editor_ops.cc:7191 editor_ops.cc:7205 editor_ops.cc:7245 editor_ops.cc:7255
+#: editor_ops.cc:7240 editor_ops.cc:7254 editor_ops.cc:7294 editor_ops.cc:7304
 msgid "insert time"
 msgstr "Stille einfügen"
 
-#: editor_ops.cc:7308
+#: editor_ops.cc:7357
 msgid "Cannot insert or delete time when in Lock edit."
 msgstr "Kann im Sperr-Bearbeitungsmodus keine Zeit einfügen oder löschen"
 
-#: editor_ops.cc:7328 editor_ops.cc:7340 editor_ops.cc:7413
+#: editor_ops.cc:7377 editor_ops.cc:7389 editor_ops.cc:7462
 msgid "cut time"
 msgstr "Zeit ausschneiden"
 
-#: editor_ops.cc:7426
+#: editor_ops.cc:7475
 msgid "remove time"
 msgstr "Zeit entfernen"
 
-#: editor_ops.cc:7500
+#: editor_ops.cc:7549
 msgid "There are too many tracks to fit in the current window"
 msgstr "Es gibt zu viele Spuren, sie in das aktuelle Fenster zu einzupassen"
 
-#: editor_ops.cc:7561
+#: editor_ops.cc:7610
 msgid "Sel"
 msgstr "Sel"
 
-#: editor_ops.cc:7600
+#: editor_ops.cc:7649
 #, c-format
 msgid "Saved view %u"
 msgstr "Ansicht %u gespeichert"
 
-#: editor_ops.cc:7625
+#: editor_ops.cc:7674
 msgid "mute regions"
 msgstr "Regionen stummschalten"
 
-#: editor_ops.cc:7627
+#: editor_ops.cc:7676
 msgid "mute region"
 msgstr "Region stummschalten"
 
-#: editor_ops.cc:7664
+#: editor_ops.cc:7713
 msgid "combine regions"
 msgstr "Regionen verbinden (combine)"
 
-#: editor_ops.cc:7702
+#: editor_ops.cc:7751
 msgid "uncombine regions"
 msgstr "Regionen trennen (uncombine)"
 
-#: editor_ops.cc:7739
+#: editor_ops.cc:7788
 msgid "%1: Locked"
 msgstr "%1: Gesperrt"
 
-#: editor_ops.cc:7746
+#: editor_ops.cc:7795
 msgid "Click to unlock"
 msgstr "Klicken, um Sperre aufzuheben"
 
-#: editor_ops.cc:7793
+#: editor_ops.cc:7844
 msgid "Moving embedded files into session folder"
 msgstr "Verschiebe eingebettete Dateien in den Projektordner"
 
-#: editor_regions.cc:112
+#: editor_regions.cc:115
 msgid "Region name, with number of channels in []'s"
 msgstr "Name der Region, mit Kanalzahl in []"
 
-#: editor_regions.cc:113
+#: editor_regions.cc:116
 msgid "Position of start of region"
 msgstr "Position des Regionen-Anfangs"
 
-#: editor_regions.cc:114 editor_regions.cc:859 time_info_box.cc:101
+#: editor_regions.cc:117 editor_regions.cc:862 time_info_box.cc:101
 msgid "End"
 msgstr "Ende"
 
-#: editor_regions.cc:114
+#: editor_regions.cc:117
 msgid "Position of end of region"
 msgstr "Position des Regionen-Endes"
 
-#: editor_regions.cc:115
+#: editor_regions.cc:118
 msgid "Length of the region"
 msgstr "Länge der Region"
 
-#: editor_regions.cc:116
+#: editor_regions.cc:119
 msgid "Position of region sync point, relative to start of the region"
 msgstr ""
 "Position des Regionen-Synchronisationspunktes, relativ zu Regionenanfang"
 
-#: editor_regions.cc:117
+#: editor_regions.cc:120
 msgid "Length of region fade-in (units: secondary clock), () if disabled"
 msgstr "Länge des Einblendens (Einheiten: sekundäre Uhr), () falls inaktiv"
 
-#: editor_regions.cc:118
+#: editor_regions.cc:121
 msgid "Length of region fade-out (units: secondary clock), () if disabled"
 msgstr "Länge des Ausblendens (Einheiten: sekundäre Uhr), () falls inaktiv"
 
-#: editor_regions.cc:119
+#: editor_regions.cc:122
 msgid "Lock|L"
 msgstr "L"
 
-#: editor_regions.cc:119
+#: editor_regions.cc:122
 msgid "Region position locked?"
 msgstr "Position der Region gesperrt?"
 
-#: editor_regions.cc:120
+#: editor_regions.cc:123
 msgid "Gain|G"
 msgstr "G"
 
-#: editor_regions.cc:120
+#: editor_regions.cc:123
 msgid "Region position glued to Bars|Beats time?"
 msgstr "Regionenposition an Takt und Schäge gebunden?"
 
-#: editor_regions.cc:121
+#: editor_regions.cc:124
 msgid "Region muted?"
 msgstr "Region stummgeschaltet?"
 
-#: editor_regions.cc:122
+#: editor_regions.cc:125
 msgid "Opaque|O"
 msgstr "O"
 
-#: editor_regions.cc:122
+#: editor_regions.cc:125
 msgid "Region opaque (blocks regions below it from being heard)?"
 msgstr "Region deckend (hindert darunterliegende Regionen, gehört zu werden)?"
 
-#: editor_regions.cc:311 editor_regions.cc:316 editor_regions.cc:318
+#: editor_regions.cc:314 editor_regions.cc:319 editor_regions.cc:321
 msgid "Hidden"
 msgstr "Versteckt"
 
-#: editor_regions.cc:391
+#: editor_regions.cc:394
 msgid "(MISSING) "
 msgstr "(FEHLT)"
 
-#: editor_regions.cc:459
+#: editor_regions.cc:462
 msgid ""
 "Do you really want to remove unused regions?\n"
 "(This is destructive and cannot be undone)"
@@ -5944,143 +6140,143 @@ msgstr ""
 "Wollen Sie ungenutzte Regionen wirklich entfernen?\n"
 "(Dies ist destruktiv und kann nicht rückgängig gemacht werden)"
 
-#: editor_regions.cc:463
+#: editor_regions.cc:466
 msgid "Yes, remove."
 msgstr "Ja, entfernen."
 
-#: editor_regions.cc:465
+#: editor_regions.cc:468
 msgid "Remove unused regions"
 msgstr "Ungenutzte Regionen entfernen"
 
-#: editor_regions.cc:694
+#: editor_regions.cc:697
 msgid "EditorRegions::format_position: negative timecode position: %1"
 msgstr "EditorRegions::format_position: Negative Timecode Position: %1"
 
-#: editor_regions.cc:824 editor_regions.cc:840 editor_regions.cc:854
+#: editor_regions.cc:827 editor_regions.cc:843 editor_regions.cc:857
 msgid "Mult."
 msgstr "Viele"
 
-#: editor_regions.cc:857 midi_list_editor.cc:104 time_info_box.cc:94
+#: editor_regions.cc:860 midi_list_editor.cc:104 time_info_box.cc:94
 msgid "Start"
 msgstr "Start"
 
-#: editor_regions.cc:875 editor_regions.cc:891
+#: editor_regions.cc:878 editor_regions.cc:894
 msgid "Multiple"
 msgstr "Viele"
 
-#: editor_regions.cc:960
+#: editor_regions.cc:963
 msgid "MISSING "
 msgstr "FEHLT"
 
-#: editor_routes.cc:183
+#: editor_routes.cc:184
 msgid "SS"
 msgstr "SS"
 
-#: editor_routes.cc:207
+#: editor_routes.cc:208
 msgid "Track/Bus Name"
 msgstr "Spur/Busname"
 
-#: editor_routes.cc:208
+#: editor_routes.cc:209
 msgid "Track/Bus visible ?"
 msgstr "Spuren/Busse sichtbar?"
 
-#: editor_routes.cc:209
+#: editor_routes.cc:210
 msgid "Track/Bus active ?"
 msgstr "Spur/Bus aktiv?"
 
-#: editor_routes.cc:210
+#: editor_routes.cc:211
 msgid "MidiInput|I"
 msgstr "I"
 
-#: editor_routes.cc:210
+#: editor_routes.cc:211
 msgid "MIDI input enabled"
 msgstr "MIDI Eingänge aktiv"
 
-#: editor_routes.cc:211
+#: editor_routes.cc:212
 msgid "Rec|R"
 msgstr "R"
 
-#: editor_routes.cc:211
+#: editor_routes.cc:212
 msgid "Record enabled"
 msgstr "Aufnahme bereit"
 
-#: editor_routes.cc:212
+#: editor_routes.cc:213
 msgid "Muted"
 msgstr "Stumm"
 
-#: editor_routes.cc:213
+#: editor_routes.cc:214
 msgid "Soloed"
 msgstr "Solo ein"
 
-#: editor_routes.cc:214
+#: editor_routes.cc:215
 msgid "SoloIso|SI"
 msgstr "SI"
 
-#: editor_routes.cc:214
+#: editor_routes.cc:215
 msgid "Solo Isolated"
 msgstr "Isoliertes Solo"
 
-#: editor_routes.cc:215
+#: editor_routes.cc:216
 msgid "SoloLock|SS"
 msgstr "SS"
 
-#: editor_routes.cc:215
+#: editor_routes.cc:216
 msgid "Solo Safe (Locked)"
 msgstr "Solo Safe (gesperrt)"
 
-#: editor_routes.cc:485 mixer_ui.cc:1213
+#: editor_routes.cc:486 mixer_ui.cc:1260
 msgid "Hide All"
 msgstr "Alle verbergen"
 
-#: editor_routes.cc:486 mixer_ui.cc:1214
+#: editor_routes.cc:487 mixer_ui.cc:1261
 msgid "Show All Audio Tracks"
 msgstr "Zeige alle Audiospuren"
 
-#: editor_routes.cc:487 mixer_ui.cc:1215
+#: editor_routes.cc:488 mixer_ui.cc:1262
 msgid "Hide All Audio Tracks"
 msgstr "Verberge alle Audiospuren"
 
-#: editor_routes.cc:488 mixer_ui.cc:1216
+#: editor_routes.cc:489 mixer_ui.cc:1263
 msgid "Show All Audio Busses"
 msgstr "Zeige alle Audiobusse"
 
-#: editor_routes.cc:489 mixer_ui.cc:1217
+#: editor_routes.cc:490 mixer_ui.cc:1264
 msgid "Hide All Audio Busses"
 msgstr "Verberge alle Audiobusse"
 
-#: editor_routes.cc:490 mixer_ui.cc:1218
+#: editor_routes.cc:491 mixer_ui.cc:1265
 msgid "Show All Midi Tracks"
 msgstr "Zeige alle MIDI-Spuren"
 
-#: editor_routes.cc:491 mixer_ui.cc:1219
+#: editor_routes.cc:492 mixer_ui.cc:1266
 msgid "Hide All Midi Tracks"
 msgstr "Verberge alle MIDI-Spuren"
 
-#: editor_routes.cc:492
-msgid "Show Tracks With Regions Under Playhead"
-msgstr "Zeige Spuren mit Regionen unter dem Positionszeiger"
+#: editor_routes.cc:493
+msgid "Only Show Tracks with Regions Under Playhead"
+msgstr "Nur Spuren mit Regionen unter dem Positionszeiger anzeigen"
 
-#: editor_rulers.cc:211
+#: editor_rulers.cc:212
 msgid "New location marker"
 msgstr "Neuer Positionsmarker"
 
-#: editor_rulers.cc:212
+#: editor_rulers.cc:213
 msgid "Clear all locations"
 msgstr "Alle Positionsmarker entfernen"
 
-#: editor_rulers.cc:213
+#: editor_rulers.cc:214
 msgid "Unhide locations"
 msgstr "Positionen anzeigen"
 
-#: editor_rulers.cc:217
+#: editor_rulers.cc:218
 msgid "New range"
 msgstr "Neuer Bereich"
 
-#: editor_rulers.cc:218
+#: editor_rulers.cc:219
 msgid "Clear all ranges"
 msgstr "Alle Bereiche entfernen"
 
-#: editor_rulers.cc:219
+#: editor_rulers.cc:220
 msgid "Unhide ranges"
 msgstr "Bereiche anzeigen"
 
@@ -6096,23 +6292,23 @@ msgstr "Neuer Punchbereich"
 msgid "New CD track marker"
 msgstr "Neuer CD-Track Marker"
 
-#: editor_rulers.cc:235 tempo_dialog.cc:38
+#: editor_rulers.cc:234 tempo_dialog.cc:38
 msgid "New Tempo"
 msgstr "Tempowechsel einfügen..."
 
-#: editor_rulers.cc:239 tempo_dialog.cc:315
+#: editor_rulers.cc:238 tempo_dialog.cc:315
 msgid "New Meter"
 msgstr "Taktwechsel einfügen..."
 
-#: editor_snapshots.cc:137
+#: editor_snapshots.cc:149
 msgid "Rename Snapshot"
 msgstr "Schnappschuss umbenennen"
 
-#: editor_snapshots.cc:139
+#: editor_snapshots.cc:151
 msgid "New name of snapshot"
 msgstr "Name für neuen Schnappschuss"
 
-#: editor_snapshots.cc:157
+#: editor_snapshots.cc:169
 msgid ""
 "Do you really want to remove snapshot \"%1\" ?\n"
 "(which cannot be undone)"
@@ -6120,7 +6316,7 @@ msgstr ""
 "Wollen Sie den Schnappschuss \"%1\" wirklich löschen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: editor_snapshots.cc:162
+#: editor_snapshots.cc:174
 msgid "Remove snapshot"
 msgstr "Schnappschuss entfernen"
 
@@ -6168,19 +6364,19 @@ msgstr ""
 "Time-Stretch konnte nicht gestartet werden - Fehler beim erstellen des "
 "Threads"
 
-#: engine_dialog.cc:87
+#: engine_dialog.cc:86
 msgid "Device Control Panel"
 msgstr "Gerätekontrollfeld"
 
-#: engine_dialog.cc:88
+#: engine_dialog.cc:87
 msgid "Midi Device Setup"
 msgstr "MIDI Geräteeinstellungen"
 
 #: engine_dialog.cc:89
-msgid "Stop (Reconfigure)"
-msgstr "Stop (Neu konfigurieren)"
+msgid "Refresh Devices"
+msgstr "Geräteliste auffrischen"
 
-#: engine_dialog.cc:90 engine_dialog.cc:2693
+#: engine_dialog.cc:90 engine_dialog.cc:2923
 msgid "Measure"
 msgstr "Messen"
 
@@ -6200,7 +6396,7 @@ msgstr "AUdio kalibrieren"
 msgid "Back to settings"
 msgstr "Zurück zu Einstellungen"
 
-#: engine_dialog.cc:117
+#: engine_dialog.cc:118
 msgid ""
 "No audio/MIDI backends detected. %1 cannot run\n"
 "\n"
@@ -6210,11 +6406,11 @@ msgstr ""
 "\n"
 "(Das ist ein Kompilier-/Paket-/Systemfehler und sollte nie passieren.)"
 
-#: engine_dialog.cc:142
+#: engine_dialog.cc:143
 msgid "Latency Measurement Tool"
 msgstr "Latenzmeßwerkzeug"
 
-#: engine_dialog.cc:154
+#: engine_dialog.cc:155
 msgid ""
 "<span weight=\"bold\">Turn down the volume on your audio equipment to a very "
 "low level.</span>"
@@ -6222,97 +6418,101 @@ msgstr ""
 "<span weight=\"bold\">Drehen Sie die Lautstärke Ihrer Audioanlage sehr leise."
 "</span>"
 
-#: engine_dialog.cc:163
+#: engine_dialog.cc:164
 msgid "Select two channels below and connect them using a cable."
 msgstr "Wählen Sie unten zwei Kanäle aus und verbinden sie mit einem Kabel."
 
-#: engine_dialog.cc:168
+#: engine_dialog.cc:169
 msgid "Output channel"
 msgstr "Ausgangskanal"
 
-#: engine_dialog.cc:176
+#: engine_dialog.cc:177
 msgid "Input channel"
 msgstr "Eingangskanal"
 
-#: engine_dialog.cc:209
+#: engine_dialog.cc:211
 msgid "Once the channels are connected, click the \"Measure\" button."
 msgstr "Wenn die Kanäle verbunden sind, klicken Sie den \"Messen\"-Knopf."
 
-#: engine_dialog.cc:216
+#: engine_dialog.cc:218
 msgid "When satisfied with the results, click the \"Use results\" button."
 msgstr ""
 "Wenn Sie mit dem Resultat zufrieden sind, klicken Sie den Knopf \"Benutze "
 "Ergebnisse\"."
 
-#: engine_dialog.cc:231 engine_dialog.cc:2813 engine_dialog.cc:2823
+#: engine_dialog.cc:233 engine_dialog.cc:3058 engine_dialog.cc:3068
 msgid "No measurement results yet"
 msgstr "Noch keine Messergebnisse"
 
-#: engine_dialog.cc:241 route_params_ui.cc:106
+#: engine_dialog.cc:243 route_params_ui.cc:106
 msgid "Latency"
 msgstr "Latenz"
 
-#: engine_dialog.cc:465
+#: engine_dialog.cc:497
 msgid "Audio System:"
 msgstr "Audiosystem:"
 
-#: engine_dialog.cc:507
+#: engine_dialog.cc:540
 msgid "Driver:"
 msgstr "Treiber:"
 
-#: engine_dialog.cc:514
+#: engine_dialog.cc:547
 msgid "Input Device:"
 msgstr "Eingangsgerät:"
 
-#: engine_dialog.cc:518
+#: engine_dialog.cc:551
 msgid "Output Device:"
 msgstr "Ausgangsgerät:"
 
-#: engine_dialog.cc:525
+#: engine_dialog.cc:558
 msgid "Device:"
 msgstr "Gerät:"
 
-#: engine_dialog.cc:534 engine_dialog.cc:639 sfdb_ui.cc:152 sfdb_ui.cc:347
-#: sfdb_ui.cc:352
+#: engine_dialog.cc:567 engine_dialog.cc:681 sfdb_ui.cc:153 sfdb_ui.cc:348
+#: sfdb_ui.cc:353
 msgid "Sample rate:"
 msgstr "Samplerate:"
 
-#: engine_dialog.cc:540 engine_dialog.cc:646
+#: engine_dialog.cc:573 engine_dialog.cc:688
 msgid "Buffer size:"
 msgstr "Puffergröße"
 
-#: engine_dialog.cc:558
+#: engine_dialog.cc:582
+msgid "Periods:"
+msgstr "Perioden:"
+
+#: engine_dialog.cc:600
 msgid "Input Channels:"
 msgstr "Eingangskanäle:"
 
-#: engine_dialog.cc:571
+#: engine_dialog.cc:613
 msgid "Output Channels:"
 msgstr "Ausgangskanäle:"
 
-#: engine_dialog.cc:583
+#: engine_dialog.cc:625
 msgid "Hardware input latency:"
 msgstr "Hardware Eingangslatenz (Samples)"
 
-#: engine_dialog.cc:586 engine_dialog.cc:599
+#: engine_dialog.cc:628 engine_dialog.cc:641
 msgid "samples"
 msgstr "Samples"
 
-#: engine_dialog.cc:596
+#: engine_dialog.cc:638
 msgid "Hardware output latency:"
 msgstr "Hardware Ausgangslatenz (Samples)"
 
-#: engine_dialog.cc:607
+#: engine_dialog.cc:649
 msgid "MIDI System:"
 msgstr "MIDI System:"
 
-#: engine_dialog.cc:631
+#: engine_dialog.cc:673
 msgid ""
 "%1 is already running. %2 will connect to it and use the existing settings."
 msgstr ""
 "%1 läuft bereits. %2 wird zu ihm verbinden und die existierenden "
 "Einstellungen übernehmen."
 
-#: engine_dialog.cc:684
+#: engine_dialog.cc:726
 msgid ""
 "Failed to start or connect to audio-engine.\n"
 "\n"
@@ -6322,7 +6522,7 @@ msgstr ""
 "\n"
 "Latenzkalibrierung erfordert ein funktionierendes Audio-Interface."
 
-#: engine_dialog.cc:690
+#: engine_dialog.cc:732
 msgid ""
 "Your selected audio configuration is playback- or capture-only.\n"
 "\n"
@@ -6334,143 +6534,151 @@ msgstr ""
 "Latenzkalibrierung verlangt Duplexbetrieb (gleichzeitig Aufnahme und "
 "Wiedergabe)"
 
-#: engine_dialog.cc:870
+#: engine_dialog.cc:938
 msgid "MIDI Devices"
 msgstr "MIDI Geräte"
 
-#: engine_dialog.cc:876
+#: engine_dialog.cc:944
 msgid "Device"
 msgstr "Gerät"
 
-#: engine_dialog.cc:878
+#: engine_dialog.cc:946
 msgid "Hardware Latencies"
 msgstr "Hardware-Latenzen"
 
-#: engine_dialog.cc:919
+#: engine_dialog.cc:987
 msgid "Calibrate"
 msgstr "Kalibrieren"
 
-#: engine_dialog.cc:1008
+#: engine_dialog.cc:1090
 msgid "all available channels"
 msgstr "alle verfügbaren Kanäle"
 
-#: engine_dialog.cc:1441 latency_gui.cc:39
+#: engine_dialog.cc:1576 latency_gui.cc:39
 msgid "sample"
 msgid_plural "samples"
 msgstr[0] "Sample"
 msgstr[1] "Samples"
 
-#: engine_dialog.cc:1494
+#: engine_dialog.cc:1640
 #, c-format
 msgid "(%.1f ms)"
 msgstr "(%.1f ms)"
 
-#: engine_dialog.cc:2161
+#: engine_dialog.cc:2371
 msgid "Could not start backend engine %1"
 msgstr "Konnte Backend Engine %1 nicht starten"
 
-#: engine_dialog.cc:2212
+#: engine_dialog.cc:2403
 msgid "Cannot set driver to %1"
 msgstr "Kann Treiber nicht auf %1 setzen"
 
-#: engine_dialog.cc:2217
+#: engine_dialog.cc:2408
 msgid "Cannot set input device name to %1"
 msgstr "Kann Namen des Eingangsgeräts nicht auf %1 setzen"
 
-#: engine_dialog.cc:2221
+#: engine_dialog.cc:2412
 msgid "Cannot set output device name to %1"
 msgstr "Kann Namen des Ausgangsgeräts nicht auf %1 setzen"
 
-#: engine_dialog.cc:2226
+#: engine_dialog.cc:2417
 msgid "Cannot set device name to %1"
 msgstr "Kann Gerät nicht auf %1 setzen"
 
-#: engine_dialog.cc:2231
+#: engine_dialog.cc:2422
 msgid "Cannot set sample rate to %1"
 msgstr "Kann Samplerate nicht auf %1 setzen"
 
-#: engine_dialog.cc:2235
+#: engine_dialog.cc:2426
 msgid "Cannot set buffer size to %1"
 msgstr "Kann Buffergröße nicht auf %1 setzen"
 
-#: engine_dialog.cc:2241
+#: engine_dialog.cc:2430
+msgid "Cannot set periods to %1"
+msgstr "Kann Perioden nicht auf %1 setzen"
+
+#: engine_dialog.cc:2436
 msgid "Cannot set input channels to %1"
 msgstr "Kann Eingangskanäle nicht auf %1 setzen"
 
-#: engine_dialog.cc:2245
+#: engine_dialog.cc:2440
 msgid "Cannot set output channels to %1"
 msgstr "Kann Ausgangskanäle nicht auf %1 setzen"
 
-#: engine_dialog.cc:2251
+#: engine_dialog.cc:2446
 msgid "Cannot set input latency to %1"
 msgstr "Kann Eingangslatenz nicht auf %1 setzen"
 
-#: engine_dialog.cc:2255
+#: engine_dialog.cc:2450
 msgid "Cannot set output latency to %1"
 msgstr "Kann Ausgangslatenz nicht auf %1 setzen"
 
-#: engine_dialog.cc:2551 engine_dialog.cc:2610
+#: engine_dialog.cc:2781 engine_dialog.cc:2840
 msgid "No signal detected "
 msgstr "Kein Signal erkannt"
 
-#: engine_dialog.cc:2564 engine_dialog.cc:2618 port_insert_ui.cc:70
+#: engine_dialog.cc:2794 engine_dialog.cc:2848 port_insert_ui.cc:70
 #: port_insert_ui.cc:98
 msgid "Disconnected from audio engine"
 msgstr "Von Audio-Engine getrennt"
 
-#: engine_dialog.cc:2573 engine_dialog.cc:2626
+#: engine_dialog.cc:2803 engine_dialog.cc:2856
 msgid "Detected roundtrip latency: "
 msgstr "Entdeckte Roundtrip-Latenz:"
 
-#: engine_dialog.cc:2575 engine_dialog.cc:2628
+#: engine_dialog.cc:2805 engine_dialog.cc:2858
 msgid "Systemic latency: "
 msgstr "Systemische Latenz:"
 
-#: engine_dialog.cc:2582
+#: engine_dialog.cc:2812
 msgid "(signal detection error)"
 msgstr "(Fehler bei der Signalerkennung)"
 
-#: engine_dialog.cc:2588
+#: engine_dialog.cc:2818
 msgid "(inverted - bad wiring)"
 msgstr "(invertiert - schlechte Verkabelung)"
 
-#: engine_dialog.cc:2635
+#: engine_dialog.cc:2865
 msgid "(averaging)"
 msgstr "(durchschnittlich)"
 
-#: engine_dialog.cc:2641
+#: engine_dialog.cc:2871
 msgid "(too large jitter)"
 msgstr "(zu viel Jitter)"
 
-#: engine_dialog.cc:2645
+#: engine_dialog.cc:2875
 msgid "(large jitter)"
 msgstr "(viel Jitter)"
 
-#: engine_dialog.cc:2657
+#: engine_dialog.cc:2887
 msgid "Timeout - large MIDI jitter."
 msgstr "Timeout - viel MIDI Jitter."
 
-#: engine_dialog.cc:2673 port_insert_ui.cc:134
+#: engine_dialog.cc:2903 port_insert_ui.cc:134
 msgid "Detecting ..."
 msgstr "Messe..."
 
-#: engine_dialog.cc:2764
+#: engine_dialog.cc:3004
 msgid "Disconnect from %1"
 msgstr "Trenne von %1"
 
-#: engine_dialog.cc:2769
+#: engine_dialog.cc:3009
 msgid "Running"
 msgstr "Läuft"
 
-#: engine_dialog.cc:2771
+#: engine_dialog.cc:3011
 msgid "Connected"
 msgstr "Verbunden"
 
-#: engine_dialog.cc:2782
+#: engine_dialog.cc:3022
 msgid "Connect to %1"
 msgstr "Verbinde zu %1"
 
-#: export_channel_selector.cc:51 sfdb_ui.cc:150
+#: engine_dialog.cc:3026 shuttle_control.cc:614
+msgid "Stopped"
+msgstr "Gestoppt"
+
+#: export_channel_selector.cc:51 sfdb_ui.cc:151
 msgid "Channels:"
 msgstr "Kanäle:"
 
@@ -6526,20 +6734,20 @@ msgstr ""
 msgid "List files"
 msgstr "Dateien auflisten"
 
-#: export_dialog.cc:158 export_format_dialog.cc:59
+#: export_dialog.cc:156 export_format_dialog.cc:59
 msgid "File format"
 msgstr "Dateiformat"
 
-#: export_dialog.cc:159 export_timespan_selector.cc:374
-#: export_timespan_selector.cc:436
+#: export_dialog.cc:157 export_timespan_selector.cc:371
+#: export_timespan_selector.cc:433
 msgid "Time Span"
 msgstr "Zeitspanne"
 
-#: export_dialog.cc:160
+#: export_dialog.cc:158
 msgid "Channels"
 msgstr "Kanäle"
 
-#: export_dialog.cc:182
+#: export_dialog.cc:180
 msgid ""
 "Export has been aborted due to an error!\n"
 "See the Log for details."
@@ -6547,39 +6755,39 @@ msgstr ""
 "Das Exportieren wurde aufgrund eines Fehlers abgebrochen!\n"
 "Details dazu stehen in der Log."
 
-#: export_dialog.cc:251
+#: export_dialog.cc:249
 msgid "Files that will be overwritten"
 msgstr "Dateien, die überschrieben werden"
 
-#: export_dialog.cc:296
+#: export_dialog.cc:294
 msgid "Export initialization failed: %1"
 msgstr "Exportinitialisierung gescheitert: %1"
 
-#: export_dialog.cc:306
+#: export_dialog.cc:304
 msgid "Stop Export"
 msgstr "Export Abbrechen"
 
-#: export_dialog.cc:327
+#: export_dialog.cc:325
 msgid "export"
 msgstr "Exportieren"
 
-#: export_dialog.cc:346
+#: export_dialog.cc:344
 msgid "Normalizing '%3' (timespan %1 of %2)"
 msgstr "Normalisiere '%3' (Zeitspanne %1 von %2)"
 
-#: export_dialog.cc:350
+#: export_dialog.cc:348
 msgid "Exporting '%3' (timespan %1 of %2)"
 msgstr "Exportiere '%3' (Zeitspanne %1 von %2)"
 
-#: export_dialog.cc:373 export_dialog.cc:375
+#: export_dialog.cc:371 export_dialog.cc:373
 msgid "<span color=\"#ffa755\">Error: "
 msgstr "<span color=\"#ffa755\">Fehler: "
 
-#: export_dialog.cc:385
+#: export_dialog.cc:383
 msgid "<span color=\"#ffa755\">Warning: "
 msgstr "<span color=\"#ffa755\">Warnung: "
 
-#: export_dialog.cc:387
+#: export_dialog.cc:385
 msgid ""
 "\n"
 "<span color=\"#ffa755\">Warning: "
@@ -6587,19 +6795,19 @@ msgstr ""
 "\n"
 "<span color=\"#ffa755\">Warnung: "
 
-#: export_dialog.cc:411
+#: export_dialog.cc:409
 msgid "Export Selection"
 msgstr "Auswahl exportieren"
 
-#: export_dialog.cc:425
+#: export_dialog.cc:423
 msgid "Export Region"
 msgstr "Region exportieren"
 
-#: export_dialog.cc:434
+#: export_dialog.cc:432
 msgid "Source"
 msgstr "Quelle"
 
-#: export_dialog.cc:450
+#: export_dialog.cc:448
 msgid "Stem Export"
 msgstr "Stem Export"
 
@@ -6631,7 +6839,7 @@ msgstr "Format: %1: %2"
 msgid "Label:"
 msgstr "Name:"
 
-#: export_filename_selector.cc:33
+#: export_filename_selector.cc:33 session_dialog.cc:310
 msgid "Session Name"
 msgstr "Projektname"
 
@@ -6654,18 +6862,18 @@ msgstr "Durchsuchen"
 msgid "<i>Build filename(s) from these components:</i>"
 msgstr "<i>Dateiname(n) aus diesen Bestandteilen erzeugen:</i>"
 
-#: export_filename_selector.cc:212
+#: export_filename_selector.cc:208
 msgid ""
 "<small><i>Sorry, no example filename can be shown at the moment</i></small>"
 msgstr ""
 "<small><i>Leider kann zur Zeit kein Dateinamen-Beispiel gezeigt werden</i></"
 "small>"
 
-#: export_filename_selector.cc:214
+#: export_filename_selector.cc:210
 msgid "<small><i>Current (approximate) filename: \"%1\"</i></small>"
 msgstr "<small><i>Momentaner (ungefährer) Dateiname: \"%1\"</i></small>"
 
-#: export_filename_selector.cc:250 export_filename_selector.cc:336
+#: export_filename_selector.cc:246 export_filename_selector.cc:332
 msgid ""
 "%1: this is only the directory/folder name, not the filename.\n"
 "The filename will be chosen from the information just above the folder "
@@ -6675,7 +6883,7 @@ msgstr ""
 "Der Dateiname wird aus den Informationen über der "
 "Verzeichnisauswahlgeneriert."
 
-#: export_filename_selector.cc:322
+#: export_filename_selector.cc:318
 msgid "Choose export folder"
 msgstr "Wähle den Exportordner"
 
@@ -6783,7 +6991,7 @@ msgstr "FLAC Optionen"
 msgid "Broadcast Wave options"
 msgstr "Broadcast Wave Optionen"
 
-#: export_format_selector.cc:136
+#: export_format_selector.cc:131
 msgid "Do you really want to remove the format?"
 msgstr "Wollen Sie das Format wirklich entfernen?"
 
@@ -6791,7 +6999,7 @@ msgstr "Wollen Sie das Format wirklich entfernen?"
 msgid "Preset"
 msgstr "Preset"
 
-#: export_preset_selector.cc:104
+#: export_preset_selector.cc:99
 msgid ""
 "The selected preset did not load successfully!\n"
 "Perhaps it references a format that has been removed?"
@@ -6799,23 +7007,23 @@ msgstr ""
 "Das ausgewählte Preset konnte nicht geladen werden!\n"
 "Möglicherweise verwendet es ein Format, das entfernt wurde."
 
-#: export_preset_selector.cc:156
+#: export_preset_selector.cc:151
 msgid "Do you really want to remove this preset?"
 msgstr "Wollen Sie dieses Preset wirklich entfernen?"
 
-#: export_timespan_selector.cc:46
+#: export_timespan_selector.cc:44
 msgid "Show Times as:"
 msgstr "Zeitanzeige:"
 
-#: export_timespan_selector.cc:53 processor_box.cc:2533
+#: export_timespan_selector.cc:51 processor_box.cc:2730
 msgid "Select All"
 msgstr "Alles auswählen"
 
-#: export_timespan_selector.cc:223 transform_dialog.cc:93
+#: export_timespan_selector.cc:220 transform_dialog.cc:93
 msgid " to "
 msgstr " bis"
 
-#: export_timespan_selector.cc:367 export_timespan_selector.cc:426
+#: export_timespan_selector.cc:364 export_timespan_selector.cc:423
 msgid "Range"
 msgstr "Bereiche"
 
@@ -6831,7 +7039,7 @@ msgstr "getSoundResourceFile: Keine gültige Wurzel in der XML-Datei"
 msgid "getSoundResourceFile: root = %1, != response"
 msgstr "getSoundResourceFile: Wurzel = %1, != Antwort"
 
-#: sfdb_freesound_mootcher.cc:410 rc_option_editor.cc:2298
+#: sfdb_freesound_mootcher.cc:410 rc_option_editor.cc:2276
 msgid "%1"
 msgstr "%1"
 
@@ -6847,7 +7055,7 @@ msgstr "Fader Automationsmodus"
 msgid "Fader automation type"
 msgstr "Fader-Automationstyp"
 
-#: gain_meter.cc:159 gain_meter.cc:831 panner_ui.cc:177 panner_ui.cc:639
+#: gain_meter.cc:159 gain_meter.cc:831 panner_ui.cc:179 panner_ui.cc:641
 msgid "Abs"
 msgstr "Abs"
 
@@ -6867,47 +7075,47 @@ msgstr "T"
 msgid "W"
 msgstr "W"
 
-#: generic_pluginui.cc:83
+#: generic_pluginui.cc:85
 msgid "<span size=\"large\">Presets</span>"
 msgstr "<span size=\"large\">Voreinstellungen</span>"
 
-#: generic_pluginui.cc:98
+#: generic_pluginui.cc:100
 msgid "Manual"
 msgstr "Manuell"
 
-#: generic_pluginui.cc:107
+#: generic_pluginui.cc:109
 msgid "All Automation"
 msgstr "Alle Automation"
 
-#: generic_pluginui.cc:251
+#: generic_pluginui.cc:253
 msgid "Switches"
 msgstr "Schalter"
 
-#: generic_pluginui.cc:261 generic_pluginui.cc:437 processor_box.cc:2507
+#: generic_pluginui.cc:263 generic_pluginui.cc:439 processor_box.cc:2708
 msgid "Controls"
 msgstr "Steuerelemente"
 
-#: generic_pluginui.cc:294
+#: generic_pluginui.cc:296
 msgid "Plugin Editor: could not build control element for port %1"
 msgstr "Plugin Editor: konnte kein Steuerelement für Port %1 erzeugen"
 
-#: generic_pluginui.cc:319
+#: generic_pluginui.cc:321
 msgid "Plugin Editor: no control for property %1"
 msgstr "Plugin Editor: kein Regler für Eigenschaft %1"
 
-#: generic_pluginui.cc:325
+#: generic_pluginui.cc:327
 msgid "Plugin Editor: could not build control element for property %1"
 msgstr "Plugin Editor: konnte kein Kontrollelement für Eigenschaft %1 erzeugen"
 
-#: generic_pluginui.cc:469
+#: generic_pluginui.cc:471
 msgid "Meters"
 msgstr "Pegelanzeigen"
 
-#: generic_pluginui.cc:491
+#: generic_pluginui.cc:493
 msgid "Automation control"
 msgstr "Automation"
 
-#: generic_pluginui.cc:498
+#: generic_pluginui.cc:500
 msgid "Mgnual"
 msgstr "Mgnuell"
 
@@ -6919,8 +7127,8 @@ msgstr "Audio Verbindungsmanager"
 msgid "MIDI Connection Manager"
 msgstr "Midi Verbindungsmanager"
 
-#: global_port_matrix.cc:201 io_selector.cc:211 mixer_strip.cc:826
-#: mixer_strip.cc:927 monitor_section.cc:1279 monitor_selector.cc:189
+#: global_port_matrix.cc:201 io_selector.cc:211 mixer_strip.cc:840
+#: mixer_strip.cc:941 monitor_section.cc:1306 monitor_selector.cc:189
 msgid "Disconnect"
 msgstr "Trenne"
 
@@ -6940,47 +7148,47 @@ msgstr "Spuren, deren Aufnahme aktiviert ist"
 msgid "Soloed..."
 msgstr "Solo-Spuren/Busse"
 
-#: group_tabs.cc:320
+#: group_tabs.cc:321
 msgid "Create New Group ..."
 msgstr "Neue Gruppe erzeugen ..."
 
-#: group_tabs.cc:321
+#: group_tabs.cc:324
 msgid "Create New Group From"
 msgstr "Neue Gruppe erzeugen aus"
 
-#: group_tabs.cc:324
+#: group_tabs.cc:327
 msgid "Edit Group..."
 msgstr "Gruppe bearbeiten..."
 
-#: group_tabs.cc:325
+#: group_tabs.cc:328
 msgid "Collect Group"
 msgstr "Gruppe sammeln"
 
-#: group_tabs.cc:326
+#: group_tabs.cc:329
 msgid "Remove Group"
 msgstr "Gruppe entfernen"
 
-#: group_tabs.cc:329
+#: group_tabs.cc:332
 msgid "Remove Subgroup Bus"
 msgstr "Subgruppen-Bus entfernen"
 
-#: group_tabs.cc:331
+#: group_tabs.cc:334
 msgid "Add New Subgroup Bus"
 msgstr "Subgruppen-Bus hinzufügen"
 
-#: group_tabs.cc:333
+#: group_tabs.cc:336
 msgid "Add New Aux Bus (pre-fader)"
 msgstr "Aux-Send zur Subgruppe hinzufügen (Pre-Fader)"
 
-#: group_tabs.cc:334
+#: group_tabs.cc:337
 msgid "Add New Aux Bus (post-fader)"
 msgstr "Aux-Send zur Subgruppe hinzufügen (Post-Fader)"
 
-#: group_tabs.cc:340
+#: group_tabs.cc:343
 msgid "Enable All Groups"
 msgstr "Alle Gruppen aktivieren"
 
-#: group_tabs.cc:341
+#: group_tabs.cc:344
 msgid "Disable All Groups"
 msgstr "Alle Gruppen deaktivieren"
 
@@ -7048,7 +7256,7 @@ msgstr "Stille einfügen"
 msgid "-none-"
 msgstr "-keine-"
 
-#: interthread_progress_window.cc:103
+#: interthread_progress_window.cc:104
 msgid "Importing file: %1 of %2"
 msgstr "Importiere Datei: %1 von %2"
 
@@ -7064,17 +7272,17 @@ msgstr "%1 Eingang"
 msgid "%1 output"
 msgstr "%1 Ausgang"
 
-#: keyboard.cc:78
+#: keyboard.cc:82
 msgid "your own"
 msgstr "Eigenes"
 
-#: keyboard.cc:141 keyboard.cc:165
+#: keyboard.cc:145 keyboard.cc:169
 msgid "Default keybindings not found - %1 will be hard to use!"
 msgstr ""
 "Keine Tastatur-Standardbelegung gefunden - %1 wird sich schwer bedienen "
 "lassen!"
 
-#: keyboard.cc:144
+#: keyboard.cc:148
 msgid "Key bindings file \"%1\" not found. Default bindings used instead"
 msgstr ""
 "Die Datei  \"%1\" für Tastaturkürzel  wurde nicht gefunden. Stattdessen wird "
@@ -7136,103 +7344,103 @@ msgid_plural "%1 samples"
 msgstr[0] "%1 Sample"
 msgstr[1] "%1 Samples"
 
-#: latency_gui.cc:72 panner_ui.cc:409 plugin_ui.cc:421
+#: latency_gui.cc:72 panner_ui.cc:411 plugin_ui.cc:421
 msgid "Reset"
 msgstr "Reset"
 
-#: latency_gui.cc:149 rhythm_ferret.cc:273 sfdb_ui.cc:1911
+#: latency_gui.cc:149 rhythm_ferret.cc:273 sfdb_ui.cc:1909
 msgid "programming error: %1 (%2)"
 msgstr "Programmierfehler: %1 (%2)"
 
-#: location_ui.cc:52 location_ui.cc:54
+#: location_ui.cc:54 location_ui.cc:56
 msgid "Use PH"
 msgstr "zu PZ"
 
-#: location_ui.cc:59
+#: location_ui.cc:61
 msgid "Glue"
 msgstr "Bindung"
 
-#: location_ui.cc:87
+#: location_ui.cc:89
 msgid "Performer:"
 msgstr "Performer:"
 
-#: location_ui.cc:88
+#: location_ui.cc:90
 msgid "Composer:"
 msgstr "Komponist:"
 
-#: location_ui.cc:90
+#: location_ui.cc:92
 msgid "Pre-Emphasis"
 msgstr "Präemphase"
 
-#: location_ui.cc:317
+#: location_ui.cc:319
 msgid "Remove this range"
 msgstr "Diesen Bereich entfernen"
 
-#: location_ui.cc:318
+#: location_ui.cc:320
 msgid "Start time - middle click to locate here"
 msgstr "Startzeit - Mittelklick, um hierher zu positionieren"
 
-#: location_ui.cc:319
+#: location_ui.cc:321
 msgid "End time - middle click to locate here"
 msgstr "Endzeit - Mittelklick, um hierher zu positionieren"
 
-#: location_ui.cc:322
+#: location_ui.cc:324
 msgid "Set range start from playhead location"
 msgstr "Bereichsbeginn auf Positionszeiger setzen"
 
-#: location_ui.cc:323
+#: location_ui.cc:325
 msgid "Set range end from playhead location"
 msgstr "Bereichsende auf Positionszeiger setzen"
 
-#: location_ui.cc:327
+#: location_ui.cc:329
 msgid "Remove this marker"
 msgstr "Diesen Marker entfernen"
 
-#: location_ui.cc:328
+#: location_ui.cc:330
 msgid "Position - middle click to locate here"
 msgstr "Position - Mittelklick, um hierher zu positionieren"
 
-#: location_ui.cc:330
+#: location_ui.cc:332
 msgid "Set marker time from playhead location"
 msgstr "Markerposition auf Positionszeiger setzen"
 
-#: location_ui.cc:499
+#: location_ui.cc:501
 msgid "You cannot put a CD marker at the start of the session"
 msgstr "Sie können keinen CD-Marker am Anfang des Projekts erstellen"
 
-#: location_ui.cc:725
+#: location_ui.cc:727
 msgid "New Marker"
 msgstr "Neuer Marker"
 
-#: location_ui.cc:726
+#: location_ui.cc:728
 msgid "New Range"
 msgstr "Neuer Bereich"
 
-#: location_ui.cc:739
+#: location_ui.cc:741
 msgid "<b>Loop/Punch Ranges</b>"
 msgstr "<b>Schleifen/Punchbereiche</b>"
 
-#: location_ui.cc:764
+#: location_ui.cc:766
 msgid "<b>Markers (Including CD Index)</b>"
 msgstr "<b>Marker (auch CD-Index)</b>"
 
-#: location_ui.cc:799
+#: location_ui.cc:801
 msgid "<b>Ranges (Including CD Track Ranges)</b>"
 msgstr "<b>Bereiche (auch CD-Track-Bereichen)</b>"
 
-#: location_ui.cc:1042
+#: location_ui.cc:1044
 msgid "add range marker"
 msgstr "Bereich hinzufügen"
 
-#: main.cc:82
+#: main.cc:86
 msgid "%1 could not connect to the audio backend."
 msgstr "%1 konnte nicht zum Audiobackend verbinden."
 
-#: main.cc:129 main.cc:145
+#: main.cc:133 main.cc:149
 msgid "The audio backend (%1) has failed, or terminated"
 msgstr "Das Audiobackend (%1) funktioniert nicht oder wurde beendet"
 
-#: main.cc:132
+#: main.cc:136
 msgid ""
 "%2 exited unexpectedly, and without notifying %1.\n"
 "\n"
@@ -7247,11 +7455,11 @@ msgstr ""
 "\n"
 "Klicke OK, um %1 zu verlassen."
 
-#: main.cc:146
+#: main.cc:150
 msgid "%2 exited unexpectedly, and without notifying %1."
 msgstr "%2 wurde unerwartet und ohne %1 zu benachrichtigen beendet "
 
-#: main.cc:241
+#: main.cc:245
 msgid ""
 "\n"
 "   %1 could not understand your command line      "
@@ -7259,23 +7467,23 @@ msgstr ""
 "\n"
 "   %1 konnte Ihre Kommandozeile nicht verstehen      "
 
-#: main.cc:243
+#: main.cc:247
 msgid "An error was encountered while launching %1"
 msgstr "Während des Programmstarts von %1 ist ein Fehler aufgetreten"
 
-#: main.cc:332
+#: main.cc:340
 msgid " (built using "
 msgstr " (kompiliert mit Version "
 
-#: main.cc:335
+#: main.cc:343
 msgid " and GCC version "
 msgstr " und GCC Version"
 
-#: main.cc:345
+#: main.cc:353
 msgid "Copyright (C) 1999-2015 Paul Davis"
 msgstr "Copyright (C) 1999-2015 Paul Davis"
 
-#: main.cc:346
+#: main.cc:354
 msgid ""
 "Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
 "Baker, Robin Gareus"
@@ -7283,68 +7491,68 @@ msgstr ""
 "Einige Teile Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
 "Baker, Robin Gareus"
 
-#: main.cc:348
+#: main.cc:356
 msgid "%1 comes with ABSOLUTELY NO WARRANTY"
 msgstr "%1 wird Ihnen ohne jegliche Gewährleistung"
 
-#: main.cc:349
+#: main.cc:357
 msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 msgstr ""
 "für allgemeine oder spezielle Gebrauchstauglichkeit zur Verfügung gestellt."
 
-#: main.cc:350
+#: main.cc:358
 msgid "This is free software, and you are welcome to redistribute it "
 msgstr "Dies ist freie Software, die Sie gerne weitergeben dürfen,"
 
-#: main.cc:351
+#: main.cc:359
 msgid "under certain conditions; see the source for copying conditions."
 msgstr ""
 "solange Sie sich an die Bedingungen, die in der Datei COPYING aufgeführt "
 "sind, halten."
 
-#: main.cc:356
+#: main.cc:364
 msgid "could not initialize %1."
 msgstr "Konnte %1 nicht initialisieren."
 
-#: main.cc:366
+#: main.cc:374
 msgid "Cannot xinstall SIGPIPE error handler"
 msgstr "Kann die SIGPIPE Fehlerbehandlung nicht installieren"
 
-#: main.cc:373
+#: main.cc:379
 msgid "Could not complete pre-GUI initialization"
 msgstr "Konnte Initialisierung (pre-GUI) nicht abschließen"
 
-#: main.cc:380
+#: main.cc:386
 msgid "could not create %1 GUI"
 msgstr "konnte das %1 GUI nicht erstellen"
 
-#: main_clock.cc:50
+#: main_clock.cc:51
 msgid "Display delta to edit cursor"
 msgstr "Zeige Abstand zu Arbeitspunkt"
 
-#: main_clock.cc:65 tempo_dialog.cc:54
+#: main_clock.cc:66 tempo_dialog.cc:54
 msgid "Edit Tempo"
 msgstr "Tempo bearbeiten"
 
-#: main_clock.cc:66 tempo_dialog.cc:326
+#: main_clock.cc:67 tempo_dialog.cc:326
 msgid "Edit Meter"
 msgstr "Taktart bearbeiten"
 
-#: main_clock.cc:67
+#: main_clock.cc:68
 msgid "Insert Tempo Change"
 msgstr "Tempowechsel einfügen"
 
-#: main_clock.cc:68
+#: main_clock.cc:69
 msgid "Insert Meter Change"
 msgstr "Taktartwechsel einfügen"
 
-#: marker.cc:276
+#: marker.cc:280
 msgid "MarkerText"
 msgstr "MarkerText"
 
 #: midi_channel_selector.cc:161 midi_channel_selector.cc:400
-#: midi_channel_selector.cc:436 rc_option_editor.cc:2044
-#: rc_option_editor.cc:2677 sfdb_ui.cc:664
+#: midi_channel_selector.cc:436 rc_option_editor.cc:2017
+#: rc_option_editor.cc:2663 sfdb_ui.cc:670
 msgid "None"
 msgstr "Kein"
 
@@ -7427,11 +7635,11 @@ msgstr "Klicke, um die Wiedergabe von Kanal %1 umzuschalten"
 msgid "Click to force all MIDI channel messages to channel %1"
 msgstr "Klicke, um alle MIDI Channel Messages auf Kanal %1 auszugeben"
 
-#: midi_channel_selector.cc:718
+#: midi_channel_selector.cc:720
 msgid "Click to toggle recording of channel %1"
 msgstr "Klicke, um die Aufnahme von Kanal %1 umzuschalten"
 
-#: midi_channel_selector.cc:726
+#: midi_channel_selector.cc:728
 msgid "Click to force all recorded channels to %1"
 msgstr "Klicke, um alle aufgenommenen Kanäle an %1 zu zwingen"
 
@@ -7535,200 +7743,200 @@ msgstr "Portname:"
 msgid "MidiPortDialog"
 msgstr "MidiPortDialog"
 
-#: midi_region_view.cc:863
+#: midi_region_view.cc:849
 msgid "channel edit"
 msgstr "Kanal editieren"
 
-#: midi_region_view.cc:899
+#: midi_region_view.cc:885
 msgid "velocity edit"
 msgstr "Velocity bearbeiten"
 
-#: midi_region_view.cc:958
+#: midi_region_view.cc:944
 msgid "add note"
 msgstr "Note hinzufügen"
 
-#: midi_region_view.cc:1890
+#: midi_region_view.cc:1872
 msgid "step add"
 msgstr "Schritt hinzufügen"
 
-#: midi_region_view.cc:1984 midi_region_view.cc:2007
+#: midi_region_view.cc:1966 midi_region_view.cc:1989
 msgid "alter patch change"
 msgstr "Patch Change ändern"
 
-#: midi_region_view.cc:2043
+#: midi_region_view.cc:2025
 msgid "add patch change"
 msgstr "Patch Change hinzufügen"
 
-#: midi_region_view.cc:2065 midi_region_view.cc:2066
+#: midi_region_view.cc:2047 midi_region_view.cc:2048
 msgid "move patch change"
 msgstr "Patch Change verschieben"
 
-#: midi_region_view.cc:2078 midi_region_view.cc:2079
+#: midi_region_view.cc:2060 midi_region_view.cc:2061
 msgid "delete patch change"
 msgstr "Patch Change löschen"
 
-#: midi_region_view.cc:2117
+#: midi_region_view.cc:2099
 msgid "delete selection"
 msgstr "Auswahl löschen"
 
-#: midi_region_view.cc:2133
+#: midi_region_view.cc:2116
 msgid "delete note"
 msgstr "Note löschen"
 
-#: midi_region_view.cc:2592
+#: midi_region_view.cc:2575
 msgid "move notes"
 msgstr "Noten verschieben"
 
-#: midi_region_view.cc:3123
+#: midi_region_view.cc:3110
 msgid "change velocities"
 msgstr "Velocity ändern"
 
-#: midi_region_view.cc:3189
+#: midi_region_view.cc:3176
 msgid "transpose"
 msgstr "Transponieren"
 
-#: midi_region_view.cc:3217
+#: midi_region_view.cc:3204
 msgid "change note lengths"
 msgstr "Notenlänge ändern"
 
-#: midi_region_view.cc:3293
+#: midi_region_view.cc:3280
 msgid "nudge"
 msgstr "Verschieben"
 
-#: midi_region_view.cc:3308
+#: midi_region_view.cc:3295
 msgid "change channel"
 msgstr "Kanal ändern"
 
-#: midi_region_view.cc:3348
+#: midi_region_view.cc:3333
 msgid "Bank "
 msgstr "Bank"
 
-#: midi_region_view.cc:3349
+#: midi_region_view.cc:3334
 msgid "Program "
 msgstr "Programm"
 
-#: midi_region_view.cc:3350
+#: midi_region_view.cc:3335
 msgid "Channel "
 msgstr "Kanal"
 
-#: midi_region_view.cc:3537
+#: midi_region_view.cc:3522
 msgid "paste"
 msgstr "Einfügen"
 
-#: midi_streamview.cc:185
+#: midi_streamview.cc:184
 msgid "attempt to display MIDI region with no source"
 msgstr "versuche, eine MIDI Region ohne Datenquelle darzustellen"
 
-#: midi_streamview.cc:195
+#: midi_streamview.cc:194
 msgid "attempt to display MIDI region with no model"
 msgstr "versuche, eine MIDI Region ohne Datenmodell darzustellen"
 
-#: midi_streamview.cc:506
+#: midi_streamview.cc:505
 msgid "failed to create MIDI region"
 msgstr "konnte MIDI-Region nicht erzeugen"
 
-#: midi_time_axis.cc:309
+#: midi_time_axis.cc:316
 msgid "External MIDI Device"
 msgstr "Externes MIDI-Gerät"
 
-#: midi_time_axis.cc:310
+#: midi_time_axis.cc:317
 msgid "External Device Mode"
 msgstr "Modus Externes Gerät"
 
-#: midi_time_axis.cc:318
+#: midi_time_axis.cc:325
 msgid "Chns"
 msgstr "Chns"
 
-#: midi_time_axis.cc:320
+#: midi_time_axis.cc:327
 msgid "Click to edit channel settings"
 msgstr "Klicke, um Kanaleinstellungen zu bearbeiten"
 
-#: midi_time_axis.cc:519
+#: midi_time_axis.cc:526
 msgid "Show Full Range"
 msgstr "Ganzen Bereich anzeigen"
 
-#: midi_time_axis.cc:524
+#: midi_time_axis.cc:531
 msgid "Fit Contents"
 msgstr "Auf Inhalt anpassen"
 
-#: midi_time_axis.cc:528
+#: midi_time_axis.cc:535
 msgid "Note Range"
 msgstr "Notenbereich"
 
-#: midi_time_axis.cc:529
+#: midi_time_axis.cc:536
 msgid "Note Mode"
 msgstr "Noten-Modus"
 
-#: midi_time_axis.cc:530
+#: midi_time_axis.cc:537
 msgid "Channel Selector"
 msgstr "Kanalauswahl"
 
-#: midi_time_axis.cc:535
+#: midi_time_axis.cc:542
 msgid "Color Mode"
 msgstr "Farbmodus"
 
-#: midi_time_axis.cc:594
+#: midi_time_axis.cc:601
 msgid "Bender"
 msgstr "Bender"
 
-#: midi_time_axis.cc:598
+#: midi_time_axis.cc:605
 msgid "Pressure"
 msgstr "Druckdaten"
 
-#: midi_time_axis.cc:610
+#: midi_time_axis.cc:617
 msgid "Controllers"
 msgstr "Controller"
 
-#: midi_time_axis.cc:615
+#: midi_time_axis.cc:622
 msgid "No MIDI Channels selected"
 msgstr "Keine MIDI-Kanäle ausgewählt"
 
-#: midi_time_axis.cc:672 midi_time_axis.cc:801
+#: midi_time_axis.cc:679 midi_time_axis.cc:808
 msgid "Hide all channels"
 msgstr "Alle Kanäle verbergen"
 
-#: midi_time_axis.cc:676 midi_time_axis.cc:805
+#: midi_time_axis.cc:683 midi_time_axis.cc:812
 msgid "Show all channels"
 msgstr "Alle Kanäle anzeigen"
 
-#: midi_time_axis.cc:687 midi_time_axis.cc:816
+#: midi_time_axis.cc:694 midi_time_axis.cc:823
 msgid "Channel %1"
 msgstr "Kanal %1"
 
-#: midi_time_axis.cc:942 midi_time_axis.cc:974
+#: midi_time_axis.cc:949 midi_time_axis.cc:981
 msgid "Controllers %1-%2"
 msgstr "Controller %1-%2"
 
-#: midi_time_axis.cc:965 midi_time_axis.cc:968
+#: midi_time_axis.cc:972 midi_time_axis.cc:975
 msgid "Controller %1"
 msgstr "Controller %1"
 
-#: midi_time_axis.cc:991
+#: midi_time_axis.cc:998
 msgid "Sustained"
 msgstr "Sustain"
 
-#: midi_time_axis.cc:998
+#: midi_time_axis.cc:1005
 msgid "Percussive"
 msgstr "Perkussiv"
 
-#: midi_time_axis.cc:1018
+#: midi_time_axis.cc:1025
 msgid "Meter Colors"
 msgstr "Nach Lautstärke"
 
-#: midi_time_axis.cc:1025
+#: midi_time_axis.cc:1032
 msgid "Channel Colors"
 msgstr "Kanalfarben"
 
-#: midi_time_axis.cc:1032
+#: midi_time_axis.cc:1039
 msgid "Track Color"
 msgstr "Spurfarbe"
 
-#: midi_time_axis.cc:1607 midi_time_axis.cc:1613 midi_time_axis.cc:1623
-#: midi_time_axis.cc:1629
+#: midi_time_axis.cc:1614 midi_time_axis.cc:1620 midi_time_axis.cc:1630
+#: midi_time_axis.cc:1636
 msgid "all"
 msgstr "alle"
 
-#: midi_time_axis.cc:1610 midi_time_axis.cc:1626
+#: midi_time_axis.cc:1617 midi_time_axis.cc:1633
 msgid "some"
 msgstr "einige"
 
@@ -7744,7 +7952,7 @@ msgstr "Auto-Scroll"
 msgid "Decimal"
 msgstr "Dezimal"
 
-#: midi_tracer.cc:57 rc_option_editor.cc:1191
+#: midi_tracer.cc:57 rc_option_editor.cc:1355
 msgid "Enabled"
 msgstr "Aktiviert"
 
@@ -7760,35 +7968,35 @@ msgstr "Port:"
 msgid "New velocity"
 msgstr "Neue Velocity"
 
-#: missing_file_dialog.cc:35
+#: missing_file_dialog.cc:36
 msgid "Missing File"
 msgstr "Fehlende Datei"
 
-#: missing_file_dialog.cc:37
+#: missing_file_dialog.cc:38
 msgid "Select a folder to search"
 msgstr "Ordner zum Suchen auswählen"
 
-#: missing_file_dialog.cc:38
+#: missing_file_dialog.cc:39
 msgid "Add chosen folder to search path, and try again"
 msgstr "Ausgewählten Ordner zur Suche hinzufügen und es nochmal versuchen"
 
-#: missing_file_dialog.cc:40
+#: missing_file_dialog.cc:41
 msgid "Stop loading this session"
 msgstr "Laden des Projekts abbrechen"
 
-#: missing_file_dialog.cc:41
+#: missing_file_dialog.cc:42
 msgid "Skip all missing files"
 msgstr "Alle fehlenden Dateien überspringen"
 
-#: missing_file_dialog.cc:42
+#: missing_file_dialog.cc:43
 msgid "Skip this file"
 msgstr "Diese Datei überspringen"
 
-#: missing_file_dialog.cc:53
+#: missing_file_dialog.cc:57
 msgid "audio"
 msgstr "Audio"
 
-#: missing_file_dialog.cc:70
+#: missing_file_dialog.cc:74
 msgid ""
 "%1 cannot find the %2 file\n"
 "\n"
@@ -7808,7 +8016,7 @@ msgstr ""
 "<tt>%4</tt>\n"
 "\n"
 
-#: missing_file_dialog.cc:104
+#: missing_file_dialog.cc:108
 msgid "Click to choose an additional folder"
 msgstr "Einen weiteren Ordner für die Suche auswählen"
 
@@ -7816,7 +8024,7 @@ msgstr "Einen weiteren Ordner für die Suche auswählen"
 msgid "Missing Plugins"
 msgstr "Fehlende Plugins"
 
-#: missing_plugin_dialog.cc:33 transcode_video_dialog.cc:60
+#: missing_plugin_dialog.cc:36 transcode_video_dialog.cc:60
 msgid "OK"
 msgstr "OK"
 
@@ -7892,20 +8100,20 @@ msgstr "Mixer-Tastenkürzel aus %1 geladen"
 msgid "Could not find mixer.bindings in search path %1"
 msgstr "Konnte mixer.bindings im Suchpfad %1 nicht finden"
 
-#: mixer_strip.cc:97 mixer_strip.cc:127
+#: mixer_strip.cc:98 mixer_strip.cc:129
 msgid "pre"
 msgstr "Pre"
 
-#: mixer_strip.cc:99 mixer_strip.cc:129 mixer_strip.cc:384 mixer_strip.cc:1456
-#: rc_option_editor.cc:2833
+#: mixer_strip.cc:101 mixer_strip.cc:132 mixer_strip.cc:387
+#: mixer_strip.cc:1470 rc_option_editor.cc:2949
 msgid "Comments"
 msgstr "Kommentare"
 
-#: mixer_strip.cc:152
+#: mixer_strip.cc:155
 msgid "Click to toggle the width of this mixer strip."
 msgstr "Klicken Sie, um die Breite dieses Kanalzuges umzuschalten"
 
-#: mixer_strip.cc:154
+#: mixer_strip.cc:157
 msgid ""
 "\n"
 "%1-%2-click to toggle the width of all strips."
@@ -7913,250 +8121,270 @@ msgstr ""
 "\n"
 "%1-%2-Klicken Sie, um die Breite aller Kanalzüge umzuschalten."
 
-#: mixer_strip.cc:161
+#: mixer_strip.cc:164
 msgid "Hide this mixer strip"
 msgstr "Diesen Kanalzug verbergen"
 
-#: mixer_strip.cc:172
+#: mixer_strip.cc:175
 msgid "Click to select metering point"
 msgstr "Abgreifpunkt der Pegelanzeige auswählen"
 
-#: mixer_strip.cc:188
+#: mixer_strip.cc:191
 msgid "Isolate Solo"
 msgstr "Solo isolieren"
 
-#: mixer_strip.cc:196
+#: mixer_strip.cc:199
 msgid "Lock Solo Status"
 msgstr "Solostatus sperren"
 
-#: mixer_strip.cc:198 mixer_strip.cc:2090
+#: mixer_strip.cc:201 mixer_strip.cc:2113
 msgid "SoloLock|Lock"
 msgstr "Lock"
 
-#: mixer_strip.cc:199 mixer_strip.cc:2089
+#: mixer_strip.cc:202 mixer_strip.cc:2112
 msgid "Iso"
 msgstr "Iso"
 
-#: mixer_strip.cc:253
+#: mixer_strip.cc:256
 msgid "Mix group"
 msgstr "Bearbeitungsgruppe"
 
-#: mixer_strip.cc:263
+#: mixer_strip.cc:266
 msgid "Trim: "
 msgstr "Anpassen: "
 
-#: mixer_strip.cc:380 rc_option_editor.cc:2829
+#: mixer_strip.cc:383 rc_option_editor.cc:2945
 msgid "Phase Invert"
 msgstr "Phaseninvertierung"
 
-#: mixer_strip.cc:381 rc_option_editor.cc:2830
+#: mixer_strip.cc:384 rc_option_editor.cc:2946
 msgid "Record & Monitor"
 msgstr "Aufnahme & Monitor..."
 
-#: mixer_strip.cc:382 rc_option_editor.cc:2831
+#: mixer_strip.cc:385 rc_option_editor.cc:2947
 msgid "Solo Iso / Lock"
 msgstr "Solo Iso / Sperre"
 
-#: mixer_strip.cc:546
+#: mixer_strip.cc:507
+msgid "Show/Hide Monitoring Section"
+msgstr "Zeige/Verstecke Monitorsektion"
+
+#: mixer_strip.cc:559
 msgid "Enable/Disable MIDI input"
 msgstr "Aktiviert/Deaktiviert MIDI Input"
 
-#: mixer_strip.cc:712
+#: mixer_strip.cc:726
 msgid "Aux"
 msgstr "Aux"
 
-#: mixer_strip.cc:738
+#: mixer_strip.cc:752
 msgid "Snd"
 msgstr "Snd"
 
-#: mixer_strip.cc:809 mixer_strip.cc:912 processor_box.cc:2449
+#: mixer_strip.cc:823 mixer_strip.cc:926 processor_box.cc:2650
 msgid "Not connected to audio engine - no I/O changes are possible"
 msgstr ""
 "Nicht mit Audioengine verbunden - es sind keine Änderungen an Ein-/Ausgängen "
 "möglich"
 
-#: mixer_strip.cc:866 mixer_strip.cc:968
+#: mixer_strip.cc:880 mixer_strip.cc:982
 msgid "Add %1 port"
 msgstr "%1-Port hinzufügen"
 
-#: mixer_strip.cc:873 mixer_strip.cc:975 monitor_section.cc:1315
+#: mixer_strip.cc:887 mixer_strip.cc:989 monitor_section.cc:1342
 msgid "Routing Grid"
 msgstr "Verbindungsraster"
 
-#: mixer_strip.cc:1204
+#: mixer_strip.cc:1218
 msgid "MIDI "
 msgstr "MIDI"
 
-#: mixer_strip.cc:1209
+#: mixer_strip.cc:1223
 msgid "<b>INPUT</b> to %1"
 msgstr "<b>EINGANG</b> zu %1"
 
-#: mixer_strip.cc:1212 monitor_section.cc:1366
+#: mixer_strip.cc:1226 monitor_section.cc:1387
 msgid "<b>OUTPUT</b> from %1"
 msgstr "<b>AUSGANG</b> von %1"
 
-#: mixer_strip.cc:1330 monitor_section.cc:1453
+#: mixer_strip.cc:1344 monitor_section.cc:1474
 msgid "Disconnected"
 msgstr "Getrennt"
 
-#: mixer_strip.cc:1459
+#: mixer_strip.cc:1473
 msgid "*Comments*"
 msgstr "*Kommentare*"
 
-#: mixer_strip.cc:1466
+#: mixer_strip.cc:1480
 msgid "Cmt"
 msgstr "Kmt"
 
-#: mixer_strip.cc:1469
+#: mixer_strip.cc:1483
 msgid "*Cmt*"
 msgstr "*Kmt*"
 
-#: mixer_strip.cc:1475
-msgid "Click to Add/Edit Comments"
-msgstr "Kommentare hinzufügen/ändern"
+#: mixer_strip.cc:1489
+msgid "Click to add/edit comments"
+msgstr "Hier klicken, um einen Kommentar hinzuzufügen"
 
-#: mixer_strip.cc:1519
+#: mixer_strip.cc:1533
 msgid "Grp"
 msgstr "Grp"
 
-#: mixer_strip.cc:1522
+#: mixer_strip.cc:1536
 msgid "~G"
 msgstr "~G"
 
-#: mixer_strip.cc:1551 route_time_axis.cc:572
+#: mixer_strip.cc:1565 route_time_axis.cc:573
 msgid "Color..."
 msgstr "Farbe..."
 
-#: mixer_strip.cc:1553 route_time_axis.cc:574
+#: mixer_strip.cc:1567 route_time_axis.cc:575
 msgid "Comments..."
 msgstr "Kommentare"
 
-#: mixer_strip.cc:1555 route_time_axis.cc:576
+#: mixer_strip.cc:1569 route_time_axis.cc:577
 msgid "Inputs..."
 msgstr "Eingänge..."
 
-#: mixer_strip.cc:1557 route_time_axis.cc:578
+#: mixer_strip.cc:1571 route_time_axis.cc:579
 msgid "Outputs..."
 msgstr "Ausgänge..."
 
-#: mixer_strip.cc:1562
+#: mixer_strip.cc:1576
 msgid "Save As Template..."
 msgstr "Als Vorlage Speichern..."
 
-#: mixer_strip.cc:1568 route_group_dialog.cc:45 route_time_axis.cc:852
+#: mixer_strip.cc:1582 route_group_dialog.cc:45 route_time_axis.cc:853
 msgid "Active"
 msgstr "Aktiv"
 
-#: mixer_strip.cc:1576
+#: mixer_strip.cc:1590
 msgid "Adjust Latency..."
 msgstr "Latenz einstellen..."
 
-#: mixer_strip.cc:1579
+#: mixer_strip.cc:1593
 msgid "Protect Against Denormals"
 msgstr "Schütze vor Denormals"
 
-#: mixer_strip.cc:1585 route_time_axis.cc:591
+#: mixer_strip.cc:1599 route_time_axis.cc:592
 msgid "Remote Control ID..."
 msgstr "ID für Fernsteuerung..."
 
-#: mixer_strip.cc:1885
+#: mixer_strip.cc:1617 route_time_axis.cc:869
+msgid "Duplicate..."
+msgstr "Duplizieren..."
+
+#: mixer_strip.cc:1905
 msgid "Pre"
 msgstr "Pre"
 
-#: mixer_strip.cc:1889
+#: mixer_strip.cc:1909
 msgid "Post"
 msgstr "Post"
 
-#: mixer_strip.cc:1905
+#: mixer_strip.cc:1925
 msgid "Meter|In"
 msgstr "In"
 
-#: mixer_strip.cc:1909
+#: mixer_strip.cc:1929
 msgid "Meter|Pr"
 msgstr "Pr"
 
-#: mixer_strip.cc:1913
+#: mixer_strip.cc:1933
 msgid "Meter|Po"
 msgstr "Po"
 
-#: mixer_strip.cc:1917
+#: mixer_strip.cc:1937
 msgid "Meter|O"
 msgstr "O"
 
-#: mixer_strip.cc:1922
+#: mixer_strip.cc:1942
 msgid "Meter|C"
 msgstr "C"
 
-#: mixer_strip.cc:2070 route_ui.cc:170
+#: mixer_strip.cc:2090 route_ui.cc:181
 msgid "Disk"
 msgstr "Disk"
 
-#: mixer_strip.cc:2082 monitor_section.cc:76
+#: mixer_strip.cc:2092
+msgid "Mon"
+msgstr "Mon"
+
+#: mixer_strip.cc:2105 monitor_section.cc:80
 msgid "AFL"
 msgstr "AFL"
 
-#: mixer_strip.cc:2085 monitor_section.cc:77
+#: mixer_strip.cc:2108 monitor_section.cc:81
 msgid "PFL"
 msgstr "PFL"
 
-#: mixer_strip.cc:2095 meter_strip.cc:387
+#: mixer_strip.cc:2118 meter_strip.cc:387
 msgid "MonitorInput|I"
 msgstr "I"
 
-#: mixer_strip.cc:2096 meter_strip.cc:388
+#: mixer_strip.cc:2119 meter_strip.cc:388
 msgid "MonitorDisk|D"
 msgstr "D"
 
-#: mixer_strip.cc:2108 meter_strip.cc:379 route_time_axis.cc:2729
+#: mixer_strip.cc:2121
+msgid "Mon|O"
+msgstr "O"
+
+#: mixer_strip.cc:2134 meter_strip.cc:379 route_time_axis.cc:2738
 msgid "AfterFader|A"
 msgstr "A"
 
-#: mixer_strip.cc:2111
+#: mixer_strip.cc:2137
 msgid "Prefader|P"
 msgstr "P"
 
-#: mixer_strip.cc:2116
+#: mixer_strip.cc:2142
 msgid "SoloIso|I"
 msgstr "I"
 
-#: mixer_strip.cc:2117
+#: mixer_strip.cc:2143
 msgid "SoloLock|L"
 msgstr "L"
 
-#: mixer_strip.cc:2303
+#: mixer_strip.cc:2348
 msgid "Pre Fader"
 msgstr "Pre Fader"
 
-#: mixer_strip.cc:2304
+#: mixer_strip.cc:2349
 msgid "Post Fader"
 msgstr "Post Fader"
 
-#: mixer_strip.cc:2349 meter_strip.cc:860
+#: mixer_strip.cc:2394 meter_strip.cc:860
 msgid "Change all in Group to %1"
 msgstr "Alle in Gruppe zu %1 ändern"
 
-#: mixer_strip.cc:2351 meter_strip.cc:862
+#: mixer_strip.cc:2396 meter_strip.cc:862
 msgid "Change all to %1"
 msgstr "Alle zu %1 ändern"
 
-#: mixer_strip.cc:2353 meter_strip.cc:864
+#: mixer_strip.cc:2398 meter_strip.cc:864
 msgid "Change same track-type to %1"
 msgstr "Gleichen Spurtyp zu %1 ändern"
 
-#: mixer_ui.cc:130 route_time_axis.cc:829
+#: mixer_ui.cc:134 route_time_axis.cc:830
 msgid "Group"
 msgstr "Gruppe"
 
-#: mixer_ui.cc:1242
+#: mixer_ui.cc:199
+msgid "Favorite Plugins"
+msgstr "Plugin-Favoriten"
+
+#: mixer_ui.cc:1289
 msgid "track display list item for renamed strip not found!"
 msgstr ""
 "Konnte Bezeichnung für umbenannten Kanalzug nicht in der Spurliste finden!"
 
-#: mixer_ui.cc:1336
+#: mixer_ui.cc:1383
 msgid "-all-"
 msgstr "-alle-"
 
-#: mixer_ui.cc:1873
+#: mixer_ui.cc:2034
 msgid "Strips"
 msgstr "Kanalzüge"
 
@@ -8164,7 +8392,7 @@ msgstr "Kanalzüge"
 msgid "Reset Peak"
 msgstr "Peaks zurücksetzen"
 
-#: meter_strip.cc:382 route_time_axis.cc:2733
+#: meter_strip.cc:382 route_time_axis.cc:2742
 msgid "PreFader|P"
 msgstr "P"
 
@@ -8188,67 +8416,67 @@ msgstr "Grande"
 msgid "Venti"
 msgstr "Venti"
 
-#: meter_patterns.cc:82
+#: meter_patterns.cc:84
 msgid "Peak (+6dBFS)"
 msgstr "Spitzenwert (+6dBFS)"
 
-#: meter_patterns.cc:85
+#: meter_patterns.cc:87
 msgid "Peak (0dBFS)"
 msgstr "Spitzenwert (0dBFS)"
 
-#: meter_patterns.cc:88
+#: meter_patterns.cc:90
 msgid "RMS + Peak"
 msgstr "RMS + Spitzenwert"
 
-#: meter_patterns.cc:91
+#: meter_patterns.cc:93
 msgid "IEC1/DIN"
 msgstr "IEC1/DIN"
 
-#: meter_patterns.cc:94
+#: meter_patterns.cc:96
 msgid "IEC1/Nordic"
 msgstr "IEC1/Nordisch"
 
-#: meter_patterns.cc:97
+#: meter_patterns.cc:99
 msgid "IEC2/BBC"
 msgstr "IEC2/BBC"
 
-#: meter_patterns.cc:100
+#: meter_patterns.cc:102
 msgid "IEC2/EBU"
 msgstr "IEC2/EBU"
 
-#: meter_patterns.cc:103
+#: meter_patterns.cc:105
 msgid "K20/RMS"
 msgstr "K20/RMS"
 
-#: meter_patterns.cc:106
+#: meter_patterns.cc:108
 msgid "K14/RMS"
 msgstr "K14/RMS"
 
-#: meter_patterns.cc:109
+#: meter_patterns.cc:111
 msgid "K12/RMS"
 msgstr "K12/RMS"
 
-#: meter_patterns.cc:112
+#: meter_patterns.cc:114
 msgid "VU"
 msgstr "VU"
 
-#: monitor_section.cc:75
+#: monitor_section.cc:79
 msgid "SiP"
 msgstr "SiP"
 
-#: monitor_section.cc:102 route_group_dialog.cc:49
+#: monitor_section.cc:108 route_group_dialog.cc:49
 msgid "Soloing"
 msgstr "Soloing"
 
-#: monitor_section.cc:106
+#: monitor_section.cc:112
 msgid "Isolated"
 msgstr "Isoliert"
 
-#: monitor_section.cc:110
+#: monitor_section.cc:116
 msgid "Auditioning"
 msgstr "Vorhören"
 
-#: monitor_section.cc:120
+#: monitor_section.cc:127
 msgid ""
 "When active, something is solo-isolated.\n"
 "Click to de-isolate everything"
@@ -8256,7 +8484,7 @@ msgstr ""
 "Wenn aktiv, ist etwas auf isoliertes Solo geschalten.\n"
 "Klick, schaltet isoliertes Solo überall aus."
 
-#: monitor_section.cc:123
+#: monitor_section.cc:130
 msgid ""
 "When active, auditioning is active.\n"
 "Click to stop the audition"
@@ -8264,44 +8492,65 @@ msgstr ""
 "Wird beim Vorhören aktiv.\n"
 "Klicken stoppt das Vorhören."
 
-#: monitor_section.cc:140
+#: monitor_section.cc:147
 msgid "Solo controls affect solo-in-place"
 msgstr "Solo-Kontrollelemente beeinflussen solo-in-place"
 
-#: monitor_section.cc:146
+#: monitor_section.cc:153
 msgid "Solo controls toggle after-fader-listen"
 msgstr "Solo-Kontrollelemente schalten AFL um"
 
-#: monitor_section.cc:152
+#: monitor_section.cc:159
 msgid "Solo controls toggle pre-fader-listen"
 msgstr "Solo-Kontrollelemente schalten PFL um"
 
-#: monitor_section.cc:162
-msgid "Gain increase for soloed signals (0dB is normal)"
-msgstr "Erhöhung der Lautstärke für Solosignale (0dB ist üblich)"
+#: monitor_section.cc:165
+msgid "Excl. Solo"
+msgstr "Exkl. Solo"
 
-#: monitor_section.cc:167 monitor_section.cc:196 monitor_section.cc:222
-#: monitor_section.cc:322
-msgid "0 dB"
-msgstr "0 dB"
+#: monitor_section.cc:167
+msgid "Exclusive solo means that only 1 solo is active at a time"
+msgstr ""
+"Exklusives Solo bedeutet, daß nur ein Solo zu einem Zeitpunkt aktiv ist"
 
-#: monitor_section.cc:168
-msgid "3 dB"
+#: monitor_section.cc:174
+msgid "Solo » Mute"
+msgstr "Solo » Mute"
+
+#: monitor_section.cc:176
+msgid ""
+"If enabled, solo will override mute\n"
+"(a soloed & muted track or bus will be audible)"
+msgstr ""
+"Wenn aktiviert, hat Solo Priorität über Mute\n"
+"(eine Spur mit aktiviertem Mute & Solo ist hörbar)"
+
+#: monitor_section.cc:194
+msgid "Gain increase for soloed signals (0dB is normal)"
+msgstr "Erhöhung der Lautstärke für Solosignale (0dB ist üblich)"
+
+#: monitor_section.cc:199 monitor_section.cc:216 monitor_section.cc:234
+#: monitor_section.cc:281
+msgid "0 dB"
+msgstr "0 dB"
+
+#: monitor_section.cc:200
+msgid "3 dB"
 msgstr "3 dB"
 
-#: monitor_section.cc:169
+#: monitor_section.cc:201
 msgid "6 dB"
 msgstr "6 dB"
 
-#: monitor_section.cc:170
+#: monitor_section.cc:202
 msgid "10 dB"
 msgstr "10 dB"
 
-#: monitor_section.cc:176
+#: monitor_section.cc:204
 msgid "Solo Boost"
 msgstr "Solo Boost"
 
-#: monitor_section.cc:191
+#: monitor_section.cc:211
 msgid ""
 "Gain reduction non-soloed signals\n"
 "A value above -inf dB causes \"solo-in-front\""
@@ -8309,120 +8558,99 @@ msgstr ""
 "Reduzierung der Lautstärke für Signale, die nicht Solo geschalten sind.\n"
 "Ein Wert über -inf dB bedeutet \"solo-in-front\""
 
-#: monitor_section.cc:197 monitor_section.cc:224 monitor_section.cc:324
+#: monitor_section.cc:217 monitor_section.cc:236 monitor_section.cc:283
 msgid "-6 dB"
 msgstr "-6 dB"
 
-#: monitor_section.cc:198 monitor_section.cc:225 monitor_section.cc:325
+#: monitor_section.cc:218 monitor_section.cc:237 monitor_section.cc:284
 msgid "-12 dB"
 msgstr "-12 dB"
 
-#: monitor_section.cc:199 monitor_section.cc:226 monitor_section.cc:326
+#: monitor_section.cc:219 monitor_section.cc:238 monitor_section.cc:285
 msgid "-20 dB"
 msgstr "-20 dB"
 
-#: monitor_section.cc:200
+#: monitor_section.cc:220
 msgid "OFF"
 msgstr "OFF"
 
-#: monitor_section.cc:202
+#: monitor_section.cc:222
 msgid "SiP Cut"
 msgstr "SiP Cut"
 
-#: monitor_section.cc:217
+#: monitor_section.cc:229
 msgid "Gain reduction to use when dimming monitor outputs"
 msgstr "Lautstärkereduzierung beim Abschwächen der Monitorausgänge"
 
-#: monitor_section.cc:223 monitor_section.cc:323
+#: monitor_section.cc:235 monitor_section.cc:282
 msgid "-3 dB"
 msgstr "-3 dB"
 
-#: monitor_section.cc:231 monitor_section.cc:289 monitor_section.cc:372
+#: monitor_section.cc:240 monitor_section.cc:255 monitor_section.cc:317
 msgid "Dim"
 msgstr "Dim"
 
-#: monitor_section.cc:241
-msgid "Excl. Solo"
-msgstr "Exkl. Solo"
-
-#: monitor_section.cc:243
-msgid "Exclusive solo means that only 1 solo is active at a time"
-msgstr ""
-"Exklusives Solo bedeutet, daß nur ein Solo zu einem Zeitpunkt aktiv ist"
-
-#: monitor_section.cc:250
-msgid "Solo » Mute"
-msgstr "Solo » Mute"
-
-#: monitor_section.cc:252
-msgid ""
-"If enabled, solo will override mute\n"
-"(a soloed & muted track or bus will be audible)"
-msgstr ""
-"Wenn aktiviert, hat Solo Priorität über Mute\n"
-"(eine Spur mit aktiviertem Mute & Solo ist hörbar)"
-
-#: monitor_section.cc:327
+#: monitor_section.cc:286
 msgid "-30 dB"
 msgstr "-30 dB"
 
-#: monitor_section.cc:341
-msgid "Monitor"
-msgstr "Monitor"
-
-#: monitor_section.cc:380
+#: monitor_section.cc:325
 msgid "Inv"
 msgstr "Inv"
 
-#: monitor_section.cc:784
+#: monitor_section.cc:387
+msgid "Monitor"
+msgstr "Monitor"
+
+#: monitor_section.cc:825
 msgid "Switch monitor to mono"
 msgstr "Monitor auf Mono schalten"
 
-#: monitor_section.cc:787
+#: monitor_section.cc:828
 msgid "Cut monitor"
 msgstr "Monitor stummschalten"
 
-#: monitor_section.cc:790
+#: monitor_section.cc:831
 msgid "Dim monitor"
 msgstr "Monitor abschwächen"
 
-#: monitor_section.cc:793
+#: monitor_section.cc:834
 msgid "Toggle exclusive solo mode"
 msgstr "Exklusives Solo umschalten"
 
-#: monitor_section.cc:799
+#: monitor_section.cc:840
 msgid "Toggle mute overrides solo mode"
 msgstr "Mute-Status hat höhere Priorität als Solo-Modus"
 
-#: monitor_section.cc:811
+#: monitor_section.cc:852
 msgid "Cut monitor channel %1"
 msgstr "Monitorkanal %1 stummschalten"
 
-#: monitor_section.cc:816
+#: monitor_section.cc:857
 msgid "Dim monitor channel %1"
 msgstr "Monitorkanal %1 abschwächen"
 
-#: monitor_section.cc:821
+#: monitor_section.cc:862
 msgid "Solo monitor channel %1"
 msgstr "Monitorkanal %1 Solo"
 
-#: monitor_section.cc:826
+#: monitor_section.cc:867
 msgid "Invert monitor channel %1"
 msgstr "Invertiere Monitorkanal %1"
 
-#: monitor_section.cc:836
+#: monitor_section.cc:877
 msgid "In-place solo"
 msgstr "In-Place Solo"
 
-#: monitor_section.cc:838
+#: monitor_section.cc:879
 msgid "After Fade Listen (AFL) solo"
 msgstr "Solo nach Fader (AFL) abhören"
 
-#: monitor_section.cc:840
+#: monitor_section.cc:881
 msgid "Pre Fade Listen (PFL) solo"
 msgstr "Solo vor Fader (PFL) abhören"
 
-#: monitor_section.cc:1262
+#: monitor_section.cc:1289
 msgid "No session - no I/O changes are possible"
 msgstr "Kein Projekt - es sind keine Änderungen an Ein-/Ausgängen möglich"
 
@@ -8430,22 +8658,22 @@ msgstr "Kein Projekt - es sind keine Änderungen an Ein-/Ausgängen möglich"
 msgid "Monitor output selector"
 msgstr "Auswahl des Monitorausgangs"
 
-#: mono_panner.cc:104 stereo_panner.cc:114
+#: mono_panner.cc:103 stereo_panner.cc:113
 msgid "bypassed"
 msgstr "überbrückt"
 
-#: mono_panner.cc:118
+#: mono_panner.cc:117
 #, c-format
 msgid "L:%3d R:%3d"
 msgstr "L:%3d R:%3d"
 
-#: mono_panner.cc:202 panner2d.cc:277 stereo_panner.cc:251
-#: stereo_panner.cc:274
+#: mono_panner.cc:201 panner2d.cc:276 stereo_panner.cc:250
+#: stereo_panner.cc:273
 msgid "Panner|L"
 msgstr "L"
 
-#: mono_panner.cc:219 panner2d.cc:278 stereo_panner.cc:249
-#: stereo_panner.cc:276
+#: mono_panner.cc:218 panner2d.cc:277 stereo_panner.cc:248
+#: stereo_panner.cc:275
 msgid "Panner|R"
 msgstr "R"
 
@@ -8552,7 +8780,7 @@ msgstr "Regionen normalisieren"
 msgid "Normalize region"
 msgstr "Region normalisieren"
 
-#: normalize_dialog.cc:49 strip_silence_dialog.cc:66
+#: normalize_dialog.cc:49 strip_silence_dialog.cc:67
 msgid "dbFS"
 msgstr "dbFS"
 
@@ -8572,36 +8800,43 @@ msgstr "Normalisieren"
 msgid "Select Note"
 msgstr "Note auswählen"
 
-#: opts.cc:57
+#: opts.cc:61
 msgid "Usage: "
 msgstr "Aufruf:"
 
-#: opts.cc:58
+#: opts.cc:62
 msgid "  [SESSION_NAME]              Name of session to load\n"
 msgstr "  [PROJEKTNAME]                   Name des zu ladenden Projekts\n"
 
-#: opts.cc:59
+#: opts.cc:63
 msgid "  -v, --version               Show version information\n"
 msgstr "  -v, --version                    Versionsinformation ausgeben\n"
 
-#: opts.cc:60
+#: opts.cc:64
 msgid "  -h, --help                  Print this message\n"
 msgstr "  -h, --help                       Diese Hinweise ausgeben\n"
 
-#: opts.cc:61
+#: opts.cc:65
 msgid ""
 "  -a, --no-announcements      Do not contact website for announcements\n"
 msgstr ""
 "  -a, --no-announcements      Webseite nicht für Neuigkeiten kontaktieren\n"
 
-#: opts.cc:62
+#: opts.cc:66
 msgid ""
 "  -b, --bindings              Print all possible keyboard binding names\n"
 msgstr ""
 "  -b, --bindings                   Alle möglichen Tastaturkürzelnamen "
 "ausgeben\n"
 
-#: opts.cc:63
+#: opts.cc:67
+msgid ""
+"  -B, --bypass-plugins        Bypass all plugins in an existing session\n"
+msgstr ""
+"  -B, --bypass-plugins        Alle Plugins in einem existierenden Projekt "
+"deaktivieren\n"
+
+#: opts.cc:68
 msgid ""
 "  -c, --name <name>           Use a specific backend client name, default is "
 "ardour\n"
@@ -8609,14 +8844,14 @@ msgstr ""
 "  -c, --name  name                 Benutze speziellen Backend-Clientnamen, "
 "Voreinstellung: ardour\n"
 
-#: opts.cc:64
+#: opts.cc:69
 msgid ""
 "  -d, --disable-plugins       Disable all plugins in an existing session\n"
 msgstr ""
 "-d, --disable-plugins            Alle Plugins eines bestehenden Projekts "
 "deaktivieren\n"
 
-#: opts.cc:65
+#: opts.cc:70
 msgid ""
 "  -D, --debug <options>       Set debug flags. Use \"-D list\" to see "
 "available options\n"
@@ -8624,41 +8859,41 @@ msgstr ""
 "  -D, --debug <options>       Setze Debug-flags. Verwende \"-D list\" um die "
 "verfügbaren Optionen zu sehen\n"
 
-#: opts.cc:66
+#: opts.cc:71
 msgid "  -n, --no-splash             Do not show splash screen\n"
 msgstr "  -n, --no-splash               Splashscreen nicht anzeigen\n"
 
-#: opts.cc:67
+#: opts.cc:72
 msgid "  -m, --menus file            Use \"file\" to define menus\n"
 msgstr "  -m, --menus file                 Benutze \"file\" für die Menüs\n"
 
-#: opts.cc:68
+#: opts.cc:73
 msgid ""
 "  -N, --new session-name      Create a new session from the command line\n"
 msgstr ""
 "  -N, --new session-name           Erstelle neues Projekt aus der "
 "Kommandozeile\n"
 
-#: opts.cc:69
+#: opts.cc:74
 msgid "  -O, --no-hw-optimizations   Disable h/w specific optimizations\n"
 msgstr ""
 "  -O, --no-hw-optimizations        Hardwarespezifische Optimierungen "
 "deaktivieren\n"
 
-#: opts.cc:70
+#: opts.cc:75
 msgid "  -P, --no-connect-ports      Do not connect any ports at startup\n"
 msgstr ""
 "  -P, --no-connect-ports      beim Programmstart keine Ports verbinden\n"
 
-#: opts.cc:71
+#: opts.cc:76
 msgid "  -S, --sync                  Draw the gui synchronously \n"
 msgstr "  -S, --sync\t                      Zeichne die GUI synchron \n"
 
-#: opts.cc:73
+#: opts.cc:78
 msgid "  -V, --novst                 Do not use VST support\n"
 msgstr "  -V, --novst                      VST-Unterstützung ausschalten\n"
 
-#: opts.cc:75
+#: opts.cc:80
 msgid ""
 "  -E, --save <file>           Load the specified session, save it to <file> "
 "and then quit\n"
@@ -8666,48 +8901,48 @@ msgstr ""
 "  -E, --save <file>           Lädt das angegebene Projekt, speichert es "
 "unter <file> und beendet sich\n"
 
-#: opts.cc:76
+#: opts.cc:81
 msgid "  -C, --curvetest filename    Curve algorithm debugger\n"
 msgstr "  -C, --curvetest filename    Curve algorithm debugger\n"
 
-#: opts.cc:77
+#: opts.cc:82
 msgid "  -k, --keybindings filename  Name of key bindings to load\n"
 msgstr ""
 "  -k, --keybindings dateiname       Dateiname für die Tastaturbelegungen"
 
-#: panner2d.cc:897
+#: panner2d.cc:896
 msgid "Panner (2D)"
 msgstr "Panner (2D)"
 
-#: panner2d.cc:899 panner_ui.cc:400 plugin_ui.cc:458
+#: panner2d.cc:898 panner_ui.cc:402 plugin_ui.cc:458
 msgid "Bypass"
 msgstr "Bypass"
 
-#: panner2d.cc:905
+#: panner2d.cc:904
 msgid "Panner"
 msgstr "Panner"
 
-#: panner_ui.cc:70
+#: panner_ui.cc:72
 msgid "Pan automation mode"
 msgstr "Pan-Automationsmodus"
 
-#: panner_ui.cc:71
+#: panner_ui.cc:73
 msgid "Pan automation type"
 msgstr "Pan-Automationstyp"
 
-#: panner_ui.cc:603
+#: panner_ui.cc:605
 msgid "Manual|M"
 msgstr "M"
 
-#: panner_ui.cc:606
+#: panner_ui.cc:608
 msgid "Play|P"
 msgstr "P"
 
-#: panner_ui.cc:609
+#: panner_ui.cc:611
 msgid "Touch|T"
 msgstr "T"
 
-#: panner_ui.cc:612
+#: panner_ui.cc:614
 msgid "Write|W"
 msgstr "W"
 
@@ -8735,104 +8970,140 @@ msgstr "nicht zugewiesen"
 msgid "Imported"
 msgstr "Importierte"
 
-#: plugin_eq_gui.cc:85 plugin_eq_gui.cc:109
+#: plugin_eq_gui.cc:83 plugin_eq_gui.cc:107
 msgid "dB scale"
 msgstr "dB Skala"
 
-#: plugin_eq_gui.cc:116
+#: plugin_eq_gui.cc:114
 msgid "Show phase"
 msgstr "Zeige Phase"
 
-#: plugin_selector.cc:53 plugin_selector.cc:225
+#: plugin_selector.cc:54 plugin_selector.cc:304
 msgid "Name contains"
 msgstr "Name enthält"
 
-#: plugin_selector.cc:54 plugin_selector.cc:229
+#: plugin_selector.cc:55 plugin_selector.cc:308
 msgid "Type contains"
 msgstr "Typ enthält"
 
-#: plugin_selector.cc:55 plugin_selector.cc:227
+#: plugin_selector.cc:56 plugin_selector.cc:306
 msgid "Category contains"
 msgstr "Kategorie enthält"
 
-#: plugin_selector.cc:56 plugin_selector.cc:249
+#: plugin_selector.cc:57 plugin_selector.cc:328
 msgid "Author contains"
 msgstr "Autor enthält"
 
-#: plugin_selector.cc:57 plugin_selector.cc:251
+#: plugin_selector.cc:58 plugin_selector.cc:330
 msgid "Library contains"
 msgstr "Katalog enthält"
 
-#: plugin_selector.cc:58 plugin_selector.cc:215 plugin_selector.cc:527
+#: plugin_selector.cc:59 plugin_selector.cc:260 plugin_selector.cc:606
 msgid "Favorites only"
 msgstr "nur Favoriten"
 
-#: plugin_selector.cc:59 plugin_selector.cc:219 plugin_selector.cc:527
+#: plugin_selector.cc:60 plugin_selector.cc:264 plugin_selector.cc:606
 msgid "Hidden only"
 msgstr "Nur versteckte"
 
-#: plugin_selector.cc:64
+#: plugin_selector.cc:65
 msgid "Plugin Manager"
 msgstr "Alle Plugins ..."
 
-#: plugin_selector.cc:85
+#: plugin_selector.cc:94
 msgid "Fav"
 msgstr "Fav"
 
-#: plugin_selector.cc:87
+#: plugin_selector.cc:96
 msgid "Available Plugins"
 msgstr "Verfügbare Plugins"
 
-#: plugin_selector.cc:88
+#: plugin_selector.cc:97
 msgid "Type"
 msgstr "Typ"
 
-#: plugin_selector.cc:89
+#: plugin_selector.cc:98
 msgid "Category"
 msgstr "Kategorie"
 
-#: plugin_selector.cc:90
+#: plugin_selector.cc:99
 msgid "Creator"
 msgstr "Ersteller"
 
-#: plugin_selector.cc:91
+#: plugin_selector.cc:100
 msgid "# Audio In"
 msgstr "# Audio In"
 
-#: plugin_selector.cc:92
+#: plugin_selector.cc:101
 msgid "# Audio Out"
 msgstr "# Audio Out"
 
-#: plugin_selector.cc:93
+#: plugin_selector.cc:102
 msgid "# MIDI In"
 msgstr "# MIDI In"
 
-#: plugin_selector.cc:94
+#: plugin_selector.cc:103
 msgid "# MIDI Out"
 msgstr "# MIDI Out"
 
-#: plugin_selector.cc:116
+#: plugin_selector.cc:125
 msgid "Plugins to be connected"
 msgstr "Plugins, die verbunden werden"
 
-#: plugin_selector.cc:129
+#: plugin_selector.cc:138
 msgid "Add a plugin to the effect list"
 msgstr "Plugin zur Effektliste hinzufügen"
 
-#: plugin_selector.cc:133
+#: plugin_selector.cc:142
 msgid "Remove a plugin from the effect list"
 msgstr "Plugin aus der Effektliste entfernen"
 
+#: plugin_selector.cc:154
+msgid "Show Hidden"
+msgstr "Verborgene anzeigen"
+
+#: plugin_selector.cc:156
+msgid "Include hidden plugins in list."
+msgstr "Verborhene Plugins in Liste einbeziehen."
+
+#: plugin_selector.cc:159
+msgid "Instruments"
+msgstr "Instrumente"
+
+#: plugin_selector.cc:161
+msgid "Cycle display of instrument plugins (if any)."
+msgstr "Anzeige von Instrumenten-Plugins umschalten (falls vorhanden)."
+
+#: plugin_selector.cc:164
+msgid "Analyzers"
+msgstr "Analyzer"
+
+#: plugin_selector.cc:166
+msgid "Cycle display of analysis plugins (if any)."
+msgstr "Anzeige von Analyse-Plugins umschalten (falls vorhanden)."
+
 #: plugin_selector.cc:169
+msgid "Utils"
+msgstr "Hilfsmittel"
+
+#: plugin_selector.cc:171
+msgid "Cycle display of utility plugins (if any)."
+msgstr "Anzeige von Utility-Plugins umschalten (falls vorhanden)."
+
+#: plugin_selector.cc:201
+msgid "Filter"
+msgstr "Filter"
+
+#: plugin_selector.cc:214
 msgid "Insert Plugin(s)"
 msgstr "Plugin(s) einfügen"
 
-#: plugin_selector.cc:333 plugin_selector.cc:334 plugin_selector.cc:335
-#: plugin_selector.cc:336
+#: plugin_selector.cc:412 plugin_selector.cc:413 plugin_selector.cc:414
+#: plugin_selector.cc:415
 msgid "variable"
 msgstr "variabel"
 
-#: plugin_selector.cc:486
+#: plugin_selector.cc:565
 msgid ""
 "The plugin \"%1\" could not be loaded\n"
 "\n"
@@ -8842,19 +9113,19 @@ msgstr ""
 "\n"
 "Im Logfenster befinden sich möglicherweise mehr Informationen"
 
-#: plugin_selector.cc:634
+#: plugin_selector.cc:723
 msgid "Favorites"
 msgstr "Favoriten"
 
-#: plugin_selector.cc:636
+#: plugin_selector.cc:725
 msgid "Plugin Manager..."
 msgstr "Plugin Manager..."
 
-#: plugin_selector.cc:640
+#: plugin_selector.cc:729
 msgid "By Creator"
 msgstr "Nach Urheber"
 
-#: plugin_selector.cc:643
+#: plugin_selector.cc:732
 msgid "By Category"
 msgstr "Nach Kategorie"
 
@@ -8922,8 +9193,8 @@ msgstr "Lösche das aktuelle Preset"
 msgid ""
 "Reset parameters to default (if no parameters are in automation play mode)"
 msgstr ""
-"Parameter auf Vorgabewert zurücksetzen (falls keine Parameter im "
-"Automations-Wiedergabemodus sind)"
+"Parameter auf Vorgabewert zurücksetzen (falls keine Parameter im Automations-"
+"Wiedergabemodus sind)"
 
 #: plugin_ui.cc:436
 msgid "Disable signal processing by the plugin"
@@ -8979,77 +9250,85 @@ msgstr "Klicke, um die normale Verwendung von %1 Tastaturkürzeln zu aktivieren"
 msgid "(none)"
 msgstr "(kein)"
 
-#: port_group.cc:337
+#: port_group.cc:338
 msgid "%1 Busses"
 msgstr "%1 Busse"
 
-#: port_group.cc:338
+#: port_group.cc:339
 msgid "%1 Tracks"
 msgstr "%1 Spuren"
 
-#: port_group.cc:339
+#: port_group.cc:340
 msgid "Hardware"
 msgstr "Hardware"
 
-#: port_group.cc:340
+#: port_group.cc:341
 msgid "%1 Misc"
 msgstr "%1 Sonstige"
 
-#: port_group.cc:341
+#: port_group.cc:342
 msgid "Other"
 msgstr "Andere"
 
-#: port_group.cc:432 port_group.cc:433
+#: port_group.cc:434 port_group.cc:435
 msgid "LTC Out"
 msgstr "LTC Out"
 
-#: port_group.cc:436 port_group.cc:437
+#: port_group.cc:438 port_group.cc:439
 msgid "LTC In"
 msgstr "LTC In"
 
-#: port_group.cc:463
+#: port_group.cc:473
 msgid "MTC in"
 msgstr "MTC in"
 
-#: port_group.cc:466
+#: port_group.cc:476
 msgid "MIDI control in"
 msgstr "MIDI control in"
 
-#: port_group.cc:469
+#: port_group.cc:479
 msgid "MIDI clock in"
 msgstr "MIDI clock in"
 
-#: port_group.cc:472
+#: port_group.cc:482
 msgid "MMC in"
 msgstr "MMC in"
 
-#: port_group.cc:476
+#: port_group.cc:486
 msgid "MTC out"
 msgstr "MTC out"
 
-#: port_group.cc:479
+#: port_group.cc:489
 msgid "MIDI control out"
 msgstr "MIDI control out"
 
-#: port_group.cc:482
+#: port_group.cc:492
 msgid "MIDI clock out"
 msgstr "MIDI clock out"
 
-#: port_group.cc:485
+#: port_group.cc:495
 msgid "MMC out"
 msgstr "MMC out"
 
-#: port_group.cc:532
+#: port_group.cc:543
 msgid ":monitor"
 msgstr ":monitor"
 
-#: port_group.cc:544
+#: port_group.cc:559
 msgid "system:"
 msgstr "system:"
 
-#: port_group.cc:545
-msgid "alsa_pcm"
-msgstr "alsa_pcm"
+#: port_group.cc:560
+msgid "alsa_pcm:"
+msgstr "alsa_pcm:"
+
+#: port_group.cc:561
+msgid "alsa_midi:"
+msgstr "alsa_midi:"
+
+#: port_group.cc:566
+msgid "Scene "
+msgstr "Szene"
 
 #: port_insert_ui.cc:39
 msgid "Measure Latency"
@@ -9071,46 +9350,46 @@ msgstr "Kein Signal erkannt"
 msgid "Port Insert "
 msgstr "Port Insert "
 
-#: port_matrix.cc:340 port_matrix.cc:366
+#: port_matrix.cc:341 port_matrix.cc:367
 msgid "<b>Sources</b>"
 msgstr "<b>Quellen</b>"
 
-#: port_matrix.cc:341 port_matrix.cc:367
+#: port_matrix.cc:342 port_matrix.cc:368
 msgid "<b>Destinations</b>"
 msgstr "<b>Ziele</b>"
 
-#: port_matrix.cc:449 port_matrix.cc:457
+#: port_matrix.cc:450 port_matrix.cc:458
 #, c-format
 msgid "Add %s %s"
 msgstr "Füge %s %s hinzu"
 
-#: port_matrix.cc:465
+#: port_matrix.cc:466
 #, c-format
 msgid "Rename '%s'..."
 msgstr "Benenne '%s' um..."
 
-#: port_matrix.cc:481
+#: port_matrix.cc:482
 msgid "Remove all"
 msgstr "Alle löschen"
 
-#: port_matrix.cc:501 port_matrix.cc:513
+#: port_matrix.cc:502 port_matrix.cc:514
 #, c-format
 msgid "%s all"
 msgstr "%s alle"
 
-#: port_matrix.cc:536
+#: port_matrix.cc:537
 msgid "Rescan"
 msgstr "Aktualisieren"
 
-#: port_matrix.cc:538
+#: port_matrix.cc:539
 msgid "Show individual ports"
 msgstr "Individuelle Ports anzeigen"
 
-#: port_matrix.cc:544
+#: port_matrix.cc:545
 msgid "Flip"
 msgstr "Drehen"
 
-#: port_matrix.cc:731
+#: port_matrix.cc:732
 msgid ""
 "It is not possible to add a port here, as the first processor in the track "
 "or buss cannot support the new configuration."
@@ -9118,15 +9397,15 @@ msgstr ""
 "Hier kann kein Port hinzugefügt werden, da der erste Prozessor der Spur/des "
 "Busses die neue Portanzahl nicht unterstützt."
 
-#: port_matrix.cc:734
+#: port_matrix.cc:735
 msgid "Cannot add port"
 msgstr "Kann Port nicht hinzufügen"
 
-#: port_matrix.cc:756
+#: port_matrix.cc:757
 msgid "Port removal not allowed"
 msgstr "Entfernen des Ports nicht erlaubt"
 
-#: port_matrix.cc:757
+#: port_matrix.cc:758
 msgid ""
 "This port cannot be removed.\n"
 "Either the first plugin in the track or buss cannot accept\n"
@@ -9137,17 +9416,17 @@ msgstr ""
 "die neue Anzahl an Eingängen nicht verarbeiten, oder das \n"
 "letzte Plugin hat mehr Ausgänge."
 
-#: port_matrix.cc:974
+#: port_matrix.cc:975
 #, c-format
 msgid "Remove '%s'"
 msgstr "Lösche '%s'"
 
-#: port_matrix.cc:989
+#: port_matrix.cc:990
 #, c-format
 msgid "%s all from '%s'"
 msgstr "%s alle von '%s'"
 
-#: port_matrix.cc:1055 transform_dialog.cc:62
+#: port_matrix.cc:1056 transform_dialog.cc:62
 msgid "channel"
 msgstr "Kanal"
 
@@ -9159,15 +9438,15 @@ msgstr "Es gibt keine Ports, zu denen verbunden werden kann."
 msgid "There are no %1 ports to connect."
 msgstr "Es gibt keine %1 Ports, zu denen verbunden werden kann."
 
-#: processor_box.cc:150
+#: processor_box.cc:162
 msgid "Send"
 msgstr "Send"
 
-#: processor_box.cc:152
+#: processor_box.cc:164
 msgid "Return"
 msgstr "Return"
 
-#: processor_box.cc:310
+#: processor_box.cc:353
 msgid ""
 "\n"
 "This mono plugin has been replicated %1 times."
@@ -9175,17 +9454,17 @@ msgstr ""
 "\n"
 "Dieses Mono-Plugin wurde %1 mal repliziert."
 
-#: processor_box.cc:314
+#: processor_box.cc:357
 msgid ""
 "<b>%1</b>\n"
 "Double-click to show GUI.\n"
-"Alt+double-click to show generic GUI.%2"
+"%2+double-click to show generic GUI.%3"
 msgstr ""
 "<b>%1</b>\n"
 "Doppelklick, um GUI zu zeigen.\n"
-"Alt+Doppelklick, um einfaches GUI zu zeigen.%2"
+"%2+Doppelklick , um einfaches GUI zu zeigen.%3"
 
-#: processor_box.cc:317
+#: processor_box.cc:360
 msgid ""
 "<b>%1</b>\n"
 "Double-click to show generic GUI.%2"
@@ -9193,32 +9472,42 @@ msgstr ""
 "<b>%1</b>\n"
 "Doppelklick, um einfaches GUI zu zeigen.%2"
 
-#: processor_box.cc:361
+#: processor_box.cc:366
+msgid ""
+"<b>%1</b>\n"
+"The Plugin is not available on this system\n"
+"and has been replaced by a stub."
+msgstr ""
+"<b>%1</b>\n"
+"Das Plugin ist auf diesem System nicht verfügbar\n"
+"und wurde durch einen Platzhalter ersetzt."
+
+#: processor_box.cc:409
 #, c-format
 msgid "(%1x1) "
 msgstr "(%1x1) "
 
-#: processor_box.cc:437
+#: processor_box.cc:485
 msgid "Show All Controls"
 msgstr "Alle Regler zeigen"
 
-#: processor_box.cc:441
+#: processor_box.cc:489
 msgid "Hide All Controls"
 msgstr "Alle Regler verbergen"
 
-#: processor_box.cc:475
+#: processor_box.cc:523
 msgid "Link panner controls"
 msgstr "Panner-Elemente verknüpfen"
 
-#: processor_box.cc:573
+#: processor_box.cc:630
 msgid "on"
 msgstr "an"
 
-#: processor_box.cc:573 rc_option_editor.cc:2862 rc_option_editor.cc:2876
+#: processor_box.cc:630 rc_option_editor.cc:2978 rc_option_editor.cc:2992
 msgid "off"
 msgstr "Aus"
 
-#: processor_box.cc:1021
+#: processor_box.cc:1100
 msgid ""
 "Right-click to add/remove/edit\n"
 "plugins,inserts,sends and more"
@@ -9226,15 +9515,25 @@ msgstr ""
 "Rechtsklick, um Plugins, Inserts, Sends etc.\n"
 "hinzuzufügen/zu editieren/zu löschen"
 
-#: processor_box.cc:1495 processor_box.cc:1870
+#: processor_box.cc:1202
+msgid ""
+"Adding the given processor(s) failed probably,\n"
+"because the I/O configuration of the plugins could\n"
+"not match the configuration of this track."
+msgstr ""
+"Das Hinzufügen des gegebenen Prozessors ist vermutlich misslungen,\n"
+"da die E/A-Konfiguration der Plugins nicht der Konfiguration dieser \n"
+"Spur angepasst werden konnte."
+
+#: processor_box.cc:1669 processor_box.cc:2055
 msgid "Plugin Incompatibility"
 msgstr "Plugin-Inkompatibilität"
 
-#: processor_box.cc:1498
+#: processor_box.cc:1672
 msgid "You attempted to add the plugin \"%1\" in slot %2.\n"
 msgstr "Sie haben versucht, das Plugin \"%1\" im Einschub %2 hinzuzufügen.\n"
 
-#: processor_box.cc:1504
+#: processor_box.cc:1678
 msgid ""
 "\n"
 "This plugin has:\n"
@@ -9242,19 +9541,19 @@ msgstr ""
 "\n"
 "Dieses Plugin hat:\n"
 
-#: processor_box.cc:1507
+#: processor_box.cc:1681
 msgid "\t%1 MIDI input\n"
 msgid_plural "\t%1 MIDI inputs\n"
 msgstr[0] "\t%1 MIDI Eingang\n"
 msgstr[1] "\t%1 MIDI Eingänge\n"
 
-#: processor_box.cc:1511
+#: processor_box.cc:1685
 msgid "\t%1 audio input\n"
 msgid_plural "\t%1 audio inputs\n"
 msgstr[0] "\t%1 Audio-Eingang\n"
 msgstr[1] "\t%1 Audio-Eingänge\n"
 
-#: processor_box.cc:1514
+#: processor_box.cc:1688
 msgid ""
 "\n"
 "but at the insertion point, there are:\n"
@@ -9262,19 +9561,19 @@ msgstr ""
 "\n"
 "aber am Einfügepunkt gibt es:\n"
 
-#: processor_box.cc:1517
+#: processor_box.cc:1691
 msgid "\t%1 MIDI channel\n"
 msgid_plural "\t%1 MIDI channels\n"
 msgstr[0] "\t%1 MIDI-Kanal\n"
 msgstr[1] "\t%1 MIDI-Kanäle\n"
 
-#: processor_box.cc:1521
+#: processor_box.cc:1695
 msgid "\t%1 audio channel\n"
 msgid_plural "\t%1 audio channels\n"
 msgstr[0] "\t%1 Audio-Kanal\n"
 msgstr[1] "\t%1 Audio-Kanäle\n"
 
-#: processor_box.cc:1524
+#: processor_box.cc:1698
 msgid ""
 "\n"
 "%1 is unable to insert this plugin here.\n"
@@ -9282,11 +9581,11 @@ msgstr ""
 "\n"
 "%1 kann dieses Plugin hier nicht einfügen.\n"
 
-#: processor_box.cc:1561
+#: processor_box.cc:1735
 msgid "Cannot set up new send: %1"
 msgstr "Kann keinen neuen Send erstellen: %1"
 
-#: processor_box.cc:1873
+#: processor_box.cc:2058
 msgid ""
 "You cannot reorder these plugins/sends/inserts\n"
 "in that way because the inputs and\n"
@@ -9296,21 +9595,21 @@ msgstr ""
 "nicht auf diese Weise verändern, sonst würden\n"
 "die Ein-/Ausgänge nicht mehr richtig funktionieren."
 
-#: processor_box.cc:2057
+#: processor_box.cc:2258
 msgid "Rename Processor"
 msgstr "Prozessor umbenennen"
 
-#: processor_box.cc:2088
+#: processor_box.cc:2289
 msgid "At least 100 IO objects exist with a name like %1 - name not changed"
 msgstr ""
 "Es gibt mindestens 100 E/A-Objekte mit einem Namen wie %1 - Name nicht "
 "geändert"
 
-#: processor_box.cc:2226
+#: processor_box.cc:2427
 msgid "plugin insert constructor failed"
 msgstr "Einfügen des Plugins gescheitert"
 
-#: processor_box.cc:2237
+#: processor_box.cc:2438
 msgid ""
 "Copying the set of processors on the clipboard failed,\n"
 "probably because the I/O configuration of the plugins\n"
@@ -9320,7 +9619,7 @@ msgstr ""
 "kopieren, vermutlich weil die E/A Konfiguration der Plugins\n"
 "nicht mit der dieser Spur übereinstimmt."
 
-#: processor_box.cc:2283
+#: processor_box.cc:2484
 msgid ""
 "Do you really want to remove all processors from %1?\n"
 "(this cannot be undone)"
@@ -9328,15 +9627,15 @@ msgstr ""
 "Wollen Sie wirklich alle Prozessoren von %1 entfernen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: processor_box.cc:2287 processor_box.cc:2312
+#: processor_box.cc:2488 processor_box.cc:2513
 msgid "Yes, remove them all"
 msgstr "Ja, alle löschen"
 
-#: processor_box.cc:2289 processor_box.cc:2314
+#: processor_box.cc:2490 processor_box.cc:2515
 msgid "Remove processors"
 msgstr "Prozessoren entfernen"
 
-#: processor_box.cc:2304
+#: processor_box.cc:2505
 msgid ""
 "Do you really want to remove all pre-fader processors from %1?\n"
 "(this cannot be undone)"
@@ -9344,7 +9643,7 @@ msgstr ""
 "Wollen Sie wirklich alle Pre-Fader-Prozessoren von %1 entfernen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: processor_box.cc:2307
+#: processor_box.cc:2508
 msgid ""
 "Do you really want to remove all post-fader processors from %1?\n"
 "(this cannot be undone)"
@@ -9352,59 +9651,59 @@ msgstr ""
 "Wollen Sie wirklich alle Post-Fader-Prozessoren von %1 entfernen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: processor_box.cc:2495
+#: processor_box.cc:2696
 msgid "New Plugin"
 msgstr "Plugin einfügen"
 
-#: processor_box.cc:2498
+#: processor_box.cc:2699
 msgid "New Insert"
 msgstr "Insert einfügen"
 
-#: processor_box.cc:2501
+#: processor_box.cc:2702
 msgid "New External Send ..."
 msgstr "Neuer externer Send..."
 
-#: processor_box.cc:2505
+#: processor_box.cc:2706
 msgid "New Aux Send ..."
 msgstr "Neuer Aux-Send..."
 
-#: processor_box.cc:2508
+#: processor_box.cc:2709
 msgid "Send Options"
 msgstr "Send Optionen"
 
-#: processor_box.cc:2510
+#: processor_box.cc:2711
 msgid "Clear (all)"
 msgstr "Leeren (alle)"
 
-#: processor_box.cc:2512
+#: processor_box.cc:2713
 msgid "Clear (pre-fader)"
 msgstr "Leeren (Pre-Fader)"
 
-#: processor_box.cc:2514
+#: processor_box.cc:2715
 msgid "Clear (post-fader)"
 msgstr "Leeren (Post-Fader)"
 
-#: processor_box.cc:2540
+#: processor_box.cc:2737
 msgid "Activate All"
 msgstr "Alle aktivieren"
 
-#: processor_box.cc:2542
+#: processor_box.cc:2739
 msgid "Deactivate All"
 msgstr "Alle deaktivieren"
 
-#: processor_box.cc:2544
+#: processor_box.cc:2741
 msgid "A/B Plugins"
 msgstr "A/B Plugins"
 
-#: processor_box.cc:2553
+#: processor_box.cc:2750
 msgid "Edit with generic controls..."
 msgstr "Mit einfachen Kontrollelementen editieren..."
 
-#: processor_box.cc:2856
+#: processor_box.cc:3053
 msgid "%1: %2 (by %3)"
 msgstr "%1: %2 (von %3)"
 
-#: processor_box.cc:2858
+#: processor_box.cc:3055
 msgid "%1 (by %2)"
 msgstr "%1 (von %2)"
 
@@ -9456,197 +9755,280 @@ msgstr "Notenanfang einrasten an"
 msgid "Snap note end"
 msgstr "Notenende einrasten an"
 
-#: rc_option_editor.cc:80
-msgid "Click audio file:"
-msgstr "Audiodatei für Klick"
-
-#: rc_option_editor.cc:83 rc_option_editor.cc:90
+#: rc_option_editor.cc:81 rc_option_editor.cc:82
 msgid "Browse..."
 msgstr "Durchsuchen..."
 
 #: rc_option_editor.cc:87
+msgid "Emphasis on first beat:"
+msgstr "Betonung auf erstem Schlag:"
+
+#: rc_option_editor.cc:93
+msgid "Use default Click:"
+msgstr "Benutze voreingestellten Klick:"
+
+#: rc_option_editor.cc:99
+msgid "Click audio file:"
+msgstr "Audiodatei für Klick"
+
+#: rc_option_editor.cc:106
 msgid "Click emphasis audio file:"
 msgstr "Audiodatei für Klick-Betonung"
 
-#: rc_option_editor.cc:119
+#: rc_option_editor.cc:152
 msgid "Choose Click"
 msgstr "Click auswählen"
 
-#: rc_option_editor.cc:142
+#: rc_option_editor.cc:175
 msgid "Choose Click Emphasis"
 msgstr "Click-Betonung auswählen"
 
-#: rc_option_editor.cc:173
+#: rc_option_editor.cc:236
 msgid "Limit undo history to"
 msgstr "Limitiere Aktionsliste auf"
 
-#: rc_option_editor.cc:174
+#: rc_option_editor.cc:237
 msgid "Save undo history of"
 msgstr "Speichere Aktionsliste von"
 
-#: rc_option_editor.cc:183 rc_option_editor.cc:190
+#: rc_option_editor.cc:246 rc_option_editor.cc:253
 msgid "commands"
 msgstr "Aktionen"
 
-#: rc_option_editor.cc:333
+#: rc_option_editor.cc:376
+msgid ""
+"\n"
+"Changes to this setting will only persist after your project has been saved."
+msgstr ""
+"\n"
+"Änderungen dieser Einstellung werden nur durch Speichern des Projekts "
+"dauerhaft übernommen."
+
+#: rc_option_editor.cc:387 rc_option_editor.cc:449
+msgid "<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"
+msgstr "<b>Empfohlene Einstellung: %1 + Taste 3 (rechte Maustaste)</b>%2"
+
+#: rc_option_editor.cc:401
 msgid "Select Keyboard layout:"
 msgstr "Tastaturlayout wählen:"
 
-#: rc_option_editor.cc:352
+#: rc_option_editor.cc:420
 msgid "When Clicking:"
 msgstr "Bei Klick:"
 
-#: rc_option_editor.cc:359
+#: rc_option_editor.cc:427
 msgid "Edit using:"
 msgstr "Bearbeiten mit:"
 
-#: rc_option_editor.cc:365 rc_option_editor.cc:394 rc_option_editor.cc:423
+#: rc_option_editor.cc:433 rc_option_editor.cc:463 rc_option_editor.cc:493
 msgid "+ button"
 msgstr "+ Maustaste"
 
-#: rc_option_editor.cc:388
+#: rc_option_editor.cc:457
 msgid "Delete using:"
 msgstr "Entfernen mit:"
 
-#: rc_option_editor.cc:417
+#: rc_option_editor.cc:479
+msgid "<b>Recommended Setting: %1 + button 1 (left mouse button)</b>%2"
+msgstr "<b>Empfohlene Einstellung: %1 + Taste 1 (linke Maustaste)</b>%2"
+
+#: rc_option_editor.cc:487
 msgid "Insert note using:"
 msgstr "Note einfügen:"
 
-#: rc_option_editor.cc:435
+#: rc_option_editor.cc:505
 msgid "When Beginning a Drag:"
 msgstr "Bei Mauszieh-Beginn:"
 
-#: rc_option_editor.cc:453
+#: rc_option_editor.cc:516 rc_option_editor.cc:543 rc_option_editor.cc:576
+#: rc_option_editor.cc:597 rc_option_editor.cc:641 rc_option_editor.cc:674
+#: rc_option_editor.cc:700 rc_option_editor.cc:728 rc_option_editor.cc:757
+#: rc_option_editor.cc:779
+msgid "<b>Recommended Setting: %1</b>%2"
+msgstr "<b>Empfohlene Einstellung: %1</b>%2"
+
+#: rc_option_editor.cc:530
 msgid "Copy items using:"
 msgstr "Kopiere Objekte mittels:"
 
-#: rc_option_editor.cc:473
+#: rc_option_editor.cc:557
 msgid "Constrain drag using:"
 msgstr "Beschränke Mausziehen mittels:"
 
-#: rc_option_editor.cc:481
+#: rc_option_editor.cc:565
 msgid "When Beginning a Trim:"
 msgstr "Bei Beginn einer Anpassung (Trim):"
 
-#: rc_option_editor.cc:499
+#: rc_option_editor.cc:584
 msgid "Trim contents using:"
 msgstr "Inhalte anpassen mittels:"
 
-#: rc_option_editor.cc:519
+#: rc_option_editor.cc:605
 msgid "Anchored trim using:"
 msgstr "Verankertes Anpassen mittels:"
 
-#: rc_option_editor.cc:562
+#: rc_option_editor.cc:649
 msgid "Resize notes relatively using:"
 msgstr "Relative Notenlängenänderung mittels:"
 
-#: rc_option_editor.cc:571
+#: rc_option_editor.cc:658
 msgid "While Dragging:"
 msgstr "Währens Mausziehens:"
 
-#: rc_option_editor.cc:589
+#: rc_option_editor.cc:682
 msgid "Ignore snap using:"
 msgstr "Einrasten ignorieren mittels:"
 
-#: rc_option_editor.cc:609
+#: rc_option_editor.cc:708
 msgid "Snap relatively using:"
 msgstr "Relativ Einrasten mittels:"
 
-#: rc_option_editor.cc:617
+#: rc_option_editor.cc:716
 msgid "While Trimming:"
 msgstr "Während des Anpassens:"
 
-#: rc_option_editor.cc:635
-msgid "Resize overlaped regions using:"
+#: rc_option_editor.cc:736
+msgid "Resize overlapped regions using:"
 msgstr "Längenänderung überlappender Regionen mittels:"
 
-#: rc_option_editor.cc:643
+#: rc_option_editor.cc:744
 msgid "While Dragging Control Points:"
 msgstr "Beim Mausziehen von Kontrollpunkten:"
 
-#: rc_option_editor.cc:661
+#: rc_option_editor.cc:765
 msgid "Fine adjust using:"
 msgstr "Feinjustierung mittels:"
 
-#: rc_option_editor.cc:681
+#: rc_option_editor.cc:787
 msgid "Push points using:"
 msgstr "Punkte \"stoßen\" mittels:"
 
-#: rc_option_editor.cc:922
+#: rc_option_editor.cc:1027
 msgid "GUI and Font scaling:"
 msgstr "GUI- und Zeichensatzskalierung:"
 
-#: rc_option_editor.cc:925
+#: rc_option_editor.cc:1030
 msgid "Default"
 msgstr "Voreinstellung"
 
-#: rc_option_editor.cc:951
+#: rc_option_editor.cc:1056
 msgid "Adjusting the scale require an application restart to re-layout."
 msgstr ""
 "Änderungen an der Skalierung verlangen einen Neustart des Programms, um das "
 "Layout anzupassen."
 
-#: rc_option_editor.cc:992
+#: rc_option_editor.cc:1098
+msgid "∞"
+msgstr "∞"
+
+#: rc_option_editor.cc:1099
+msgid "30 sec"
+msgstr "30 sec"
+
+#: rc_option_editor.cc:1100
+msgid "1 min"
+msgstr "1 min"
+
+#: rc_option_editor.cc:1101
+msgid "2 mins"
+msgstr "2 mins"
+
+#: rc_option_editor.cc:1102
+msgid "3 mins"
+msgstr "3 mins"
+
+#: rc_option_editor.cc:1103
+msgid "4 mins"
+msgstr "4 mins"
+
+#: rc_option_editor.cc:1104
+msgid "5 mins"
+msgstr "5 mins"
+
+#: rc_option_editor.cc:1107
+msgid ""
+"Specify the default timeout for plugin instantiation. Plugins that require "
+"more time to load will be blacklisted. A value of 0 disables the timeout."
+msgstr ""
+"Geben Sie die Voreinstellung für das Timeout bei der Plugin-Instanzierung "
+"an. Plugins, die mehr Zeit benötigen, um zu laden, werden auf die schwarze "
+"Liste gesetzt. Ein Wert von 0 deaktiviert das Timeout."
+
+#: rc_option_editor.cc:1109
+msgid "Scan Time Out:"
+msgstr "Scan-Timeout:"
+
+#: rc_option_editor.cc:1157
 msgid "Waveform Clip Level (dBFS):"
 msgstr "Wellenform Clipping-Wert (dBFS):"
 
-#: rc_option_editor.cc:1046
+#: rc_option_editor.cc:1210
 msgid "Small sessions (4-16 tracks)"
 msgstr "Kleine Projekte (4-16 Spuren)"
 
-#: rc_option_editor.cc:1047
+#: rc_option_editor.cc:1211
 msgid "Medium sessions (16-64 tracks)"
 msgstr "Mittlere Projekte (16 - 64 Spuren)"
 
-#: rc_option_editor.cc:1048
+#: rc_option_editor.cc:1212
 msgid "Large sessions (64+ tracks)"
 msgstr "Große Projekte (64+ Spuren)"
 
-#: rc_option_editor.cc:1049
+#: rc_option_editor.cc:1213
 msgid "Custom (set by sliders below)"
 msgstr "Benutzerdefiniert (setze über untere Schieberegler)"
 
-#: rc_option_editor.cc:1053 export_video_dialog.cc:168
+#: rc_option_editor.cc:1217 export_video_dialog.cc:167
 msgid "Preset:"
 msgstr "Preset:"
 
-#: rc_option_editor.cc:1065
+#: rc_option_editor.cc:1229
 msgid "Playback (seconds of buffering):"
 msgstr "Wiedergabe (gepufferte Sekunden):"
 
-#: rc_option_editor.cc:1078
+#: rc_option_editor.cc:1242
 msgid "Recording (seconds of buffering):"
 msgstr "Aufnahme (gepufferte Sekunden):"
 
-#: rc_option_editor.cc:1156
+#: rc_option_editor.cc:1320
 msgid "programming error: unknown buffering preset string, index = %1"
 msgstr ""
 "Programmierfehler: unbekannte Zeichenkette für Puffer-Voreinstellung, index  "
 "= %1"
 
-#: rc_option_editor.cc:1188
+#: rc_option_editor.cc:1352
 msgid "Control Surface Protocol"
 msgstr "Eingabegeräteprotokoll"
 
-#: rc_option_editor.cc:1197
-msgid "Double-click on a name to edit settings for an enabled protocol"
+#: rc_option_editor.cc:1366
+msgid ""
+"Click to edit the settings for selected protocol ( it must be ENABLED "
+"first ):"
 msgstr ""
-"Doppelklick auf einen Namen editiert Einstellungen für ein aktiviertes "
-"Protokoll"
+"Klicken, um die Einstellungen für das gewählte Protokoll zu bearbeiten (erst "
+"muss es AKTIVIERT werden):"
 
-#: rc_option_editor.cc:1354
+#: rc_option_editor.cc:1370
+msgid "Show Protocol Settings"
+msgstr "Protokolleinstellungen anzeigen"
+
+#: rc_option_editor.cc:1493
+msgid "Configuration"
+msgstr "Konfiguration"
+
+#: rc_option_editor.cc:1546
 msgid "Show Video Export Info before export"
 msgstr "Zeige Video-Exportinformationen vor dem Exportieren"
 
-#: rc_option_editor.cc:1355
+#: rc_option_editor.cc:1547
 msgid "Show Video Server Startup Dialog"
 msgstr "Zeige den Videoserver-Startdialog"
 
-#: rc_option_editor.cc:1356
+#: rc_option_editor.cc:1548
 msgid "Advanced Setup (remote video server)"
 msgstr "Ausführliche Einrichtung (entfernter Videoserver)"
 
-#: rc_option_editor.cc:1364
+#: rc_option_editor.cc:1556
 msgid ""
 "<b>When enabled</b> you can speficify a custom video-server URL and docroot. "
 "- Do not enable this option unless you know what you are doing."
@@ -9655,11 +10037,11 @@ msgstr ""
 "für den Videoserver eingeben. - Aktivieren Sie diese Option nur, wenn Sie "
 "wissen, was Sie tun."
 
-#: rc_option_editor.cc:1366
+#: rc_option_editor.cc:1558
 msgid "Video Server URL:"
 msgstr "Videoserver URL:"
 
-#: rc_option_editor.cc:1371
+#: rc_option_editor.cc:1563
 msgid ""
 "Base URL of the video-server including http prefix. This is usually 'http://"
 "hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when "
@@ -9669,11 +10051,11 @@ msgstr ""
 "hostname.example.org:1554/' und ist auf 'http://localhost:1554/' "
 "voreingestellt, wenn der Videoserver lokal läuft"
 
-#: rc_option_editor.cc:1373
+#: rc_option_editor.cc:1565
 msgid "Video Folder:"
 msgstr "Videoordner:"
 
-#: rc_option_editor.cc:1378
+#: rc_option_editor.cc:1570
 msgid ""
 "Local path to the video-server document-root. Only files below this "
 "directory will be accessible by the video-server. If the server run on a "
@@ -9688,7 +10070,7 @@ msgstr ""
 "werden, falls es nicht zugänglich ist. Wird für den lokalen Videomonitor und "
 "die Dateisuche beim Öffnen/Hinzufügen einer Videodatei benutzt."
 
-#: rc_option_editor.cc:1385
+#: rc_option_editor.cc:1577
 msgid ""
 "<b>When enabled</b> an information window with details is displayed before "
 "the video-export dialog."
@@ -9696,216 +10078,98 @@ msgstr ""
 "<b>Wenn aktiviert</b> , wird vor dem Videoexport-Dialog ein "
 "Informationsfenster mit Details angezeigt."
 
-#: rc_option_editor.cc:1390
+#: rc_option_editor.cc:1582
 msgid ""
 "<b>When enabled</b> the video server is never launched automatically without "
 "confirmation"
 msgstr ""
 "<b>Wenn aktiviert</b>, wird der Videoserver nie ohne Bestätigung gestartet"
 
-#: rc_option_editor.cc:1473
-msgid "Always Display Plugin Scan Progress"
-msgstr "Plugin Scan-Fortschritt immer anzeigen"
-
-#: rc_option_editor.cc:1474
-msgid "Scan for [new] VST Plugins on Application Start"
-msgstr "Bei Programmstart nach [neuen] VST Plugins scannen"
-
-#: rc_option_editor.cc:1475
-msgid "Scan for AudioUnit Plugins on Application Start"
-msgstr "Bei Programmstart nach AudioUnit Plugins scannen"
-
-#: rc_option_editor.cc:1476
-msgid "Verbose Plugin Scan"
-msgstr "Gesprächiger Plugin-Scan"
-
-#: rc_option_editor.cc:1487
-msgid "General"
-msgstr "Allgemein"
-
-#: rc_option_editor.cc:1493 startup.cc:349
-msgid "Scan for Plugins"
-msgstr "Scanne nach Plugins"
-
-#: rc_option_editor.cc:1500
-msgid ""
-"<b>When enabled</b> a popup window showing plugin scan progress is displayed "
-"for indexing (cache load) and discovery (detect new plugins)"
-msgstr ""
-"<b>Wenn aktiviert,</b> wird ein Popupfenster dargestellt, um Plugin Scan-"
-"Fortschritt, Indizierung(Laden des Cace) und Entdeckung (neue Plugins "
-"finden) anzuzeigen"
-
-#: rc_option_editor.cc:1507
-msgid ""
-"Specify the default timeout for plugin instantiation in 1/10 seconds. "
-"Plugins that require more time to load will be blacklisted. A value of 0 "
-"disables the timeout."
-msgstr ""
-"Geben Sie die Voreinstellung für das Timeout bei der Plugin-Instanzierung in "
-"1/10 Sekunden an. Plugins, die mehr Zeit benötigen um zu laden, werden auf "
-"die schwarze Liste gesetzt. Ein Wert von 0 deaktiviert das Timeout."
-
-#: rc_option_editor.cc:1509
-msgid "Scan Time Out [deciseconds]"
-msgstr "Scan-Timeout [Zehntelsekunden]"
-
-#: rc_option_editor.cc:1517
-msgid "VST"
-msgstr "VST"
-
-#: rc_option_editor.cc:1523
-msgid "Clear VST Cache"
-msgstr "VST Cache leeren"
-
-#: rc_option_editor.cc:1527
-msgid "Clear VST Blacklist"
-msgstr "VST Blacklist leeren"
-
-#: rc_option_editor.cc:1535
-msgid ""
-"<b>When enabled</b> new VST plugins are searched, tested and added to the "
-"cache index on application start. When disabled new plugins will only be "
-"available after triggering a 'Scan' manually"
-msgstr ""
-"<b>Wenn aktiviert<b>, werden bei Programmstart neue VST Plugins gesucht, "
-"getestet und dem Cache-Index hinzugefügt. Wenn nicht aktiviert, werden neue "
-"Plugins nur nach einem manuellen Scan verfügbar sein"
-
-#: rc_option_editor.cc:1538
-msgid "Linux VST Path:"
-msgstr "Linux VST Pfad:"
-
-#: rc_option_editor.cc:1545
-msgid "Windows VST Path:"
-msgstr "Windows VST Pfad:"
-
-#: rc_option_editor.cc:1554
-msgid ""
-"<b>When enabled</b> additional information for every plugin is added to the "
-"Log Window."
-msgstr ""
-"<b>Wenn aktiviert</b>, wird zusätzliche Information für jedes Plugin ins "
-"Logfenster geschrieben."
-
-#: rc_option_editor.cc:1560
-msgid "Audio Unit"
-msgstr "Audio Unit"
-
-#: rc_option_editor.cc:1569
-msgid ""
-"<b>When enabled</b> Audio Unit Plugins are discovered on application start. "
-"When disabled AU plugins will only be available after triggering a 'Scan' "
-"manually. The first successful scan will enable AU auto-scan, Any crash "
-"during plugin discovery will disable it."
-msgstr ""
-"<b>Wenn aktiviert<b>, werden bei Programmstart AudioUnit Plugins entdeckt. "
-"Wenn nicht aktiviert, werden neue Plugins nur nach einem manuellen Scan "
-"verfügbar sein. Der erste erfolgreiche Scan wird weitere automatische AU-"
-"Scans aktivieren, ein Crash während der Pluginentdeckung wird sie "
-"deaktivieren."
-
-#: rc_option_editor.cc:1572
-msgid "Clear AU Cache"
-msgstr "AU Cache leeren"
-
-#: rc_option_editor.cc:1576
-msgid "Clear AU Blacklist"
-msgstr "AU Blacklist leeren"
-
-#: rc_option_editor.cc:1670
-msgid "Set Windows VST Search Path"
-msgstr "Windows VST Suchpfad setzen"
-
-#: rc_option_editor.cc:1685
-msgid "Set Linux VST Search Path"
-msgstr "Linux VST Suchpfad setzen"
-
-#: rc_option_editor.cc:1766
+#: rc_option_editor.cc:1723
 msgid "%1 Preferences"
 msgstr "%1 Einstellungen"
 
-#: rc_option_editor.cc:1778
+#: rc_option_editor.cc:1734
 msgid "DSP CPU Utilization"
 msgstr "DSP CPU Nutzung"
 
-#: rc_option_editor.cc:1782
+#: rc_option_editor.cc:1738
 msgid "Signal processing uses"
 msgstr "Die Signalverarbeitung verwendet"
 
-#: rc_option_editor.cc:1787
+#: rc_option_editor.cc:1743
 msgid "all but one processor"
 msgstr "Alle außer einem Prozessor"
 
-#: rc_option_editor.cc:1788
+#: rc_option_editor.cc:1744
 msgid "all available processors"
 msgstr "Alle verfügbaren Prozessoren"
 
-#: rc_option_editor.cc:1791
+#: rc_option_editor.cc:1747
 msgid "%1 processors"
 msgstr "%1 Prozessoren"
 
-#: rc_option_editor.cc:1794
+#: rc_option_editor.cc:1750
 msgid "This setting will only take effect when %1 is restarted."
 msgstr "Diese Einstellung wird erst nach einem Neustart von %1 wirksam."
 
-#: rc_option_editor.cc:1799
+#: rc_option_editor.cc:1755
 msgid "Options|Undo"
 msgstr "Undo"
 
-#: rc_option_editor.cc:1806
+#: rc_option_editor.cc:1762
 msgid "Verify removal of last capture"
 msgstr "Verwerfen der letzten Aufnahme bestätigen"
 
-#: rc_option_editor.cc:1814
-msgid "Make periodic backups of the session file"
-msgstr "Erstelle regelmäßig Backups der Projektdatei"
-
-#: rc_option_editor.cc:1819
+#: rc_option_editor.cc:1767
 msgid "Session Management"
 msgstr "Projektmanagement:"
 
-#: rc_option_editor.cc:1824
+#: rc_option_editor.cc:1772
+msgid "Make periodic backups of the session file"
+msgstr "Erstelle regelmäßig Backups der Projektdatei"
+
+#: rc_option_editor.cc:1780
 msgid "Always copy imported files"
 msgstr "Importierte Dateien immer kopieren"
 
-#: rc_option_editor.cc:1831
+#: rc_option_editor.cc:1787
 msgid "Default folder for new sessions:"
 msgstr "Standardordner für neue Projekte"
 
-#: rc_option_editor.cc:1839
+#: rc_option_editor.cc:1795
 msgid "Maximum number of recent sessions"
 msgstr "Maximale Anzahl kürzlich geöffneter Projekte"
 
-#: rc_option_editor.cc:1852
+#: rc_option_editor.cc:1808
 msgid "Click gain level"
 msgstr "Lautstärke für Klick"
 
-#: rc_option_editor.cc:1857 route_time_axis.cc:268 route_time_axis.cc:832
+#: rc_option_editor.cc:1813 route_time_axis.cc:269 route_time_axis.cc:833
 msgid "Automation"
 msgstr "Automationen"
 
-#: rc_option_editor.cc:1862
+#: rc_option_editor.cc:1818
 msgid "Thinning factor (larger value => less data)"
 msgstr "Ausdünnungsfaktor (größerer Wert => weniger Daten)"
 
-#: rc_option_editor.cc:1871
+#: rc_option_editor.cc:1827
 msgid "Automation sampling interval (milliseconds)"
 msgstr "Meßintervall für Automation (Millisekunden)"
 
-#: rc_option_editor.cc:1879
+#: rc_option_editor.cc:1835
 msgid "Transport Options"
 msgstr "Transport Optionen"
 
-#: rc_option_editor.cc:1885
+#: rc_option_editor.cc:1841
 msgid "Keep record-enable engaged on stop"
 msgstr "Aufnahme bleibt nach Stopp aktiviert"
 
-#: rc_option_editor.cc:1894
+#: rc_option_editor.cc:1850
 msgid "Play loop is a transport mode"
 msgstr "Schleifenwiedergabe ist ein Transportmodus"
 
-#: rc_option_editor.cc:1899
+#: rc_option_editor.cc:1855
 msgid ""
 "<b>When enabled</b> the loop button does not start playback but forces "
 "playback to always play the loop\n"
@@ -9913,33 +10177,33 @@ msgid ""
 "<b>When disabled</b> the loop button starts playing the loop, but stop then "
 "cancels loop playback"
 msgstr ""
-"<b>Wenn aktiviert<b>, startet die Schleifen-Schaltfläche nicht die "
+"<b>Wenn aktiviert</b>, startet die Schleifen-Schaltfläche nicht die "
 "Wiedergabe, zwingt aber die Wiedergabe, immer die Schleife zu spielen\n"
 "\n"
-"<b>Wenn deaktiviert<b>, startet die Schleifen-Schaltfläche die Wiedergabe, "
+"<b>Wenn deaktiviert</b>, startet die Schleifen-Schaltfläche die Wiedergabe, "
 "ein späteres \"Stop\" beendet aber die Wiedergabe als Schleife"
 
-#: rc_option_editor.cc:1905
+#: rc_option_editor.cc:1861
 msgid "Stop recording when an xrun occurs"
 msgstr "Aufnahme bei xrun stoppen"
 
-#: rc_option_editor.cc:1910
+#: rc_option_editor.cc:1866
 msgid ""
 "<b>When enabled</b> %1 will stop recording if an over- or underrun is "
 "detected by the audio engine"
 msgstr ""
-"<b>Falls an</b>, wird %1 Aufnahmen bei Auftreten von Over- oder Underruns  "
-"abbrechen"
+"<b>Wenn aktiviert</b>, wird %1 Aufnahmen bei Auftreten von Over- oder "
+"Underruns  abbrechen"
 
-#: rc_option_editor.cc:1916
+#: rc_option_editor.cc:1872
 msgid "Create markers where xruns occur"
 msgstr "Bei xrun Marker erzeugen"
 
-#: rc_option_editor.cc:1925
+#: rc_option_editor.cc:1881
 msgid "Stop at the end of the session"
 msgstr "Am Ende des Projektes anhalten"
 
-#: rc_option_editor.cc:1930
+#: rc_option_editor.cc:1886
 msgid ""
 "<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the "
 "transport when it reaches the current session end marker\n"
@@ -9947,16 +10211,16 @@ msgid ""
 "<b>When disabled</b> %1 will continue to roll past the session end marker at "
 "all times"
 msgstr ""
-"<b>Falls an</b>, und %1 </b>nimmt nicht auf</b>, wird es bei Erreichen ds "
-"Projektende-Markers die Wiedergabe stoppen\n"
+"<b>Wenn aktiviert</b>, und %1 <b>nimmt nicht auf</b>, wird es bei Erreichen "
+"ds Projektende-Markers die Wiedergabe stoppen\n"
 "\n"
-"<b>Falls aus</b> , wird %1 am Ende des Projektes immer weiterlaufen"
+"<b>Wenn deaktiviert</b> , wird %1 am Ende des Projektes immer weiterlaufen"
 
-#: rc_option_editor.cc:1938
+#: rc_option_editor.cc:1894
 msgid "Do seamless looping (not possible when slaved to MTC, LTC etc)"
 msgstr "Nahtlose Schleifen (nicht möglich, wenn an MTC, LTC o.ä. gekoppelt)"
 
-#: rc_option_editor.cc:1943
+#: rc_option_editor.cc:1899
 msgid ""
 "<b>When enabled</b> this will loop by reading ahead and wrapping around at "
 "the loop point, preventing any need to do a transport locate at the end of "
@@ -9965,31 +10229,31 @@ msgid ""
 "<b>When disabled</b> looping is done by locating back to the start of the "
 "loop when %1 reaches the end which will often cause a small click or delay"
 msgstr ""
-"<b>Falls an</b>, wird dies vorauslesen und am Schleifenendpunkt "
+"<b>Wenn aktiviert</b>, wird dies vorauslesen und am Schleifenendpunkt "
 "zurückspringen, wodurch eine Neupositionierung am Schleifenende vermieden "
 "wird\n"
 "\n"
-"<b>Falls aus</b>, wird %1 bei Erreichen des Schleifenendes zum Anfang der "
-"Schleife springen, was oft einen hörbaren Klick oder kurze Verzögerung "
+"<b>Wenn deaktiviert</b>, wird %1 bei Erreichen des Schleifenendes zum Anfang "
+"der Schleife springen, was oft einen hörbaren Klick oder kurze Verzögerung "
 "verursacht"
 
-#: rc_option_editor.cc:1951
+#: rc_option_editor.cc:1907
 msgid "Disable per-track record disarm while rolling"
 msgstr "Während der Aufnahme Aufnahmestatus einzelner Spuren sperren"
 
-#: rc_option_editor.cc:1955
+#: rc_option_editor.cc:1911
 msgid ""
 "<b>When enabled</b> this will prevent you from accidentally stopping "
 "specific tracks recording during a take"
 msgstr ""
-"<b>Wenn eingeschaltet</b> , hindert Sie dies daran, während eines "
+"<b>Wenn aktiviert</b> , hindert Sie dies daran, während eines "
 "Aufnahmevorgangs unabsichtlich bei einzelnen Spuren die Aufnahme zu beenden"
 
-#: rc_option_editor.cc:1960
+#: rc_option_editor.cc:1916
 msgid "12dB gain reduction during fast-forward and fast-rewind"
 msgstr "Beim Spulen Pegel um 12dB absenken"
 
-#: rc_option_editor.cc:1964
+#: rc_option_editor.cc:1920
 msgid ""
 "This will reduce the unpleasant increase in perceived volume that occurs "
 "when fast-forwarding or rewinding through some kinds of audio"
@@ -9997,19 +10261,62 @@ msgstr ""
 "Dies wird die unangenehme Steigerung der wahrgenommenen Lautstärke "
 "verringern, die bei manchem Material bei Vor/Rücklauf auftritt"
 
-#: rc_option_editor.cc:1968
+#: rc_option_editor.cc:1926
+msgid "Preroll"
+msgstr "Vorlauf"
+
+#: rc_option_editor.cc:1931
+msgid ""
+"The amount of preroll (in seconds) to apply when <b>Play with Preroll</b> is "
+"initiated.\n"
+"\n"
+"If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead "
+"position when a region is selected or trimmed."
+msgstr ""
+"Die anzuwendende Länge des Vorlaufs (in Sekunden), wenn <b>Wiedergabe mit "
+"Vorlauf</b> ausgelöst wird.\n"
+"\n"
+"Falls <b>Folge Bearbeitungen</b> aktiviert ist, wird der Vorlauf an der "
+"Wiedergabeposition angewandt, wenn eine Region ausgewählt oder in der Länge "
+"angepasst wird."
+
+#: rc_option_editor.cc:1933
+msgid "0 (no pre-roll)"
+msgstr "0 (kein Vorlauf)"
+
+#: rc_option_editor.cc:1934
+msgid "0.1 second"
+msgstr "0.1 Sekunden"
+
+#: rc_option_editor.cc:1935
+msgid "0.25 second"
+msgstr "0.25 Sekunden"
+
+#: rc_option_editor.cc:1936
+msgid "0.5 second"
+msgstr "0.5 Sekunden"
+
+#: rc_option_editor.cc:1937
+msgid "1.0 second"
+msgstr "1.25 Sekunden"
+
+#: rc_option_editor.cc:1938
+msgid "2.0 seconds"
+msgstr "2.0 Sekunden"
+
+#: rc_option_editor.cc:1941
 msgid "Sync/Slave"
 msgstr "Sync/Slave"
 
-#: rc_option_editor.cc:1972
+#: rc_option_editor.cc:1945
 msgid "External timecode source"
 msgstr "Externe Timecode-Quelle"
 
-#: rc_option_editor.cc:1981
+#: rc_option_editor.cc:1954
 msgid "Match session video frame rate to external timecode"
 msgstr "Videoframerate des Projekts an externen Timecode anpassen"
 
-#: rc_option_editor.cc:1987
+#: rc_option_editor.cc:1960
 msgid ""
 "This option controls the value of the video frame rate <i>while chasing</i> "
 "an external timecode source.\n"
@@ -10025,20 +10332,20 @@ msgstr ""
 "Diese Option bestimmt den Wert der Videoframerate <i>während der "
 "Synchronisation</i> mit einer externen Timecode-Quelle. \n"
 "\n"
-"<b>Falls an</b>, wird die Videoframerate des Projektes an die der externen "
-"Timecode-Quelle angepasst. \n"
+"<b>Wenn deaktiviert</b>, wird die Videoframerate des Projektes an die der "
+"externeTimecode-Quelle angepasst. \n"
 "\n"
-"<b>Falls aus</b>, wird die Videoframerate des Projektes nicht geändert. "
-"Stattdessen wird die Anzeige der Framerate in der Uhr rot blinken und %1 "
-"wird zwischen den Standards der externen Quelle und des Projektes "
+"<b>Wenn deaktiviert</b>, wird die Videoframerate des Projektes nicht "
+"geändert. Stattdessen wird die Anzeige der Framerate in der Uhr rot blinken "
+"und %1 wird zwischen den Standards der externen Quelle und des Projektes "
 "konvertieren."
 
-#: rc_option_editor.cc:1997
+#: rc_option_editor.cc:1970
 msgid "Sync-lock timecode to clock (disable drift compensation)"
 msgstr ""
 "Starre Synchronisation von Timecode und Uhr (unterbinde Driftkompensation)"
 
-#: rc_option_editor.cc:2003
+#: rc_option_editor.cc:1976
 msgid ""
 "<b>When enabled</b> %1 will never varispeed when slaved to external "
 "timecode. Sync Lock indicates that the selected external timecode source "
@@ -10059,11 +10366,11 @@ msgstr ""
 "<b>Wenn deaktiviert</b>, wird  %1 potentiellen Drift kompensieren, "
 "ungeachtet, ob die Timecodequellen Clock Sync teilen."
 
-#: rc_option_editor.cc:2018
+#: rc_option_editor.cc:1991
 msgid "Lock to 29.9700 fps instead of 30000/1001"
 msgstr "Fest auf 29.9700 fps statt 30000/1001"
 
-#: rc_option_editor.cc:2024
+#: rc_option_editor.cc:1997
 msgid ""
 "<b>When enabled</b> the external timecode source is assumed to use 29.97 fps "
 "instead of 30000/1001.\n"
@@ -10075,50 +10382,50 @@ msgid ""
 "vendors use that rate - despite it being against the specs - because the "
 "variant of using exactly 29.97 fps has zero timecode drift.\n"
 msgstr ""
-"<b>Wenn aktiv</b>, wird erwartet, daß die externe Timecode-Quelle 29.97 fps "
-"statt 30000/1001 benutzt.\n"
+"<b>Wenn aktiviert</b>, wird erwartet, daß die externe Timecode-Quelle 29.97 "
+"fps statt 30000/1001 benutzt.\n"
 "SMPTE 12M-1999 spezifiziert 29.97df as 30000/1001. Die Spezifikation erwähnt "
 "darüber hinaus, daß Drop-frame Timecode einen Fehler von -86ms im Zeitraum "
 "von 24 Stunden akkumuliert.\n"
 "Drop-frame Timecode würde eine NTSC Farb-Framerate von 30 * 0.9990 "
-"(entspricht29.970000) exakt kompensieren. Das ist nicht die tatsächliche "
-"Rate, jedoch benutzen manche Hersteller diese - der Spezifikation "
-"widersprechend - da bei der Variante mit exakt 29.97 fps kein Timecode-Drift "
-"auftritt.\n"
+"(entspricht 29.970000) exakt kompensieren. Das ist nicht die tatsächliche "
+"Rate, jedoch benutzen manche Hersteller diese - obwohl der Spezifikation "
+"widersprechend -, da bei der Variante mit exakt 29.97 fps kein Timecode-"
+"Drift auftritt.\n"
 
-#: rc_option_editor.cc:2034
+#: rc_option_editor.cc:2007
 msgid "LTC Reader"
 msgstr "LTC-Leser"
 
-#: rc_option_editor.cc:2038
+#: rc_option_editor.cc:2011
 msgid "LTC incoming port"
 msgstr "LTC Eingangsport"
 
-#: rc_option_editor.cc:2053
+#: rc_option_editor.cc:2027
 msgid "LTC Generator"
 msgstr "LTC-Generator"
 
-#: rc_option_editor.cc:2058
+#: rc_option_editor.cc:2032
 msgid "Enable LTC generator"
 msgstr "LTC-Generator aktivieren"
 
-#: rc_option_editor.cc:2065
+#: rc_option_editor.cc:2039
 msgid "Send LTC while stopped"
 msgstr "LTC senden, während Transport stillsteht"
 
-#: rc_option_editor.cc:2071
+#: rc_option_editor.cc:2045
 msgid ""
 "<b>When enabled</b> %1 will continue to send LTC information even when the "
 "transport (playhead) is not moving"
 msgstr ""
-"<b>Falls an</b>, wird %1 weiterhin LTC-Information senden, sogar wenn der "
-"Transport (Positionszeiger) stillsteht"
+"<b>Wenn aktiviert</b>, wird %1 weiterhin LTC-Information senden, sogar wenn "
+"der Transport (Positionszeiger) stillsteht"
 
-#: rc_option_editor.cc:2077
+#: rc_option_editor.cc:2051
 msgid "LTC generator level"
 msgstr "LTC-Generator-Lautstärke"
 
-#: rc_option_editor.cc:2081
+#: rc_option_editor.cc:2055
 msgid ""
 "Specify the Peak Volume of the generated LTC signal in dbFS. A good value "
 "is  0dBu ^= -18dbFS in an EBU calibrated system"
@@ -10126,395 +10433,419 @@ msgstr ""
 "Geben Sie den Spitzenwert des erzeugten LTC-Signals in dbFS an. Ein guter "
 "Wert für ein EBU-kalibriertes System ist 0dBu ^= -18dbFS"
 
-#: rc_option_editor.cc:2093
+#: rc_option_editor.cc:2064
+msgid "Make rubberband selection rectangle snap to the grid"
+msgstr "Gummiband-Auswahl an Raster ausrichten"
+
+#: rc_option_editor.cc:2071
+msgid "Name new markers"
+msgstr "Neue Marker benennen"
+
+#: rc_option_editor.cc:2076
+msgid ""
+"If enabled, popup a dialog when a new marker is created to allow its name to "
+"be set as it is created.\n"
+"\n"
+"You can always rename markers by right-clicking on them"
+msgstr ""
+"Falls an, wird bei Erzeugung eines neuen Markers ein Dialog eingeblendet, "
+"damit der Name sofort bearbeitet werden kann.\n"
+"\n"
+"Marker können jederzeit per Rechtsklick umbenannt werden"
+
+#: rc_option_editor.cc:2082
 msgid "Allow dragging of playhead"
 msgstr "Erlaube Ziehen des Positionszeigers"
 
-#: rc_option_editor.cc:2101
-msgid "Move relevant automation when audio regions are moved"
-msgstr "Verschiebe relevante Automationen mit Region"
-
-#: rc_option_editor.cc:2109
+#: rc_option_editor.cc:2090
 msgid "Show meters on tracks in the editor"
 msgstr "Aktiviere Pegelanzeigen im Editor"
 
-#: rc_option_editor.cc:2117
+#: rc_option_editor.cc:2098
 msgid "Display master-meter in the toolbar"
 msgstr "Master-Pegelanzeige in der Werkzeugleiste anzeigen"
 
+#: rc_option_editor.cc:2107
+msgid "Show zoom toolbar (if torn off)"
+msgstr "Zoom-Toolbar zeigen (falls abgelöst)"
+
+#: rc_option_editor.cc:2116
+msgid "Update editor window during drags of the summary"
+msgstr ""
+"Aktualisiere das Editorfenster, während die Projektübersicht verändert wird"
+
 #: rc_option_editor.cc:2124
+msgid "Auto-scroll editor window when dragging near its edges"
+msgstr "Bei Mausziehen nahe den Rändern das Editorfenster automatisch scrollen"
+
+#: rc_option_editor.cc:2132
+msgid "Show gain envelopes in audio regions"
+msgstr "Zeige Lautstärkekurven in Regionen an"
+
+#: rc_option_editor.cc:2133
+msgid "in all modes"
+msgstr "in allen Modi"
+
+#: rc_option_editor.cc:2134
+msgid "only in Draw and Internal Edit modes"
+msgstr "nur in Zeichen- und internem Bearbeitungsmodus"
+
+#: rc_option_editor.cc:2139
+msgid "Editor Behavior"
+msgstr "Editor-Verhalten"
+
+#: rc_option_editor.cc:2144
+msgid "Move relevant automation when audio regions are moved"
+msgstr "Verschiebe relevante Automationen mit Region"
+
+#: rc_option_editor.cc:2151
 msgid "Default fade shape"
 msgstr "Voreingestellte Fade-Art"
 
-#: rc_option_editor.cc:2143
+#: rc_option_editor.cc:2170
 msgid "Regions in active edit groups are edited together"
 msgstr "Regionen der aktiven Bearbeitungsgruppen werden gemeinsam bearbeitet"
 
-#: rc_option_editor.cc:2144
+#: rc_option_editor.cc:2171
 msgid "whenever they overlap in time"
 msgstr "immer, wenn sie sich auf der Zeitachse überlappen"
 
-#: rc_option_editor.cc:2145
+#: rc_option_editor.cc:2172
 msgid "only if they have identical length, position and origin"
 msgstr "nur bei identischer Länge, Position und Herkunft"
 
-#: rc_option_editor.cc:2154
+#: rc_option_editor.cc:2181
 msgid "Layering model"
 msgstr "Layering-Modell"
 
-#: rc_option_editor.cc:2159
+#: rc_option_editor.cc:2186
 msgid "later is higher"
 msgstr "später ist höher"
 
-#: rc_option_editor.cc:2160
+#: rc_option_editor.cc:2187
 msgid "manual layering"
 msgstr "manuelles Layering"
 
-#: rc_option_editor.cc:2166
-msgid "Make rubberband selection rectangle snap to the grid"
-msgstr "Gummiband-Auswahl an Raster ausrichten"
+#: rc_option_editor.cc:2192
+msgid "After splitting selected regions, select"
+msgstr "Nach dem Teilen"
 
-#: rc_option_editor.cc:2174
-msgid "Show waveforms in regions"
-msgstr "Zeige Wellenformen in Regionen"
+#: rc_option_editor.cc:2197
+msgid "no regions"
+msgstr "keine Regionen"
 
-#: rc_option_editor.cc:2182
-msgid "Show gain envelopes in audio regions"
-msgstr "Zeige Lautstärkekurven in Regionen an"
+#: rc_option_editor.cc:2200
+msgid "newly-created regions"
+msgstr "neu erzeugte Regionen"
 
-#: rc_option_editor.cc:2183
-msgid "in all modes"
-msgstr "in allen Modi"
+#: rc_option_editor.cc:2204
+msgid "existing selection and newly-created regions"
+msgstr "existierende Auswahl und neu erzeugte Regionen"
 
-#: rc_option_editor.cc:2184
-msgid "only in Draw and Internal Edit modes"
-msgstr "nur in Zeichen- und internem Bearbeitungsmodus"
+#: rc_option_editor.cc:2208
+msgid "Waveforms"
+msgstr "Wellenformen"
 
-#: rc_option_editor.cc:2191
+#: rc_option_editor.cc:2214
+msgid "Show waveforms in regions"
+msgstr "Zeige Wellenformen in Regionen"
+
+#: rc_option_editor.cc:2223
+msgid "Show waveforms for audio while it is being recorded"
+msgstr "Zeige bei Aufnahmen die Wellenformen des aufgenommenen Audiomaterials"
+
+#: rc_option_editor.cc:2230
 msgid "Waveform scale"
 msgstr "Wellenformskalierung"
 
-#: rc_option_editor.cc:2196
+#: rc_option_editor.cc:2235
 msgid "linear"
 msgstr "Linear"
 
-#: rc_option_editor.cc:2197
+#: rc_option_editor.cc:2236
 msgid "logarithmic"
 msgstr "Logarithmisch"
 
-#: rc_option_editor.cc:2203
+#: rc_option_editor.cc:2242
 msgid "Waveform shape"
 msgstr "Wellenform Anzeigeart"
 
-#: rc_option_editor.cc:2208
+#: rc_option_editor.cc:2247
 msgid "traditional"
 msgstr "Traditionell"
 
-#: rc_option_editor.cc:2209
+#: rc_option_editor.cc:2248
 msgid "rectified"
 msgstr "Rectified"
 
-#: rc_option_editor.cc:2218
-msgid "Show waveforms for audio while it is being recorded"
-msgstr "Zeige bei Aufnahmen die Wellenformen des aufgenommenen Audiomaterials"
-
-#: rc_option_editor.cc:2226
-msgid "Show zoom toolbar"
-msgstr "Zeige Zoom Toolbar"
-
-#: rc_option_editor.cc:2234
-msgid "Update editor window during drags of the summary"
-msgstr ""
-"Aktualisiere das Editorfenster, während die Projektübersicht verändert wird"
-
-#: rc_option_editor.cc:2241
-msgid "Name new markers"
-msgstr "Neue Marker benennen"
-
-#: rc_option_editor.cc:2247
-msgid ""
-"If enabled, popup a dialog when a new marker is created to allow its name to "
-"be set as it is created.\n"
-"\n"
-"You can always rename markers by right-clicking on them"
-msgstr ""
-"Falls an, wird bei Erzeugung eines neuen Markers ein Dialog eingeblendet, "
-"damit der Name sofort bearbeitet werden kann.\n"
-"\n"
-"Marker können jederzeit per Rechtsklick umbenannt werden"
-
-#: rc_option_editor.cc:2253
-msgid "Auto-scroll editor window when dragging near its edges"
-msgstr "Bei Mausziehen nahe den Rändern das Editorfenster automatisch scrollen"
-
-#: rc_option_editor.cc:2260
-msgid "After splitting selected regions, select"
-msgstr "Nach dem Teilen"
-
-#: rc_option_editor.cc:2265
-msgid "no regions"
-msgstr "keine Regionen"
-
-#: rc_option_editor.cc:2268
-msgid "newly-created regions"
-msgstr "neu erzeugte Regionen"
-
-#: rc_option_editor.cc:2272
-msgid "existing selection and newly-created regions"
-msgstr "existierende Auswahl und neu erzeugte Regionen"
-
-#: rc_option_editor.cc:2279
+#: rc_option_editor.cc:2257
 msgid "Buffering"
 msgstr "Pufferung"
 
-#: rc_option_editor.cc:2287
+#: rc_option_editor.cc:2265
 msgid "Record monitoring handled by"
 msgstr "Aufnahmemonitoring wird verwaltet von"
 
-#: rc_option_editor.cc:2293
+#: rc_option_editor.cc:2271
 msgid "via Audio Driver"
 msgstr "via Audiotreiber"
 
-#: rc_option_editor.cc:2299
+#: rc_option_editor.cc:2277
 msgid "audio hardware"
 msgstr "Audiohardware"
 
-#: rc_option_editor.cc:2306
+#: rc_option_editor.cc:2284
 msgid "Tape machine mode"
 msgstr "Bandmaschinen-Modus"
 
-#: rc_option_editor.cc:2311
+#: rc_option_editor.cc:2290
 msgid "Connection of tracks and busses"
 msgstr "Verbindung von Spuren und Bussen"
 
-#: rc_option_editor.cc:2316
+#: rc_option_editor.cc:2295
 msgid "Auto-connect master/monitor busses"
 msgstr "Master/Monitor-Busse automatisch verbinden"
 
-#: rc_option_editor.cc:2323
+#: rc_option_editor.cc:2302
 msgid "Connect track inputs"
 msgstr "Verbinde Spureingänge"
 
-#: rc_option_editor.cc:2328
+#: rc_option_editor.cc:2307
 msgid "automatically to physical inputs"
 msgstr "automatisch mit Audioeingängen"
 
-#: rc_option_editor.cc:2329 rc_option_editor.cc:2342
+#: rc_option_editor.cc:2308 rc_option_editor.cc:2321
 msgid "manually"
 msgstr "manuell"
 
-#: rc_option_editor.cc:2335
+#: rc_option_editor.cc:2314
 msgid "Connect track and bus outputs"
 msgstr "Verbinde Spur- und Busausgänge"
 
-#: rc_option_editor.cc:2340
+#: rc_option_editor.cc:2319
 msgid "automatically to physical outputs"
 msgstr "automatisch mit Audioausgängen"
 
-#: rc_option_editor.cc:2341
+#: rc_option_editor.cc:2320
 msgid "automatically to master bus"
 msgstr "automatisch mit dem Master-Bus"
 
-#: rc_option_editor.cc:2346
+#: rc_option_editor.cc:2326
 msgid "Denormals"
 msgstr "Denormals"
 
-#: rc_option_editor.cc:2351
+#: rc_option_editor.cc:2331
 msgid "Use DC bias to protect against denormals"
 msgstr "Nutze DC bias als Schutz vor Denormals"
 
-#: rc_option_editor.cc:2358
+#: rc_option_editor.cc:2338
 msgid "Processor handling"
 msgstr "Umgang des Prozessors mit Denormals"
 
-#: rc_option_editor.cc:2364
+#: rc_option_editor.cc:2344
 msgid "no processor handling"
 msgstr "nicht behandeln"
 
-#: rc_option_editor.cc:2370
+#: rc_option_editor.cc:2350
 msgid "use FlushToZero"
 msgstr "Benutze FlushToZero"
 
-#: rc_option_editor.cc:2377
+#: rc_option_editor.cc:2357
 msgid "use DenormalsAreZero"
 msgstr "Benutze DenormalsAreZero"
 
-#: rc_option_editor.cc:2384
+#: rc_option_editor.cc:2364
 msgid "use FlushToZero and DenormalsAreZero"
 msgstr "Benutze FlushToZero & DenormalsAreZero"
 
-#: rc_option_editor.cc:2400
+#: rc_option_editor.cc:2380
 msgid "Silence plugins when the transport is stopped"
 msgstr "Deaktiviere Plugins, wenn der Transport gestoppt ist."
 
-#: rc_option_editor.cc:2408
+#: rc_option_editor.cc:2388
 msgid "Make new plugins active"
 msgstr "Neue Plugins sind aktiv"
 
-#: rc_option_editor.cc:2418
+#: rc_option_editor.cc:2398
 msgid "Enable automatic analysis of audio"
 msgstr "Audiodaten automatisch analysieren"
 
-#: rc_option_editor.cc:2426
+#: rc_option_editor.cc:2406
 msgid "Replicate missing region channels"
 msgstr "Fehlende Kanäle in Regionen durch Kopien ersetzen"
 
-#: rc_option_editor.cc:2433 rc_option_editor.cc:2435 rc_option_editor.cc:2450
-#: rc_option_editor.cc:2462 rc_option_editor.cc:2474 rc_option_editor.cc:2486
-#: rc_option_editor.cc:2490 rc_option_editor.cc:2498 rc_option_editor.cc:2506
-#: rc_option_editor.cc:2514 rc_option_editor.cc:2516 rc_option_editor.cc:2524
-#: rc_option_editor.cc:2532 rc_option_editor.cc:2540 rc_option_editor.cc:2548
-#: rc_option_editor.cc:2550
+#: rc_option_editor.cc:2413 rc_option_editor.cc:2422 rc_option_editor.cc:2424
+#: rc_option_editor.cc:2432 rc_option_editor.cc:2440 rc_option_editor.cc:2448
+#: rc_option_editor.cc:2466 rc_option_editor.cc:2478 rc_option_editor.cc:2490
+#: rc_option_editor.cc:2492 rc_option_editor.cc:2494 rc_option_editor.cc:2502
+#: rc_option_editor.cc:2510 rc_option_editor.cc:2518 rc_option_editor.cc:2526
+#: rc_option_editor.cc:2528
 msgid "Solo / mute"
 msgstr "Solo / Mute"
 
-#: rc_option_editor.cc:2438
-msgid "Solo-in-place mute cut (dB)"
-msgstr "Solo-in-Place Mute Dämpfung (dB)"
-
-#: rc_option_editor.cc:2445
+#: rc_option_editor.cc:2417
 msgid "Solo controls are Listen controls"
 msgstr "Solo-Schalter arbeiten als AFL/PFL"
 
-#: rc_option_editor.cc:2454
+#: rc_option_editor.cc:2427
+msgid "Exclusive solo"
+msgstr "Exclusives Solo"
+
+#: rc_option_editor.cc:2435
+msgid "Show solo muting"
+msgstr "Solo auf anderen Kanälen als Mute anzeigen"
+
+#: rc_option_editor.cc:2443
+msgid "Soloing overrides muting"
+msgstr "Solo ist trotz Mute hörbar"
+
+#: rc_option_editor.cc:2451
+msgid "Solo-in-place mute cut (dB)"
+msgstr "Solo-in-Place Mute Dämpfung (dB)"
+
+#: rc_option_editor.cc:2458
 msgid "Listen Position"
 msgstr "Abhörpunkt"
 
-#: rc_option_editor.cc:2459
+#: rc_option_editor.cc:2463
 msgid "after-fader (AFL)"
 msgstr "After-Fader (AFL)"
 
-#: rc_option_editor.cc:2460
+#: rc_option_editor.cc:2464
 msgid "pre-fader (PFL)"
 msgstr "Pre-Fader (PFL)"
 
-#: rc_option_editor.cc:2466
+#: rc_option_editor.cc:2470
 msgid "PFL signals come from"
 msgstr "Abgreifpunkt der PFL Signale"
 
-#: rc_option_editor.cc:2471
+#: rc_option_editor.cc:2475
 msgid "before pre-fader processors"
 msgstr "Vor den Pre-Fader Prozessoren"
 
-#: rc_option_editor.cc:2472
+#: rc_option_editor.cc:2476
 msgid "pre-fader but after pre-fader processors"
 msgstr "Pre-Fader, aber nach den Prozessoren"
 
-#: rc_option_editor.cc:2478
+#: rc_option_editor.cc:2482
 msgid "AFL signals come from"
 msgstr "Abgreifpunkt der AFL Signale"
 
-#: rc_option_editor.cc:2483
+#: rc_option_editor.cc:2487
 msgid "immediately post-fader"
 msgstr "Direkt nach dem Fader"
 
-#: rc_option_editor.cc:2484
+#: rc_option_editor.cc:2488
 msgid "after post-fader processors (before pan)"
-msgstr "Nach den Post-Fader Prozessoren (vor Pan)"
-
-#: rc_option_editor.cc:2493
-msgid "Exclusive solo"
-msgstr "Exclusives Solo"
-
-#: rc_option_editor.cc:2501
-msgid "Show solo muting"
-msgstr "Solo auf anderen Kanälen als Mute anzeigen"
-
-#: rc_option_editor.cc:2509
-msgid "Soloing overrides muting"
-msgstr "Solo ist trotz Mute hörbar"
+msgstr "Nach den Post-Fader Prozessoren (vor Pan)"
 
-#: rc_option_editor.cc:2514
+#: rc_option_editor.cc:2492
 msgid "Default track / bus muting options"
 msgstr "Standardeinstellungen für Mute von Spuren / Bussen"
 
-#: rc_option_editor.cc:2519
+#: rc_option_editor.cc:2497
 msgid "Mute affects pre-fader sends"
 msgstr "Mute schaltet Pre-Fader Sends stumm"
 
-#: rc_option_editor.cc:2527
+#: rc_option_editor.cc:2505
 msgid "Mute affects post-fader sends"
 msgstr "Mute schaltet Post-Fader Sends stumm"
 
-#: rc_option_editor.cc:2535
+#: rc_option_editor.cc:2513
 msgid "Mute affects control outputs"
 msgstr "Mute schaltet Abhörausgänge stumm"
 
-#: rc_option_editor.cc:2543
+#: rc_option_editor.cc:2521
 msgid "Mute affects main outputs"
 msgstr "Mute schaltet Hauptausgänge stumm"
 
-#: rc_option_editor.cc:2548
+#: rc_option_editor.cc:2526
 msgid "Send Routing"
 msgstr "Send Routing"
 
-#: rc_option_editor.cc:2553
+#: rc_option_editor.cc:2531
 msgid "Link panners of Aux and External Sends with main panner by default"
 msgstr "Verknüpfe Aux- und External-Send-Panner mit Hauptpanner"
 
-#: rc_option_editor.cc:2561
+#: rc_option_editor.cc:2536
+msgid "MIDI Preferences"
+msgstr "MIDI Einstellungen"
+
+#: rc_option_editor.cc:2541
 msgid "MIDI read-ahead time (seconds)"
 msgstr "MIDI read-ahead Zeit (Sekunden)"
 
-#: rc_option_editor.cc:2579
+#: rc_option_editor.cc:2551
+msgid "Initial program change"
+msgstr "Erstmaliger Programmwechsel"
+
+#: rc_option_editor.cc:2560
+msgid "Display first MIDI bank/program as 0"
+msgstr "Erste(s) MIDI Bank/Programm als 0 anzeigen"
+
+#: rc_option_editor.cc:2568
+msgid "Never display periodic MIDI messages (MTC, MIDI Clock)"
+msgstr "Periodische MIDI Nachrichten nie anzeigen (MTC, MIDI Clock)"
+
+#: rc_option_editor.cc:2576
+msgid "Sound MIDI notes as they are selected in the editor"
+msgstr "MIDI Noten ertönen bei Auswahl im Editor"
+
+#: rc_option_editor.cc:2584
+msgid "Send MIDI control feedback"
+msgstr "MIDI Control Feedback senden"
+
+#: rc_option_editor.cc:2589
+msgid "MIDI Clock"
+msgstr "MIDI Clock"
+
+#: rc_option_editor.cc:2599
+msgid "MIDI Time Code (MTC)"
+msgstr "MIDI Time Code (MTC)"
+
+#: rc_option_editor.cc:2604
 msgid "Send MIDI Time Code"
 msgstr "Sende MIDI Time Code"
 
-#: rc_option_editor.cc:2587
+#: rc_option_editor.cc:2612
 msgid "Percentage either side of normal transport speed to transmit MTC"
 msgstr ""
 "Prozentzahl beiderseits der normalen Transportgeschwindigkeit, bis zu der "
 "MTC übertragen wird"
 
-#: rc_option_editor.cc:2596
+#: rc_option_editor.cc:2618
+msgid "Midi Machine Control (MMC)"
+msgstr "Midi Machine Control (MMC)"
+
+#: rc_option_editor.cc:2623
 msgid "Obey MIDI Machine Control commands"
 msgstr "MIDI Machine Control Commands empfangen"
 
-#: rc_option_editor.cc:2604
+#: rc_option_editor.cc:2631
 msgid "Send MIDI Machine Control commands"
 msgstr "MIDI Machine Control Commands senden"
 
-#: rc_option_editor.cc:2612
-msgid "Send MIDI control feedback"
-msgstr "MIDI Control Feedback senden"
-
-#: rc_option_editor.cc:2620
+#: rc_option_editor.cc:2639
 msgid "Inbound MMC device ID"
 msgstr "ID des eingehenden MMC-Geräts"
 
-#: rc_option_editor.cc:2629
+#: rc_option_editor.cc:2648
 msgid "Outbound MMC device ID"
 msgstr "ID des ausgehenden MMC-Geräts"
 
-#: rc_option_editor.cc:2638
-msgid "Initial program change"
-msgstr "Erstmaliger Programmwechsel"
-
-#: rc_option_editor.cc:2647
-msgid "Display first MIDI bank/program as 0"
-msgstr "Erste(s) MIDI Bank/Programm als 0 anzeigen"
-
-#: rc_option_editor.cc:2655
-msgid "Never display periodic MIDI messages (MTC, MIDI Clock)"
-msgstr "Periodische MIDI Nachrichten nie anzeigen (MTC, MIDI Clock)"
-
-#: rc_option_editor.cc:2663
-msgid "Sound MIDI notes as they are selected"
-msgstr "MIDI Noten ertönen bei Auswahl"
-
-#: rc_option_editor.cc:2668
+#: rc_option_editor.cc:2654
 msgid "Midi Audition"
 msgstr "Midi vorhören"
 
-#: rc_option_editor.cc:2672
+#: rc_option_editor.cc:2658
 msgid "Midi Audition Synth (LV2)"
 msgstr "Midi Vorhör-Synth (LV2)"
 
-#: rc_option_editor.cc:2703 rc_option_editor.cc:2713 rc_option_editor.cc:2715
+#: rc_option_editor.cc:2689 rc_option_editor.cc:2699 rc_option_editor.cc:2701
 msgid "User interaction"
 msgstr "Benutzerinteraktion"
 
-#: rc_option_editor.cc:2706
+#: rc_option_editor.cc:2692
 msgid ""
 "Use translations of %1 messages\n"
 "   <i>(requires a restart of %1 to take effect)</i>\n"
@@ -10524,59 +10855,189 @@ msgstr ""
 "   <i>(erfordert Neustart von %1)</i>\n"
 "   <i>(falls für Ihre gewünschte Sprache verfügbar)</i>"
 
-#: rc_option_editor.cc:2713
+#: rc_option_editor.cc:2699
 msgid "Keyboard"
 msgstr "Tastatur"
 
-#: rc_option_editor.cc:2723
+#: rc_option_editor.cc:2709
 msgid "Control surface remote ID"
 msgstr "Remote ID des Eingabegeräts"
 
-#: rc_option_editor.cc:2728
+#: rc_option_editor.cc:2714
 msgid "assigned by user"
 msgstr "vom Benutzer festgelegt"
 
-#: rc_option_editor.cc:2729
+#: rc_option_editor.cc:2715
 msgid "follows order of mixer"
 msgstr "folgt Reihenfolge im Mixer"
 
+#: rc_option_editor.cc:2723
+msgid "General"
+msgstr "Allgemein"
+
+#: rc_option_editor.cc:2726 startup.cc:351
+msgid "Scan for Plugins"
+msgstr "Scanne nach Plugins"
+
+#: rc_option_editor.cc:2731
+msgid "Always Display Plugin Scan Progress"
+msgstr "Plugin Scan-Fortschritt immer anzeigen"
+
+#: rc_option_editor.cc:2737
+msgid ""
+"<b>When enabled</b> a popup window showing plugin scan progress is displayed "
+"for indexing (cache load) and discovery (detect new plugins)"
+msgstr ""
+"<b>Wenn aktiviert,</b> wird ein Popupfenster dargestellt, um Plugin Scan-"
+"Fortschritt, Indizierung(Laden des Cache) und Entdeckung (neue Plugins "
+"finden) anzuzeigen"
+
+#: rc_option_editor.cc:2742
+msgid "VST"
+msgstr "VST"
+
 #: rc_option_editor.cc:2746
-msgid "Possibly improve slow graphical performance"
-msgstr "Versuche, langsame Grafikperformance zu verbessern"
+msgid "Scan for [new] VST Plugins on Application Start"
+msgstr "Bei Programmstart nach [neuen] VST Plugins scannen"
+
+#: rc_option_editor.cc:2752
+msgid ""
+"<b>When enabled</b> new VST plugins are searched, tested and added to the "
+"cache index on application start. When disabled new plugins will only be "
+"available after triggering a 'Scan' manually"
+msgstr ""
+"<b>Wenn aktiviert</b>, werden bei Programmstart neue VST Plugins gesucht, "
+"getestet und dem Cache-Index hinzugefügt. Wenn deaktiviert, werden neue "
+"Plugins nur nach einem manuellen Scan verfügbar sein"
+
+#: rc_option_editor.cc:2758
+msgid "Verbose Plugin Scan"
+msgstr "Gesprächiger Plugin-Scan"
+
+#: rc_option_editor.cc:2764
+msgid ""
+"<b>When enabled</b> additional information for every plugin is added to the "
+"Log Window."
+msgstr ""
+"<b>Wenn aktiviert</b>, wird zusätzliche Information für jedes Plugin ins "
+"Logfenster geschrieben."
+
+#: rc_option_editor.cc:2772
+msgid "VST Cache:"
+msgstr "VST Cache:"
+
+#: rc_option_editor.cc:2777
+msgid "VST Blacklist:"
+msgstr "VST Schwarzliste:"
+
+#: rc_option_editor.cc:2784
+msgid "Linux VST Path:"
+msgstr "Linux VST Pfad:"
+
+#: rc_option_editor.cc:2789 rc_option_editor.cc:2802
+msgid "Path:"
+msgstr "Pfad:"
+
+#: rc_option_editor.cc:2798
+msgid "Windows VST Path:"
+msgstr "Windows VST Pfad:"
+
+#: rc_option_editor.cc:2808
+msgid "Audio Unit"
+msgstr "Audio Unit"
+
+#: rc_option_editor.cc:2812
+msgid "Scan for AudioUnit Plugins on Application Start"
+msgstr "Bei Programmstart nach AudioUnit Plugins scannen"
+
+#: rc_option_editor.cc:2818
+msgid ""
+"<b>When enabled</b> Audio Unit Plugins are discovered on application start. "
+"When disabled AU plugins will only be available after triggering a 'Scan' "
+"manually. The first successful scan will enable AU auto-scan, Any crash "
+"during plugin discovery will disable it."
+msgstr ""
+"<b>Wenn aktiviert</b>, werden bei Programmstart AudioUnit Plugins entdeckt. "
+"Wenn nicht aktiviert, werden neue Plugins nur nach einem manuellen Scan "
+"verfügbar sein. Der erste erfolgreiche Scan wird weitere automatische AU-"
+"Scans aktivieren, ein Crash während der Pluginentdeckung wird sie "
+"deaktivieren."
+
+#: rc_option_editor.cc:2823
+msgid "AU Cache:"
+msgstr "AU Cache:"
+
+#: rc_option_editor.cc:2828
+msgid "AU Blacklist:"
+msgstr "AU Schwarzliste:"
+
+#: rc_option_editor.cc:2832
+msgid "Plugin GUI"
+msgstr "Plugin GUI"
+
+#: rc_option_editor.cc:2836
+msgid "Automatically open the plugin GUI when adding a new plugin"
+msgstr "Bei Hinzufügen eines neuen Plugins dessen GUI automatisch öffnen"
 
-#: rc_option_editor.cc:2751
-msgid "This requires restarting %1 before having an effect"
-msgstr "Diese Einstellung wird erst nach einem Neustart von %1 wirksam"
+#: rc_option_editor.cc:2847
+msgid "Disable Graphics Hardware Acceleration (requires restart)"
+msgstr "Deaktiviere Grafik-Hardwarebeschleunigung (benötigt Neustart)"
 
-#: rc_option_editor.cc:2752 rc_option_editor.cc:2755 rc_option_editor.cc:2764
-#: rc_option_editor.cc:2773 rc_option_editor.cc:2783 rc_option_editor.cc:2808
-#: rc_option_editor.cc:2823 rc_option_editor.cc:2836 rc_option_editor.cc:2845
+#: rc_option_editor.cc:2853
+msgid ""
+"Render large parts of the application user-interface in software, instead of "
+"using 2D-graphics acceleration.\n"
+"This requires restarting %1 before having an effect"
+msgstr ""
+"Software-Rendering für große Teile der Anwendungs-Benutzeroberfläche, statt "
+"2D-Grafik-Beschleunigung zu verwenden.\n"
+"Dies erfordert einen Neustart von %1, um Auswirkung zu zeigen"
+
+#: rc_option_editor.cc:2854 rc_option_editor.cc:2866 rc_option_editor.cc:2869
+#: rc_option_editor.cc:2878 rc_option_editor.cc:2887 rc_option_editor.cc:2906
+#: rc_option_editor.cc:2922 rc_option_editor.cc:2938 rc_option_editor.cc:2952
+#: rc_option_editor.cc:2961
 msgid "Preferences|GUI"
 msgstr "GUI"
 
-#: rc_option_editor.cc:2758
+#: rc_option_editor.cc:2860
+msgid "Possibly improve slow graphical performance (requires restart)"
+msgstr ""
+"Versuche, langsame Grafikperformance zu verbessern (erfordert Neustart)"
+
+#: rc_option_editor.cc:2865
+msgid ""
+"Disables hardware gradient rendering on buggy video drivers (\"buggy "
+"gradients patch\").\n"
+"This requires restarting %1 before having an effect"
+msgstr ""
+"Abschalten des Hardware-Rendering von Farbverläufen bei fehlerhaften "
+"Videotreibern (\"buggy gradients patch\").\n"
+"Diese Einstellung wird erst nach einem Neustart von %1 wirksam"
+
+#: rc_option_editor.cc:2872
 msgid "Graphically indicate mouse pointer hovering over various widgets"
 msgstr "Mouseover-Effekt über verschiedenen Anzeigen"
 
-#: rc_option_editor.cc:2767
+#: rc_option_editor.cc:2881
 msgid "Show tooltips if mouse hovers over a control"
 msgstr "Zeige Tooltips, wenn die Maus über einem Element schwebt"
 
-#: rc_option_editor.cc:2776
+#: rc_option_editor.cc:2890
 msgid "Use name highlight bars in region displays (requires a restart)"
 msgstr ""
 "Verwende Farbbalken zur Namenshervorhebung in der Regionendarstellung "
 "(erfordert Neustart)"
 
-#: rc_option_editor.cc:2789
-msgid "update transport clock display at FPS instead of every 100ms"
+#: rc_option_editor.cc:2898
+msgid "Update transport clock display at FPS instead of every 100ms"
 msgstr "Auffrischen der Transport-Uhranzeige in FPS statt alle 100 ms"
 
-#: rc_option_editor.cc:2799
+#: rc_option_editor.cc:2913
 msgid "Waveform image cache size (megabytes)"
 msgstr "Wellenformbild Cachegröße (Megabyte)"
 
-#: rc_option_editor.cc:2807
+#: rc_option_editor.cc:2921
 msgid ""
 "Increasing the cache size uses more memory to store waveform images, which "
 "can improve graphical performance."
@@ -10584,94 +11045,94 @@ msgstr ""
 "Ein größerer Cache benutzt mehr RAM-Speicher, was die Grafikperformance "
 "verbessern kann."
 
-#: rc_option_editor.cc:2814
+#: rc_option_editor.cc:2929
 msgid "Lock timeout (seconds)"
 msgstr "Sperr-Timeout (Sekunden)"
 
-#: rc_option_editor.cc:2822
+#: rc_option_editor.cc:2937
 msgid "Lock GUI after this many idle seconds (zero to never lock)"
 msgstr "Sperre GUI nach so vielen untätigen Sekunden (null, um nie zu sperren)"
 
-#: rc_option_editor.cc:2838
+#: rc_option_editor.cc:2954
 msgid "Mixer Strip"
 msgstr "Anzeige im Kanalzug"
 
-#: rc_option_editor.cc:2848
+#: rc_option_editor.cc:2964
 msgid "Use narrow strips in the mixer by default"
 msgstr "Standardmäßig schmale Kanalzüge verwenden"
 
-#: rc_option_editor.cc:2853 rc_option_editor.cc:2867 rc_option_editor.cc:2884
-#: rc_option_editor.cc:2900 rc_option_editor.cc:2916 rc_option_editor.cc:2930
-#: rc_option_editor.cc:2956 rc_option_editor.cc:2974 rc_option_editor.cc:2985
-#: rc_option_editor.cc:2992 rc_option_editor.cc:2994
+#: rc_option_editor.cc:2969 rc_option_editor.cc:2983 rc_option_editor.cc:3000
+#: rc_option_editor.cc:3016 rc_option_editor.cc:3032 rc_option_editor.cc:3046
+#: rc_option_editor.cc:3072 rc_option_editor.cc:3090 rc_option_editor.cc:3101
+#: rc_option_editor.cc:3108 rc_option_editor.cc:3110
 msgid "Preferences|Metering"
 msgstr "Pegelanzeige"
 
-#: rc_option_editor.cc:2857
+#: rc_option_editor.cc:2973
 msgid "Peak hold time"
 msgstr "Haltezeit für Spitzenwert"
 
-#: rc_option_editor.cc:2863
+#: rc_option_editor.cc:2979
 msgid "short"
 msgstr "Kurz"
 
-#: rc_option_editor.cc:2864
+#: rc_option_editor.cc:2980
 msgid "medium"
 msgstr "Mittel"
 
-#: rc_option_editor.cc:2865
+#: rc_option_editor.cc:2981
 msgid "long"
 msgstr "Lange"
 
-#: rc_option_editor.cc:2871
+#: rc_option_editor.cc:2987
 msgid "DPM fall-off"
 msgstr "Abfall der digitalen Pegelanzeige"
 
-#: rc_option_editor.cc:2877
+#: rc_option_editor.cc:2993
 msgid "slowest [6.6dB/sec]"
 msgstr "am langsamsten [6.6dB/sec]"
 
-#: rc_option_editor.cc:2878
+#: rc_option_editor.cc:2994
 msgid "slow [8.6dB/sec] (BBC PPM, EBU PPM)"
 msgstr "langsam [8.6dB/sec] (BBC PPM, EBU PPM)"
 
-#: rc_option_editor.cc:2879
+#: rc_option_editor.cc:2995
 msgid "moderate [12.0dB/sec] (DIN)"
 msgstr "moderat [12.0dB/sec] (DIN)"
 
-#: rc_option_editor.cc:2880
+#: rc_option_editor.cc:2996
 msgid "medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"
 msgstr "mittel [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"
 
-#: rc_option_editor.cc:2881
+#: rc_option_editor.cc:2997
 msgid "fast [20dB/sec]"
 msgstr "schnell [20dB/sec]"
 
-#: rc_option_editor.cc:2882
+#: rc_option_editor.cc:2998
 msgid "very fast [32dB/sec]"
 msgstr "sehr schnell [32dB/sec]"
 
-#: rc_option_editor.cc:2888
+#: rc_option_editor.cc:3004
 msgid "Meter line-up level; 0dBu"
 msgstr "Ausrichtung der Pegelanzeige; 0dBu"
 
-#: rc_option_editor.cc:2893 rc_option_editor.cc:2909
+#: rc_option_editor.cc:3009 rc_option_editor.cc:3025
 msgid "-24dBFS (SMPTE US: 4dBu = -20dBFS)"
 msgstr "-24dBFS (SMPTE US: 4dBu = -20dBFS)"
 
-#: rc_option_editor.cc:2894 rc_option_editor.cc:2910
+#: rc_option_editor.cc:3010 rc_option_editor.cc:3026
 msgid "-20dBFS (SMPTE RP.0155)"
 msgstr "-20dBFS (SMPTE RP.0155)"
 
-#: rc_option_editor.cc:2895 rc_option_editor.cc:2911
+#: rc_option_editor.cc:3011 rc_option_editor.cc:3027
 msgid "-18dBFS (EBU, BBC)"
 msgstr "-18dBFS (EBU, BBC)"
 
-#: rc_option_editor.cc:2896 rc_option_editor.cc:2912
+#: rc_option_editor.cc:3012 rc_option_editor.cc:3028
 msgid "-15dBFS (DIN)"
 msgstr "-15dBFS (DIN)"
 
-#: rc_option_editor.cc:2898
+#: rc_option_editor.cc:3014
 msgid ""
 "Configure meter-marks and color-knee point for dBFS scale DPM, set reference "
 "level for IEC1/Nordic, IEC2 PPM and VU meter."
@@ -10679,51 +11140,51 @@ msgstr ""
 "Konfiguriere Skalierung und Farbschwellwert für DPM mit dBFS-Skala, "
 "setzeReferenzpegel  für IEC1/Nordisch, IEC2 PPM und VU Pegelanzeigen."
 
-#: rc_option_editor.cc:2904
+#: rc_option_editor.cc:3020
 msgid "IEC1/DIN Meter line-up level; 0dBu"
 msgstr "Ausrichtung der IEC1/DIN Pegelanzeige; 0dBu"
 
-#: rc_option_editor.cc:2914
+#: rc_option_editor.cc:3030
 msgid "Reference level for IEC1/DIN meter."
 msgstr "Referenzpegel  für IEC1/DIN Pegelanzeige."
 
-#: rc_option_editor.cc:2920
+#: rc_option_editor.cc:3036
 msgid "VU Meter standard"
 msgstr "Standard für VU-Pegelanzeige"
 
-#: rc_option_editor.cc:2925
+#: rc_option_editor.cc:3041
 msgid "0VU = -2dBu (France)"
 msgstr "0VU = -2dBu (Frankreich)"
 
-#: rc_option_editor.cc:2926
+#: rc_option_editor.cc:3042
 msgid "0VU = 0dBu (North America, Australia)"
 msgstr "0VU = 0dBu (Nordamerika, Australien)"
 
-#: rc_option_editor.cc:2927
+#: rc_option_editor.cc:3043
 msgid "0VU = +4dBu (standard)"
 msgstr "0VU = +4dBu (Standard)"
 
-#: rc_option_editor.cc:2928
+#: rc_option_editor.cc:3044
 msgid "0VU = +8dBu"
 msgstr "0VU = +8dBu"
 
-#: rc_option_editor.cc:2934
+#: rc_option_editor.cc:3050
 msgid "Peak threshold [dBFS]"
 msgstr "Schwelle für Spitzenwert [dBFS]"
 
-#: rc_option_editor.cc:2943
+#: rc_option_editor.cc:3059
 msgid "Default Meter Type for Master Bus"
 msgstr "Voreingestellter Metertyp für Masterbus"
 
-#: rc_option_editor.cc:2961
+#: rc_option_editor.cc:3077
 msgid "Default Meter Type for Busses"
 msgstr "Voreingestellter Metertyp für Busse"
 
-#: rc_option_editor.cc:2978
+#: rc_option_editor.cc:3094
 msgid "Default Meter Type for Tracks"
 msgstr "Voreingestellter Metertyp für Spuren"
 
-#: rc_option_editor.cc:2990
+#: rc_option_editor.cc:3106
 msgid ""
 "Specify the audio signal level in dbFS at and above which the meter-peak "
 "indicator will flash red."
@@ -10731,67 +11192,75 @@ msgstr ""
 "Geben Sie den Signalpegel in dbFS an, bei dessen Erreichen oder "
 "Ãœberschreitung die Spitzenwertanzeige in der Pegelanzeige rot blinkt"
 
-#: rc_option_editor.cc:2997
+#: rc_option_editor.cc:3113
 msgid "LED meter style"
 msgstr "Pegelanzeigen im LED-Stil"
 
-#: rc_option_editor.cc:3005
+#: rc_option_editor.cc:3121
 msgid "Theme"
 msgstr "Thema"
 
-#: region_editor.cc:79
+#: rc_option_editor.cc:3193
+msgid "Set Linux VST Search Path"
+msgstr "Linux VST Suchpfad setzen"
+
+#: rc_option_editor.cc:3207
+msgid "Set Windows VST Search Path"
+msgstr "Windows VST Suchpfad setzen"
+
+#: region_editor.cc:81
 msgid "audition this region"
 msgstr "Diese Region vorhören"
 
-#: region_editor.cc:88 region_layering_order_editor.cc:75
+#: region_editor.cc:90 region_layering_order_editor.cc:75
 msgid "Position:"
 msgstr "Position:"
 
-#: region_editor.cc:90 add_video_dialog.cc:155
+#: region_editor.cc:92 add_video_dialog.cc:155
 msgid "End:"
 msgstr "Ende:"
 
-#: region_editor.cc:92 sfdb_ui.cc:144
+#: region_editor.cc:94 sfdb_ui.cc:145
 msgid "Length:"
 msgstr "Länge:"
 
-#: region_editor.cc:94
+#: region_editor.cc:96
 msgid "Sync point (relative to region):"
 msgstr "Synchronisationspunkt (relativ zur Region)"
 
-#: region_editor.cc:96
+#: region_editor.cc:98
 msgid "Sync point (absolute):"
 msgstr "Synchronisationspunkt (absolut)"
 
-#: region_editor.cc:98
+#: region_editor.cc:100
 msgid "File start:"
 msgstr "Dateibeginn:"
 
-#: region_editor.cc:102
+#: region_editor.cc:104
 msgid "Sources:"
 msgstr "Quellen:"
 
-#: region_editor.cc:104
+#: region_editor.cc:106
 msgid "Source:"
 msgstr "Quelle:"
 
-#: region_editor.cc:166
+#: region_editor.cc:168
 msgid "Region '%1'"
 msgstr "Region '%1'"
 
-#: region_editor.cc:277
+#: region_editor.cc:279
 msgid "change region start position"
 msgstr "Startposition der Region ändern"
 
-#: region_editor.cc:297
+#: region_editor.cc:299
 msgid "change region end position"
 msgstr "Endposition der Region ändern"
 
-#: region_editor.cc:320
+#: region_editor.cc:322
 msgid "change region length"
 msgstr "Länge der Region verändern"
 
-#: region_editor.cc:414 region_editor.cc:426
+#: region_editor.cc:416 region_editor.cc:428
 msgid "change region sync point"
 msgstr "Synchronisationspunkt der Region ändern"
 
@@ -10811,33 +11280,33 @@ msgstr "Spur:"
 msgid "Choose Top Region"
 msgstr "Oberste Region auswählen"
 
-#: region_view.cc:277
+#: region_view.cc:270
 msgid "SilenceText"
 msgstr "StilleText"
 
-#: region_view.cc:292 region_view.cc:311
+#: region_view.cc:285 region_view.cc:304
 msgid "minutes"
 msgstr "Minuten"
 
-#: region_view.cc:295 region_view.cc:314
+#: region_view.cc:288 region_view.cc:307
 msgid "msecs"
 msgstr "ms"
 
-#: region_view.cc:298 region_view.cc:317
+#: region_view.cc:291 region_view.cc:310
 msgid "secs"
 msgstr "s"
 
-#: region_view.cc:301
+#: region_view.cc:294
 msgid "%1 silent segment"
 msgid_plural "%1 silent segments"
 msgstr[0] "%1 stilles Segment"
 msgstr[1] "%1 stille Segmente"
 
-#: region_view.cc:303
+#: region_view.cc:296
 msgid "shortest = %1 %2"
 msgstr "kürzestes = %1 %2"
 
-#: region_view.cc:320
+#: region_view.cc:313
 msgid ""
 "\n"
 "  (shortest audible segment = %1 %2)"
@@ -10913,7 +11382,7 @@ msgstr "Erkennungsfunktion"
 msgid "Trigger gap"
 msgstr "Mindestauslöseabstand"
 
-#: rhythm_ferret.cc:122 strip_silence_dialog.cc:64
+#: rhythm_ferret.cc:122 strip_silence_dialog.cc:65
 msgid "Threshold"
 msgstr "Threshold"
 
@@ -10957,7 +11426,7 @@ msgstr "Aufnahmestatus"
 msgid "Active state"
 msgstr "Aktiv-Status"
 
-#: route_group_dialog.cc:53 route_group_dialog.cc:82 theme_manager.cc:92
+#: route_group_dialog.cc:53 route_group_dialog.cc:82 theme_manager.cc:87
 msgid "Color"
 msgstr "Farbe"
 
@@ -11010,292 +11479,292 @@ msgstr "KEINE SPUR"
 msgid "No Track or Bus Selected"
 msgstr "Keine Spuren oder Busse ausgewählt"
 
-#: route_time_axis.cc:104
+#: route_time_axis.cc:105
 msgid "RTAV|G"
 msgstr "G"
 
-#: route_time_axis.cc:105
+#: route_time_axis.cc:106
 msgid "RTAV|P"
 msgstr "P"
 
-#: route_time_axis.cc:106
+#: route_time_axis.cc:107
 msgid "RTAV|A"
 msgstr "A"
 
-#: route_time_axis.cc:183
+#: route_time_axis.cc:184
 msgid "Record (Right-click for Step Edit)"
 msgstr "Aufnahme (Rechtsklick für Step Entry)"
 
-#: route_time_axis.cc:186
+#: route_time_axis.cc:187
 msgid "Record"
 msgstr "Aufnahme"
 
-#: route_time_axis.cc:256
+#: route_time_axis.cc:257
 msgid "Route Group"
 msgstr "Bearbeitungsgruppe"
 
-#: route_time_axis.cc:266
+#: route_time_axis.cc:267
 msgid "MIDI Controllers and Automation"
 msgstr "MIDI-Controller und Automation"
 
-#: route_time_axis.cc:497
+#: route_time_axis.cc:498
 msgid "Show All Automation"
 msgstr "Alle Automationen anzeigen"
 
-#: route_time_axis.cc:500
+#: route_time_axis.cc:501
 msgid "Show Existing Automation"
 msgstr "Genutzte Automationen zeigen"
 
-#: route_time_axis.cc:503
+#: route_time_axis.cc:504
 msgid "Hide All Automation"
 msgstr "Alle Automationen verbergen"
 
-#: route_time_axis.cc:512
+#: route_time_axis.cc:513
 msgid "Processor automation"
 msgstr "Prozessorautomation"
 
-#: route_time_axis.cc:519
+#: route_time_axis.cc:520
 msgid "Fader"
 msgstr "Fader"
 
-#: route_time_axis.cc:546
+#: route_time_axis.cc:547
 msgid "Pan"
 msgstr "Pan"
 
-#: route_time_axis.cc:637
+#: route_time_axis.cc:638
 msgid "Overlaid"
 msgstr "Overlaid"
 
-#: route_time_axis.cc:643
+#: route_time_axis.cc:644
 msgid "Stacked"
 msgstr "Stacked"
 
-#: route_time_axis.cc:651
+#: route_time_axis.cc:652
 msgid "Layers"
 msgstr "Layers"
 
-#: route_time_axis.cc:720
+#: route_time_axis.cc:721
 msgid "Automatic (based on I/O connections)"
 msgstr "Automatisch (auf den I/O Verbindungen basierend)"
 
-#: route_time_axis.cc:729
+#: route_time_axis.cc:730
 msgid "(Currently: Existing Material)"
 msgstr "(Momentan: An vorhandenem Material ausrichten)"
 
-#: route_time_axis.cc:732
+#: route_time_axis.cc:733
 msgid "(Currently: Capture Time)"
 msgstr "(Momentan: An Aufnahmezeit ausrichten)"
 
-#: route_time_axis.cc:740
-msgid "Align With Existing Material"
-msgstr "An vorhandenem Material ausrichten"
+#: route_time_axis.cc:741
+msgid "Align with Existing Material"
+msgstr "An existierendem Material ausrichten"
 
-#: route_time_axis.cc:745
-msgid "Align With Capture Time"
+#: route_time_axis.cc:746
+msgid "Align with Capture Time"
 msgstr "An Aufnahmezeit ausrichten"
 
-#: route_time_axis.cc:750
+#: route_time_axis.cc:751
 msgid "Alignment"
 msgstr "Ausrichtung"
 
-#: route_time_axis.cc:785
+#: route_time_axis.cc:786
 msgid "Normal Mode"
 msgstr "Normaler Modus"
 
-#: route_time_axis.cc:791
+#: route_time_axis.cc:792
 msgid "Tape Mode"
 msgstr "Band-Modus"
 
-#: route_time_axis.cc:797
+#: route_time_axis.cc:798
 msgid "Non-Layered Mode"
 msgstr "Non-Layered Mode"
 
-#: route_time_axis.cc:803
+#: route_time_axis.cc:804
 msgid "Record Mode"
 msgstr "Aufnahmemodus"
 
-#: route_time_axis.cc:810 route_time_axis.cc:1801
+#: route_time_axis.cc:811 route_time_axis.cc:1806
 msgid "Playlist"
 msgstr "Wiedergabeliste"
 
-#: route_time_axis.cc:1104
+#: route_time_axis.cc:1109
 msgid "Rename Playlist"
 msgstr "Wiedergabeliste umbenennen"
 
-#: route_time_axis.cc:1105
+#: route_time_axis.cc:1110
 msgid "New name for playlist:"
 msgstr "Neuer Name für Wiedergabeliste:"
 
-#: route_time_axis.cc:1190
+#: route_time_axis.cc:1195
 msgid "New Copy Playlist"
 msgstr "Neue Kopie der Wiedergabeliste"
 
-#: route_time_axis.cc:1191 route_time_axis.cc:1244
+#: route_time_axis.cc:1196 route_time_axis.cc:1249
 msgid "Name for new playlist:"
 msgstr "Name für die neue Wiedergabeliste:"
 
-#: route_time_axis.cc:1243
+#: route_time_axis.cc:1248
 msgid "New Playlist"
 msgstr "Neue Wiedergabeliste"
 
-#: route_time_axis.cc:1447
+#: route_time_axis.cc:1452
 msgid "You cannot create a track with that name as it is reserved for %1"
 msgstr ""
 "Sie können keine Spur mit einem Namen erstellen, der für %1 reserviert ist."
 
-#: route_time_axis.cc:1690
+#: route_time_axis.cc:1695
 msgid "New Copy..."
 msgstr "Neue Kopie..."
 
-#: route_time_axis.cc:1694
+#: route_time_axis.cc:1699
 msgid "New Take"
 msgstr "Neuer Take"
 
-#: route_time_axis.cc:1695
+#: route_time_axis.cc:1700
 msgid "Copy Take"
 msgstr "Take kopieren"
 
-#: route_time_axis.cc:1700
+#: route_time_axis.cc:1705
 msgid "Clear Current"
 msgstr "Aktuelle leeren"
 
-#: route_time_axis.cc:1703
-msgid "Select From All..."
+#: route_time_axis.cc:1708
+msgid "Select from All..."
 msgstr "Aus allen auswählen..."
 
-#: route_time_axis.cc:1791
+#: route_time_axis.cc:1796
 msgid "Take: %1.%2"
 msgstr "Take: %1.%2"
 
-#: route_time_axis.cc:2197 selection.cc:1007 selection.cc:1061
+#: route_time_axis.cc:2202 selection.cc:1009 selection.cc:1063
 msgid "programming error: "
 msgstr "Programmierfehler:"
 
-#: route_time_axis.cc:2613
+#: route_time_axis.cc:2622
 msgid "Underlays"
 msgstr "Darunterliegende"
 
-#: route_time_axis.cc:2616
+#: route_time_axis.cc:2625
 msgid "Remove \"%1\""
 msgstr "Lösche \"%1\""
 
-#: route_time_axis.cc:2666 route_time_axis.cc:2703
+#: route_time_axis.cc:2675 route_time_axis.cc:2712
 msgid "programming error: underlay reference pointer pairs are inconsistent!"
 msgstr "programming error: underlay reference pointer pairs are inconsistent!"
 
-#: route_time_axis.cc:2730
+#: route_time_axis.cc:2739
 msgid "After-fade listen (AFL)"
 msgstr "After-Fader (AFL)"
 
-#: route_time_axis.cc:2734
+#: route_time_axis.cc:2743
 msgid "Pre-fade listen (PFL)"
 msgstr "Pre-Fader (PFL)"
 
-#: route_ui.cc:142
+#: route_ui.cc:153
 msgid "Mute this track"
 msgstr "Diese Spur stummschalten"
 
-#: route_ui.cc:146
+#: route_ui.cc:157
 msgid "Mute other (non-soloed) tracks"
 msgstr "Andere (nicht Solo-)Spuren stummschalten"
 
-#: route_ui.cc:152
+#: route_ui.cc:163
 msgid "Enable recording on this track"
 msgstr "Aktiviere die Aufnahme auf dieser Spur"
 
-#: route_ui.cc:160
+#: route_ui.cc:171
 msgid "make mixer strips show sends to this bus"
 msgstr "Kanalzüge zeigen Sends zu diesem Bus"
 
-#: route_ui.cc:165
+#: route_ui.cc:176
 msgid "Monitor input"
 msgstr "Eingang abhören"
 
-#: route_ui.cc:171
+#: route_ui.cc:182
 msgid "Monitor playback"
 msgstr "Vorhandenes Material abhören"
 
-#: route_ui.cc:678
+#: route_ui.cc:691
 msgid "Not connected to AudioEngine - cannot engage record"
 msgstr "Nicht mit Audio-Engine verbunden - Aufnahme nicht möglich"
 
-#: route_ui.cc:877
+#: route_ui.cc:890
 msgid "Step Entry"
 msgstr "Eingabemodus (Step Entry)"
 
-#: route_ui.cc:950
+#: route_ui.cc:963
 msgid "Assign all tracks (prefader)"
 msgstr "Alle Audiospuren zuweisen (Pre-Fader)"
 
-#: route_ui.cc:954
+#: route_ui.cc:967
 msgid "Assign all tracks and buses (prefader)"
 msgstr "Alle Audiospuren und Busse zuweisen (Pre-Fader)"
 
-#: route_ui.cc:958
+#: route_ui.cc:971
 msgid "Assign all tracks (postfader)"
 msgstr "Alle Audiospuren zuweisen (Post-Fader)"
 
-#: route_ui.cc:962
+#: route_ui.cc:975
 msgid "Assign all tracks and buses (postfader)"
 msgstr "Alle Audiospuren und Busse zuweisen (Post-Fader)"
 
-#: route_ui.cc:966
+#: route_ui.cc:979
 msgid "Assign selected tracks (prefader)"
 msgstr "Ausgewählte Audiospuren zuweisen (Pre-Fader)"
 
-#: route_ui.cc:970
+#: route_ui.cc:983
 msgid "Assign selected tracks and buses (prefader)"
 msgstr "Ausgewählte Audiospuren und Busse zuweisen (Pre-Fader)"
 
-#: route_ui.cc:973
+#: route_ui.cc:986
 msgid "Assign selected tracks (postfader)"
 msgstr "Ausgewählte Audiospuren zuweisen (Post-Fader)"
 
-#: route_ui.cc:977
+#: route_ui.cc:990
 msgid "Assign selected tracks and buses (postfader)"
 msgstr "Ausgewählte Audiospuren und Busse zuweisen (Post-Fader)"
 
-#: route_ui.cc:980
+#: route_ui.cc:993
 msgid "Copy track/bus gains to sends"
 msgstr "Lautstärken der Spuren/Busse auf ihre Sends kopieren"
 
-#: route_ui.cc:981
+#: route_ui.cc:994
 msgid "Set sends gain to -inf"
 msgstr "Setze Sends-Lautstärken to -inf"
 
-#: route_ui.cc:982
+#: route_ui.cc:995
 msgid "Set sends gain to 0dB"
 msgstr "Setze Sends-Lautstärken to 0dB"
 
-#: route_ui.cc:1301
+#: route_ui.cc:1314
 msgid "Solo Isolate"
 msgstr "Isoliertes Solo"
 
-#: route_ui.cc:1308
+#: route_ui.cc:1321
 msgid "Solo Safe"
 msgstr "Solo sperren"
 
-#: route_ui.cc:1330
+#: route_ui.cc:1343
 msgid "Pre Fader Sends"
 msgstr "Pre-Fader Sends"
 
-#: route_ui.cc:1336
+#: route_ui.cc:1349
 msgid "Post Fader Sends"
 msgstr "Post-Fader Sends"
 
-#: route_ui.cc:1342
+#: route_ui.cc:1355
 msgid "Control Outs"
 msgstr "Vorhörausgang"
 
-#: route_ui.cc:1348
+#: route_ui.cc:1361
 msgid "Main Outs"
 msgstr "Hauptausgänge"
 
-#: route_ui.cc:1485
+#: route_ui.cc:1527
 msgid "Color Selection"
 msgstr "Farbauswahl"
 
-#: route_ui.cc:1550
+#: route_ui.cc:1592
 msgid ""
 "The use of colons (':') is discouraged in track and bus names.\n"
 "Do you want to use this new name?"
@@ -11304,51 +11773,51 @@ msgstr ""
 "wird nicht empfohlen.\n"
 "Wollen Sie diesen neuen Namen verwenden?"
 
-#: route_ui.cc:1554
+#: route_ui.cc:1596
 msgid "Use the new name"
 msgstr "Neuen Namen verwenden"
 
-#: route_ui.cc:1555
+#: route_ui.cc:1597
 msgid "Re-edit the name"
 msgstr "Namen bearbeiten"
 
-#: route_ui.cc:1568
+#: route_ui.cc:1610
 msgid "Rename Track"
 msgstr "Spur umbenennen"
 
-#: route_ui.cc:1570
+#: route_ui.cc:1612
 msgid "Rename Bus"
 msgstr "Bus umbenennen"
 
-#: route_ui.cc:1638
+#: route_ui.cc:1680
 msgid ": comment editor"
 msgstr ": Kommentare bearbeiten"
 
-#: route_ui.cc:1804
+#: route_ui.cc:1852
 msgid " latency"
 msgstr " Latenz"
 
-#: route_ui.cc:1817
+#: route_ui.cc:1892
 msgid "Cannot create route template directory %1"
 msgstr "Kann das Vorlagenverzeichnis für Spuren/Busse %1 nicht erzeugen"
 
-#: route_ui.cc:1823
+#: route_ui.cc:1898
 msgid "Save As Template"
 msgstr "Als Vorlage speichern"
 
-#: route_ui.cc:1824
+#: route_ui.cc:1899
 msgid "Template name:"
 msgstr "Name der Vorlage:"
 
-#: route_ui.cc:1905
+#: route_ui.cc:1976
 msgid "Remote Control ID"
 msgstr "ID für Fernsteuerung"
 
-#: route_ui.cc:1915
+#: route_ui.cc:1986
 msgid "Remote control ID:"
 msgstr "ID für Fernsteuerung:"
 
-#: route_ui.cc:1929
+#: route_ui.cc:2000
 msgid ""
 "The remote control ID of %1 is: %2\n"
 "\n"
@@ -11360,15 +11829,15 @@ msgstr ""
 "\n"
 "Die Fernbedienungs-ID von %3 kann nicht geändert werden."
 
-#: route_ui.cc:1933
+#: route_ui.cc:2004
 msgid "the master bus"
 msgstr "der Master-Bus"
 
-#: route_ui.cc:1933
+#: route_ui.cc:2004
 msgid "the monitor bus"
 msgstr "der Monitor-Bus"
 
-#: route_ui.cc:1935
+#: route_ui.cc:2006
 msgid ""
 "The remote control ID of %5 is: %2\n"
 "\n"
@@ -11387,7 +11856,7 @@ msgstr ""
 "%3Benutzen Sie den Reiter GUI im Fenster \"Einstellungen\", um dies zu ändern"
 "%4"
 
-#: route_ui.cc:1992
+#: route_ui.cc:2063
 msgid ""
 "Left-click to invert (phase reverse) channel %1 of this track.  Right-click "
 "to show menu."
@@ -11395,7 +11864,7 @@ msgstr ""
 "Linksklick, um die Phase von Kanal %1 zu invertieren. Rechtsklick zeigt das "
 "Menü."
 
-#: route_ui.cc:1994
+#: route_ui.cc:2065
 msgid "Click to show a menu of channels for inversion (phase reverse)"
 msgstr ""
 "Klicken, um ein Menü zum Invertieren der Kanäle (Phasendrehung) anzuzeigen"
@@ -11440,122 +11909,130 @@ msgstr "Projektordner"
 msgid "Send "
 msgstr "Send "
 
-#: session_dialog.cc:61
+#: session_dialog.cc:71
 msgid "Session Setup"
 msgstr "Projekteinrichtung"
 
-#: session_dialog.cc:66
+#: session_dialog.cc:76
 msgid "Advanced options ..."
 msgstr "Erweiterte Einstellungen..."
 
-#: session_dialog.cc:263
+#: session_dialog.cc:163 session_dialog.cc:394
+msgid "Recent Sessions"
+msgstr "Zuletzt verwendete Projekte"
+
+#: session_dialog.cc:311
+msgid "Sample Rate"
+msgstr "Samplerate"
+
+#: session_dialog.cc:312
+msgid "File Resolution"
+msgstr "Dateiauflösung"
+
+#: session_dialog.cc:313
+msgid "Last Modified"
+msgstr "Zuletzt geändert"
+
+#: session_dialog.cc:338
 msgid "New Session"
 msgstr "Neues Projekt"
 
-#: session_dialog.cc:301
+#: session_dialog.cc:376
 msgid "Check the website for more..."
 msgstr "Informieren Sie sich auf der Webseite weiter..."
 
-#: session_dialog.cc:304
+#: session_dialog.cc:379
 msgid "Click to open the program website in your web browser"
 msgstr "Klicken Sie, um die Webseite in Ihrem Web-Browse zu öffnen"
 
-#: session_dialog.cc:324
-msgid "Sample Rate"
-msgstr "Samplerate"
-
-#: session_dialog.cc:325
-msgid "Disk Format"
-msgstr "Dateiformat"
-
-#: session_dialog.cc:343
+#: session_dialog.cc:401
 msgid "Select session file"
 msgstr "Projektdatei auswählen"
 
-#: session_dialog.cc:358
+#: session_dialog.cc:414
 msgid "Other Sessions"
 msgstr "Andere Projekte"
 
-#: session_dialog.cc:384
+#: session_dialog.cc:421
+msgid "Safe Mode: Disable all Plugins"
+msgstr "Abgesicherter Modus: Alle Plugins abschalten"
+
+#: session_dialog.cc:451
 msgid "Open"
 msgstr "Öffnen"
 
-#: session_dialog.cc:451
+#: session_dialog.cc:518
 msgid "Session name:"
 msgstr "Projektname:"
 
-#: session_dialog.cc:473
+#: session_dialog.cc:540
 msgid "Create session folder in:"
 msgstr "Ort des Projektverzeichnisses:"
 
-#: session_dialog.cc:496
+#: session_dialog.cc:561
 msgid "Select folder for session"
 msgstr "Ordner für Projekt wählen"
 
-#: session_dialog.cc:525
+#: session_dialog.cc:588
 msgid "Use this template"
 msgstr "Diese Vorlage verwenden"
 
-#: session_dialog.cc:528
+#: session_dialog.cc:591
 msgid "no template"
 msgstr "keine Vorlage"
 
-#: session_dialog.cc:663 session_dialog.cc:699
-msgid "32 bit float"
-msgstr "32 Bit float"
+#: session_dialog.cc:743 session_dialog.cc:790
+msgid "32-bit float"
+msgstr "32-bit float"
 
-#: session_dialog.cc:666 session_dialog.cc:702
-msgid "24 bit"
-msgstr "24 Bit"
+#: session_dialog.cc:746 session_dialog.cc:793
+msgid "24-bit"
+msgstr "24-bit"
 
-#: session_dialog.cc:669 session_dialog.cc:705
-msgid "16 bit"
-msgstr "16 Bit"
+#: session_dialog.cc:749 session_dialog.cc:796
+msgid "16-bit"
+msgstr "16-bit"
 
-#: session_dialog.cc:747 session_dialog.cc:748 session_dialog.cc:749
+#: session_dialog.cc:874 session_dialog.cc:875 session_dialog.cc:876
 msgid "channels"
 msgstr "Kanäle"
 
-#: session_dialog.cc:763
+#: session_dialog.cc:890
 msgid "<b>Busses</b>"
 msgstr "<b>Busse</b>"
 
-#: session_dialog.cc:764
+#: session_dialog.cc:891
 msgid "<b>Inputs</b>"
 msgstr "<b>Eingänge</b>"
 
-#: session_dialog.cc:765
+#: session_dialog.cc:892
 msgid "<b>Outputs</b>"
 msgstr "<b>Ausgänge</b>"
 
-#: session_dialog.cc:773
+#: session_dialog.cc:900
 msgid "Create master bus"
 msgstr "Master-Bus erstellen"
 
-#: session_dialog.cc:783
+#: session_dialog.cc:910
 msgid "Automatically connect to physical inputs"
 msgstr "Automatisch mit Audioeingängen verbinden"
 
-#: session_dialog.cc:790 session_dialog.cc:849
+#: session_dialog.cc:917 session_dialog.cc:976
 msgid "Use only"
 msgstr "Benutze nur"
 
-#: session_dialog.cc:843
+#: session_dialog.cc:970
 msgid "Automatically connect outputs"
 msgstr "Ausgänge automatisch verbinden"
 
-#: session_dialog.cc:865
+#: session_dialog.cc:992
 msgid "... to master bus"
 msgstr "... mit dem Master-Bus"
 
-#: session_dialog.cc:875
+#: session_dialog.cc:1002
 msgid "... to physical outputs"
 msgstr "... mit den Audioausgängen"
 
-#: session_import_dialog.cc:65
-msgid "Import from Session"
-msgstr "Aus Projekt importieren"
-
 #: session_import_dialog.cc:74
 msgid "Elements"
 msgstr "Elemente"
@@ -11926,166 +12403,182 @@ msgid "Destructive crossfade length"
 msgstr "Länge für destruktive Crossfades"
 
 #: session_option_editor.cc:146
+msgid "Declick when transport starts and stops"
+msgstr "Klickgeräusch vermeiden, wenn Wiedergabe beginnt und stoppt"
+
+#: session_option_editor.cc:153
+msgid "Declick when monitor state changes"
+msgstr "Klicken vermeiden, wenn sich der Monitorzustand ändert"
+
+#: session_option_editor.cc:160
 msgid "Region fades active"
 msgstr "Regionen Fade-Ins/Fade-Outs sind aktiv"
 
-#: session_option_editor.cc:153
+#: session_option_editor.cc:167
 msgid "Region fades visible"
 msgstr "Regionen Fade-Ins/Fade-Outs sind sichtbar"
 
-#: session_option_editor.cc:160 session_option_editor.cc:173
-#: session_option_editor.cc:187
+#: session_option_editor.cc:174 session_option_editor.cc:187
+#: session_option_editor.cc:208
 msgid "Media"
 msgstr "Medien"
 
-#: session_option_editor.cc:160
+#: session_option_editor.cc:174
 msgid "Audio file format"
 msgstr "Audio-Dateiformat"
 
-#: session_option_editor.cc:164
+#: session_option_editor.cc:178
 msgid "Sample format"
 msgstr "Sampleformat"
 
-#: session_option_editor.cc:169
+#: session_option_editor.cc:183
 msgid "32-bit floating point"
 msgstr "32-bit floating point"
 
-#: session_option_editor.cc:170
+#: session_option_editor.cc:184
 msgid "24-bit integer"
 msgstr "24-bit integer"
 
-#: session_option_editor.cc:171
+#: session_option_editor.cc:185
 msgid "16-bit integer"
 msgstr "16-bit integer"
 
-#: session_option_editor.cc:177
+#: session_option_editor.cc:191
 msgid "File type"
 msgstr "Dateiformat"
 
-#: session_option_editor.cc:182
-msgid "Broadcast WAVE"
-msgstr "Broadcast WAVE"
+#: session_option_editor.cc:196
+msgid "Broadcast WAVE (4GB size limit)"
+msgstr "Broadcast WAVE (4GB Größenlimit)"
 
-#: session_option_editor.cc:183
-msgid "WAVE"
-msgstr "WAVE"
+#: session_option_editor.cc:198
+msgid "Broadcast RF64"
+msgstr "Broadcast RF64"
 
-#: session_option_editor.cc:184
+#: session_option_editor.cc:200
+msgid "WAVE (4GB size limit)"
+msgstr "WAVE (4GB Größenlimit)"
+
+#: session_option_editor.cc:201
 msgid "WAVE-64"
 msgstr "WAVE-64"
 
-#: session_option_editor.cc:189
+#: session_option_editor.cc:205
+msgid "RF64 (WAV compatible)"
+msgstr "RF64 (WAV kompatibel)"
+
+#: session_option_editor.cc:210
 msgid "File locations"
 msgstr "Dateipfade"
 
-#: session_option_editor.cc:191
+#: session_option_editor.cc:212
 msgid "Search for audio files in:"
 msgstr "Suche hier nach Audiodateien:"
 
-#: session_option_editor.cc:197
+#: session_option_editor.cc:218
 msgid "Search for MIDI files in:"
 msgstr "Suche hier nach MIDI-Dateien:"
 
-#: session_option_editor.cc:206 session_option_editor.cc:218
-#: session_option_editor.cc:228 session_option_editor.cc:239
+#: session_option_editor.cc:227 session_option_editor.cc:239
+#: session_option_editor.cc:249 session_option_editor.cc:260
 msgid "Filenames"
 msgstr "Dateinamen"
 
-#: session_option_editor.cc:206
+#: session_option_editor.cc:227
 msgid "File Naming"
 msgstr "Dateibenennung"
 
-#: session_option_editor.cc:212
+#: session_option_editor.cc:233
 msgid "Prefix Track number"
 msgstr "Füge Spurnummer vorne ein"
 
-#: session_option_editor.cc:217
+#: session_option_editor.cc:238
 msgid ""
 "Adds the current track number to the beginning of the recorded file name."
 msgstr ""
 "Fügt die momentane Spurnummer am Beginn des Dateinamens der Aufnahme hinzu."
 
-#: session_option_editor.cc:222
+#: session_option_editor.cc:243
 msgid "Prefix Take Name"
 msgstr "Füge Takenamen vorne ein"
 
-#: session_option_editor.cc:227
+#: session_option_editor.cc:248
 msgid "Adds the Take Name to the beginning of the recorded file name."
 msgstr "Fügt den Take-Namen am Beginn des Dateinamens der Aufnahme hinzu."
 
-#: session_option_editor.cc:232
+#: session_option_editor.cc:253
 msgid "Take Name"
 msgstr "Name übernehmen"
 
-#: session_option_editor.cc:245
+#: session_option_editor.cc:266
 msgid ""
 "Track Input Monitoring automatically follows transport state (\"auto-input\")"
 msgstr ""
 "Spur-Eingangs-Monitoring folgt automatisch dem Transportstatus (\"auto-input"
 "\")"
 
-#: session_option_editor.cc:252
+#: session_option_editor.cc:273
 msgid "Use monitor section in this session"
 msgstr "In diesem Projekt eine Monitorsektion verwenden"
 
-#: session_option_editor.cc:257 session_option_editor.cc:259
-#: session_option_editor.cc:266 session_option_editor.cc:273
-#: session_option_editor.cc:280 session_option_editor.cc:282
-#: session_option_editor.cc:289 session_option_editor.cc:296
-#: session_option_editor.cc:303 session_option_editor.cc:310
-#: session_option_editor.cc:312
+#: session_option_editor.cc:278 session_option_editor.cc:280
+#: session_option_editor.cc:287 session_option_editor.cc:294
+#: session_option_editor.cc:301 session_option_editor.cc:303
+#: session_option_editor.cc:310 session_option_editor.cc:317
+#: session_option_editor.cc:324 session_option_editor.cc:331
+#: session_option_editor.cc:333
 msgid "Meterbridge"
 msgstr "Meterbridge"
 
-#: session_option_editor.cc:257
+#: session_option_editor.cc:278
 msgid "Route Display"
 msgstr "Routenanzeige"
 
-#: session_option_editor.cc:261
+#: session_option_editor.cc:282
 msgid "Show Midi Tracks"
 msgstr "Zeige MIDI-Spuren"
 
-#: session_option_editor.cc:268
+#: session_option_editor.cc:289
 msgid "Show Busses"
 msgstr "Zeige Busse"
 
-#: session_option_editor.cc:275
+#: session_option_editor.cc:296
 msgid "Include Master Bus"
 msgstr "Zeige Master-Bus"
 
-#: session_option_editor.cc:280
+#: session_option_editor.cc:301
 msgid "Button Area"
 msgstr "Schaltflächenbereich"
 
-#: session_option_editor.cc:284
+#: session_option_editor.cc:305
 msgid "Rec-enable Button"
 msgstr "Schaltfläche für Aufnahmebereitschaft"
 
-#: session_option_editor.cc:291
+#: session_option_editor.cc:312
 msgid "Mute Button"
 msgstr "Schaltfläche für Stummschaltung"
 
-#: session_option_editor.cc:298
+#: session_option_editor.cc:319
 msgid "Solo Button"
 msgstr "Schaltfläche für Solostatus"
 
-#: session_option_editor.cc:305
+#: session_option_editor.cc:326
 msgid "Monitor Buttons"
 msgstr "Monitor-Knöpfe"
 
-#: session_option_editor.cc:310
+#: session_option_editor.cc:331
 msgid "Name Labels"
 msgstr "Namensfelder"
 
-#: session_option_editor.cc:314
+#: session_option_editor.cc:335
 msgid "Track Name"
 msgstr "Spurname"
 
-#: session_option_editor.cc:325
+#: session_option_editor.cc:346
 msgid "MIDI region copies are independent"
 msgstr "Kopien von MIDI Regionen sind unabhängig"
 
-#: session_option_editor.cc:332
+#: session_option_editor.cc:353
 msgid ""
 "Policy for handling overlapping notes\n"
 " on the same MIDI channel"
@@ -12093,223 +12586,215 @@ msgstr ""
 "Vorgehen bei überlappenden Noten\n"
 "am selben MIDI-Kanal"
 
-#: session_option_editor.cc:337
+#: session_option_editor.cc:358
 msgid "never allow them"
 msgstr "Niemals erlauben"
 
-#: session_option_editor.cc:338
+#: session_option_editor.cc:359
 msgid "don't do anything in particular"
 msgstr "Nichts bestimmtes tun"
 
-#: session_option_editor.cc:339
+#: session_option_editor.cc:360
 msgid "replace any overlapped existing note"
 msgstr "Ãœberlagerte Note ersetzen"
 
-#: session_option_editor.cc:340
+#: session_option_editor.cc:361
 msgid "shorten the overlapped existing note"
 msgstr "Überlagerte Note kürzen"
 
-#: session_option_editor.cc:341
+#: session_option_editor.cc:362
 msgid "shorten the overlapping new note"
 msgstr "Die überlagernde neue Note kürzen"
 
-#: session_option_editor.cc:342
+#: session_option_editor.cc:363
 msgid "replace both overlapping notes with a single note"
 msgstr "Ãœberlagernde Note mit einer einzelnen ersetzen"
 
-#: session_option_editor.cc:346
+#: session_option_editor.cc:367
 msgid "Glue to bars and beats"
 msgstr "An Takte und Schläge binden"
 
-#: session_option_editor.cc:350
+#: session_option_editor.cc:371
 msgid "Glue new markers to bars and beats"
 msgstr "Neue Marker an Takte und Schläge binden"
 
-#: session_option_editor.cc:357
+#: session_option_editor.cc:378
 msgid "Glue new regions to bars and beats"
 msgstr "Neue Regionen an Takte und Schläge binden"
 
-#: session_option_editor.cc:362
+#: session_option_editor.cc:383
 msgid "Defaults"
 msgstr "Voreinstellungen"
 
-#: session_option_editor.cc:364
+#: session_option_editor.cc:385
 msgid "Use these settings as defaults"
 msgstr "Diese Einstellungen als Voreinstellungen nehmen"
 
-#: sfdb_ui.cc:89 sfdb_ui.cc:109 sfdb_ui.cc:118
+#: sfdb_ui.cc:90 sfdb_ui.cc:110 sfdb_ui.cc:119
 msgid "as new tracks"
 msgstr "als neue Spuren"
 
-#: sfdb_ui.cc:91 sfdb_ui.cc:111
+#: sfdb_ui.cc:92 sfdb_ui.cc:112
 msgid "to selected tracks"
 msgstr "zu ausgewählten Spuren"
 
-#: sfdb_ui.cc:93 sfdb_ui.cc:113
+#: sfdb_ui.cc:94 sfdb_ui.cc:114
 msgid "to region list"
 msgstr "zur Liste der Regionen"
 
-#: sfdb_ui.cc:95 sfdb_ui.cc:115
+#: sfdb_ui.cc:96 sfdb_ui.cc:116
 msgid "as new tape tracks"
 msgstr "als neue Band-Spuren"
 
-#: sfdb_ui.cc:99
+#: sfdb_ui.cc:100
 msgid "programming error: unknown import mode string %1"
 msgstr "Programmierfehler: unbekannter Importmodus %1"
 
-#: sfdb_ui.cc:126
+#: sfdb_ui.cc:127
 msgid "Auto-play"
 msgstr "Auto-Play"
 
-#: sfdb_ui.cc:134 sfdb_ui.cc:323
+#: sfdb_ui.cc:135 sfdb_ui.cc:324
 msgid "<b>Sound File Information</b>"
 msgstr "<b>Eigenschaften der Audiodatei</b>"
 
-#: sfdb_ui.cc:146
+#: sfdb_ui.cc:147
 msgid "Timestamp:"
 msgstr "Zeitstempel:"
 
-#: sfdb_ui.cc:148
+#: sfdb_ui.cc:149
 msgid "Format:"
 msgstr "Format:"
 
-#: sfdb_ui.cc:187 sfdb_ui.cc:652
+#: sfdb_ui.cc:188 sfdb_ui.cc:658
 msgid "Tags:"
 msgstr "Stichworte:"
 
-#: sfdb_ui.cc:292 sfdb_ui.cc:408
+#: sfdb_ui.cc:293 sfdb_ui.cc:409
 msgid "Could not read file: %1 (%2)."
 msgstr "Konnte Datei nicht lesen: %1 (%2)."
 
-#: sfdb_ui.cc:296
+#: sfdb_ui.cc:297
 msgid "<b>Midi File Information</b>"
 msgstr "<b>Midi Datei Information</b>"
 
-#: sfdb_ui.cc:457
+#: sfdb_ui.cc:458
 msgid "Could not access soundfile: "
 msgstr "Konnte auf Audiodatei nicht zugreifen: "
 
-#: sfdb_ui.cc:529
+#: sfdb_ui.cc:530
 msgid "SoundFileBox: Could not tokenize string: "
 msgstr "SoundFileBox: Konnte Zeichenkette nicht zerlegen: "
 
-#: sfdb_ui.cc:549 sfdb_ui.cc:551
+#: sfdb_ui.cc:550 sfdb_ui.cc:552
 msgid "Search"
 msgstr "Suchen"
 
-#: sfdb_ui.cc:575
+#: sfdb_ui.cc:581
 msgid "Audio and MIDI files"
 msgstr "Audio- und MIDIdateien"
 
-#: sfdb_ui.cc:578
+#: sfdb_ui.cc:584
 msgid "Audio files"
 msgstr "Audiodateien"
 
-#: sfdb_ui.cc:581
+#: sfdb_ui.cc:587
 msgid "MIDI files"
 msgstr "MIDI-Dateien"
 
-#: sfdb_ui.cc:584 add_video_dialog.cc:123
+#: sfdb_ui.cc:590 add_video_dialog.cc:123
 msgid "All files"
 msgstr "Alle Dateien"
 
-#: sfdb_ui.cc:603 add_video_dialog.cc:246
+#: sfdb_ui.cc:609 add_video_dialog.cc:246
 msgid "Browse Files"
 msgstr "Durchsuchen"
 
-#: sfdb_ui.cc:632
+#: sfdb_ui.cc:638
 msgid "Paths"
 msgstr "Pfade"
 
-#: sfdb_ui.cc:641
+#: sfdb_ui.cc:647
 msgid "Search Tags"
 msgstr "Stichwortsuche"
 
-#: sfdb_ui.cc:657
+#: sfdb_ui.cc:663
 msgid "Sort:"
 msgstr "Sortierung:"
 
-#: sfdb_ui.cc:665
+#: sfdb_ui.cc:671
 msgid "Longest"
 msgstr "Längste"
 
-#: sfdb_ui.cc:666
+#: sfdb_ui.cc:672
 msgid "Shortest"
 msgstr "Kürzeste"
 
-#: sfdb_ui.cc:667
+#: sfdb_ui.cc:673
 msgid "Newest"
 msgstr "Neueste"
 
-#: sfdb_ui.cc:668
+#: sfdb_ui.cc:674
 msgid "Oldest"
 msgstr "Ältestes"
 
-#: sfdb_ui.cc:669
+#: sfdb_ui.cc:675
 msgid "Most downloaded"
 msgstr "Am häufigsten heruntergeladen"
 
-#: sfdb_ui.cc:670
+#: sfdb_ui.cc:676
 msgid "Least downloaded"
 msgstr "Am seltensten heruntergeladen"
 
-#: sfdb_ui.cc:671
+#: sfdb_ui.cc:677
 msgid "Highest rated"
 msgstr "Bestbewertetes"
 
-#: sfdb_ui.cc:672
+#: sfdb_ui.cc:678
 msgid "Lowest rated"
 msgstr "Am schlechtesten bewertetes"
 
-#: sfdb_ui.cc:677
+#: sfdb_ui.cc:683
 msgid "More"
 msgstr "Mehr"
 
-#: sfdb_ui.cc:681
+#: sfdb_ui.cc:687
 msgid "Similar"
 msgstr "Ähnlich"
 
-#: sfdb_ui.cc:693
+#: sfdb_ui.cc:699
 msgid "ID"
 msgstr "ID"
 
-#: sfdb_ui.cc:694 add_video_dialog.cc:83
+#: sfdb_ui.cc:700 add_video_dialog.cc:83
 msgid "Filename"
 msgstr "Dateiname"
 
-#: sfdb_ui.cc:696
+#: sfdb_ui.cc:702
 msgid "Duration"
 msgstr "Dauer"
 
-#: sfdb_ui.cc:697
+#: sfdb_ui.cc:703
 msgid "Size"
 msgstr "Größe"
 
-#: sfdb_ui.cc:698
+#: sfdb_ui.cc:704
 msgid "Samplerate"
 msgstr "Samplerate"
 
-#: sfdb_ui.cc:699
+#: sfdb_ui.cc:705
 msgid "License"
 msgstr "Lizenz"
 
-#: sfdb_ui.cc:717
+#: sfdb_ui.cc:723
 msgid "Search Freesound"
 msgstr "Freesound durchsuchen"
 
-#: sfdb_ui.cc:737
-msgid "Press to import selected files and close this window"
-msgstr ""
-"Drücken Sie hier, um die angewählten Dateien zu importieren und dieses "
-"Fenster zu schließen"
-
-#: sfdb_ui.cc:738
-msgid "Press to import selected files and leave this window open"
-msgstr ""
-"Drücken Sie hier, um die angewählten Dateien zu importieren und dieses "
-"Fenster offen zu lassen"
-
 #: sfdb_ui.cc:739
+msgid "Press to import selected files"
+msgstr "Drücken Sie, um die gewählten Dateien zu importieren"
+
+#: sfdb_ui.cc:740
 msgid "Press to close this window without importing any files"
 msgstr ""
 "Drücken Sie hier, um dieses Fenster zu schließen, ohne Dateien zu importieren"
@@ -12344,39 +12829,39 @@ msgstr "MB"
 msgid "GB"
 msgstr "GB"
 
-#: sfdb_ui.cc:1424 sfdb_ui.cc:1737 sfdb_ui.cc:1800 sfdb_ui.cc:1818
+#: sfdb_ui.cc:1429 sfdb_ui.cc:1734 sfdb_ui.cc:1795 sfdb_ui.cc:1813
 msgid "one track per file"
 msgstr "eine Spur pro Datei"
 
-#: sfdb_ui.cc:1427 sfdb_ui.cc:1801 sfdb_ui.cc:1819
+#: sfdb_ui.cc:1432 sfdb_ui.cc:1796 sfdb_ui.cc:1814
 msgid "one track per channel"
 msgstr "eine Spur pro Kanal"
 
-#: sfdb_ui.cc:1435 sfdb_ui.cc:1803 sfdb_ui.cc:1820
+#: sfdb_ui.cc:1440 sfdb_ui.cc:1798 sfdb_ui.cc:1815
 msgid "sequence files"
 msgstr "Dateien aneinanderreihen"
 
-#: sfdb_ui.cc:1438 sfdb_ui.cc:1808
+#: sfdb_ui.cc:1443 sfdb_ui.cc:1803
 msgid "all files in one track"
 msgstr "Alle Dateien in eine Spur"
 
-#: sfdb_ui.cc:1439 sfdb_ui.cc:1802
+#: sfdb_ui.cc:1444 sfdb_ui.cc:1797
 msgid "merge files"
 msgstr "Dateien zusammenfügen"
 
-#: sfdb_ui.cc:1445 sfdb_ui.cc:1805
+#: sfdb_ui.cc:1450 sfdb_ui.cc:1800
 msgid "one region per file"
 msgstr "eine Region pro Datei"
 
-#: sfdb_ui.cc:1448 sfdb_ui.cc:1806
+#: sfdb_ui.cc:1453 sfdb_ui.cc:1801
 msgid "one region per channel"
 msgstr "eine Region pro Kanal"
 
-#: sfdb_ui.cc:1453 sfdb_ui.cc:1807 sfdb_ui.cc:1821
+#: sfdb_ui.cc:1458 sfdb_ui.cc:1802 sfdb_ui.cc:1816
 msgid "all files in one region"
 msgstr "alle Dateien in einer Region"
 
-#: sfdb_ui.cc:1520
+#: sfdb_ui.cc:1525
 msgid ""
 "One or more of the selected files\n"
 "cannot be used by %1"
@@ -12384,104 +12869,104 @@ msgstr ""
 "Eine oder mehrere der ausgewählten Dateien\n"
 "können von %1 nicht verwendet werden"
 
-#: sfdb_ui.cc:1664
+#: sfdb_ui.cc:1669
 msgid "Copy files to session"
 msgstr "Kopiere Dateien in Projekt"
 
-#: sfdb_ui.cc:1681 sfdb_ui.cc:1858
+#: sfdb_ui.cc:1688 sfdb_ui.cc:1856
 msgid "file timestamp"
 msgstr "Zeitstempel"
 
-#: sfdb_ui.cc:1682 sfdb_ui.cc:1860
+#: sfdb_ui.cc:1689 sfdb_ui.cc:1858
 msgid "edit point"
 msgstr "Arbeitspunkt"
 
-#: sfdb_ui.cc:1683 sfdb_ui.cc:1862
+#: sfdb_ui.cc:1690 sfdb_ui.cc:1860
 msgid "playhead"
 msgstr "Positionszeiger"
 
-#: sfdb_ui.cc:1684
+#: sfdb_ui.cc:1691
 msgid "session start"
 msgstr "Projektanfang"
 
-#: sfdb_ui.cc:1690
-msgid "<b>Add files as ...</b>"
-msgstr "<b>Füge Dateien hinzu als...</b>"
+#: sfdb_ui.cc:1697
+msgid "<b>Add files ...</b>"
+msgstr "<b>Dateien hinzufügen ...</b>"
 
-#: sfdb_ui.cc:1712
+#: sfdb_ui.cc:1709
 msgid "<b>Insert at</b>"
 msgstr "<b>Einfügen bei</b>"
 
-#: sfdb_ui.cc:1725
+#: sfdb_ui.cc:1722
 msgid "<b>Mapping</b>"
 msgstr "<b>Zuordnung</b>"
 
-#: sfdb_ui.cc:1743
+#: sfdb_ui.cc:1740
 msgid "<b>Conversion quality</b>"
 msgstr "<b>Konvertierungsqualität:</b>"
 
-#: sfdb_ui.cc:1755
+#: sfdb_ui.cc:1752
 msgid "<b>Instrument</b>"
 msgstr "<b>Instrument</b>"
 
-#: sfdb_ui.cc:1767 sfdb_ui.cc:1874
+#: sfdb_ui.cc:1764 sfdb_ui.cc:1872
 msgid "Best"
 msgstr "bestmöglich"
 
-#: sfdb_ui.cc:1768 sfdb_ui.cc:1876
+#: sfdb_ui.cc:1765 sfdb_ui.cc:1874
 msgid "Good"
 msgstr "gut"
 
-#: sfdb_ui.cc:1769 sfdb_ui.cc:1878
+#: sfdb_ui.cc:1766 sfdb_ui.cc:1876
 msgid "Quick"
 msgstr "schnell"
 
-#: sfdb_ui.cc:1771
+#: sfdb_ui.cc:1768
 msgid "Fastest"
 msgstr "Schnellstmöglich"
 
-#: shuttle_control.cc:56
+#: shuttle_control.cc:57
 msgid "Shuttle speed control (Context-click for options)"
 msgstr "Abspielgeschwindigkeit (Rechtsklick für Optionen)"
 
-#: shuttle_control.cc:183
+#: shuttle_control.cc:184
 msgid "Percent"
 msgstr "Prozent"
 
-#: shuttle_control.cc:191
+#: shuttle_control.cc:192
 msgid "Units"
 msgstr "Einheiten"
 
-#: shuttle_control.cc:197 shuttle_control.cc:620
+#: shuttle_control.cc:198 shuttle_control.cc:633
 msgid "Sprung"
 msgstr "Feder"
 
-#: shuttle_control.cc:201 shuttle_control.cc:623
+#: shuttle_control.cc:202 shuttle_control.cc:636
 msgid "Wheel"
 msgstr "Drehrad"
 
-#: shuttle_control.cc:235
+#: shuttle_control.cc:236
 msgid "Maximum speed"
 msgstr "Max. Geschwindigkeit"
 
-#: shuttle_control.cc:579
+#: shuttle_control.cc:239
+msgid "Reset to 100%"
+msgstr "Auf 100% zurücksetzen"
+
+#: shuttle_control.cc:592
 msgid "Playing"
 msgstr "Wiedergabe"
 
-#: shuttle_control.cc:594
+#: shuttle_control.cc:607
 #, c-format
 msgid "<<< %+d semitones"
 msgstr "<<< %+d Halbtöne"
 
-#: shuttle_control.cc:596
+#: shuttle_control.cc:609
 #, c-format
 msgid ">>> %+d semitones"
 msgstr ">>> %+d Halbtöne"
 
-#: shuttle_control.cc:601
-msgid "Stopped"
-msgstr "Gestoppt"
-
 #: soundcloud_export_selector.cc:44
 msgid "User Email"
 msgstr "Benutzer Email"
@@ -12506,7 +12991,7 @@ msgstr "Dateien herunterladbar machen"
 msgid "%1: %2 of %3 bytes uploaded"
 msgstr "%1: %2 von %3 bytes hochgeladen"
 
-#: splash.cc:73
+#: splash.cc:75
 msgid "%1 loading ..."
 msgstr "%1 startet ..."
 
@@ -12522,7 +13007,7 @@ msgstr "Lautsprecher entfernen"
 msgid "Azimuth:"
 msgstr "Azimut:"
 
-#: startup.cc:68
+#: startup.cc:70
 msgid ""
 "Use an external mixer or the hardware mixer of your audio interface.\n"
 "%1 will play NO role in monitoring"
@@ -12530,11 +13015,11 @@ msgstr ""
 "Verwende einen externen Mixer oder den Hardwaremixer der Audiohardware.\n"
 "%1 wird das Monitoring NICHT übernehmen."
 
-#: startup.cc:70
+#: startup.cc:72
 msgid "Ask %1 to play back material as it is being recorded"
 msgstr "%1 soll laufende Aufnahmen wiedergeben"
 
-#: startup.cc:143
+#: startup.cc:145
 msgid ""
 "<span size=\"larger\">%1 is a digital audio workstation. You can use it to "
 "record, edit and mix multi-track audio. You can produce your own CDs, mix "
@@ -12551,15 +13036,15 @@ msgstr ""
 "Es gibt ein paar Dinge, die vor dem ersten Programmstart konfiguriert werden "
 "müssen.</span>"
 
-#: startup.cc:169
+#: startup.cc:171
 msgid "Welcome to %1"
 msgstr "Willkommen bei %1"
 
-#: startup.cc:192
+#: startup.cc:194
 msgid "Default folder for %1 sessions"
 msgstr "Standardordner für %1 Projekte"
 
-#: startup.cc:198
+#: startup.cc:200
 msgid ""
 "Each project that you work on with %1 has its own folder.\n"
 "These can require a lot of disk space if you are recording audio.\n"
@@ -12576,11 +13061,11 @@ msgstr ""
 "<i>(Neue Projekte können überall abgespeichert werden, dies ist nur die "
 "Vorgabe)</i>"
 
-#: startup.cc:221
+#: startup.cc:223
 msgid "Default folder for new sessions"
 msgstr "Standardordner für neue Projekte"
 
-#: startup.cc:242
+#: startup.cc:244
 msgid ""
 "While recording instruments or vocals, you probably want to listen to the\n"
 "signal as well as record it. This is called \"monitoring\". There are\n"
@@ -12605,15 +13090,15 @@ msgstr ""
 "\n"
 "<i>Im Zweifelsfall akzeptieren Sie einfach die Voreinstellung.</i>"
 
-#: startup.cc:263
+#: startup.cc:265
 msgid "Monitoring Choices"
 msgstr "Auswahl des Monitoring"
 
-#: startup.cc:286
+#: startup.cc:288
 msgid "Use a Master bus directly"
 msgstr "Nutze den Master-Bus direkt"
 
-#: startup.cc:288
+#: startup.cc:290
 msgid ""
 "Connect the Master bus directly to your hardware outputs. This is preferable "
 "for simple usage."
@@ -12621,11 +13106,11 @@ msgstr ""
 "Verbinde den Master-Bus direkt mit den Audioausgängen. Wird für einfache "
 "Anwendungen empfohlen."
 
-#: startup.cc:297
+#: startup.cc:299
 msgid "Use an additional Monitor bus"
 msgstr "Nutze einen zusätzlichen Monitor-Bus"
 
-#: startup.cc:300
+#: startup.cc:302
 msgid ""
 "Use a Monitor bus between Master bus and hardware outputs for \n"
 "greater control in monitoring without affecting the mix."
@@ -12633,7 +13118,7 @@ msgstr ""
 "Nutze einen Monitor-Bus zwischen Master-Bus und Audioausgängen, um mehr\n"
 "Möglichkeiten für das Monitoring zu bekommen, ohne den Mix zu beeinflussen."
 
-#: startup.cc:322
+#: startup.cc:324
 msgid ""
 "<i>You can change this preference at any time via the Preferences dialog.\n"
 "You can also add or remove the monitor section to/from any session.</i>\n"
@@ -12647,7 +13132,7 @@ msgstr ""
 "\n"
 "</i>Im Zweifelsfall akzeptieren Sie einfach die Voreinstellung.</i>"
 
-#: startup.cc:333
+#: startup.cc:335
 msgid "Monitor Section"
 msgstr "Monitorsektion"
 
@@ -13035,12 +13520,12 @@ msgstr "Akkordeingabe umschalten"
 msgid "Sustain Selected Notes by Note Length"
 msgstr "Ausgewählte Noten ertönen über Notenlänge"
 
-#: stereo_panner.cc:128
+#: stereo_panner.cc:127
 #, c-format
 msgid "L:%3d R:%3d Width:%d%%"
 msgstr "L:%3d R:%3d Breite:%d%%"
 
-#: stereo_panner.cc:271
+#: stereo_panner.cc:270
 msgid "Panner|M"
 msgstr "M"
 
@@ -13056,14 +13541,18 @@ msgstr "Breite"
 msgid "Strip Silence"
 msgstr "Stille entfernen"
 
-#: strip_silence_dialog.cc:75
+#: strip_silence_dialog.cc:76
 msgid "Minimum length"
 msgstr "Mindestlänge"
 
-#: strip_silence_dialog.cc:83
+#: strip_silence_dialog.cc:84
 msgid "Fade length"
 msgstr "Fade-Länge"
 
+#: strip_silence_dialog.cc:111 strip_silence_dialog.cc:295
+msgid "Analyzing"
+msgstr "Analysiere"
+
 #: tempo_dialog.cc:41 tempo_dialog.cc:57
 msgid "bar:"
 msgstr "Takt:"
@@ -13153,71 +13642,75 @@ msgstr "Taktart beginnt bei Takt:"
 msgid "incomprehensible meter note type (%1)"
 msgstr "Unverständlicher Signatur-Notentyp (%1)"
 
-#: theme_manager.cc:67
+#: theme_manager.cc:61
 msgid "Dark Theme"
 msgstr "Dunkles Thema"
 
-#: theme_manager.cc:68
+#: theme_manager.cc:62
 msgid "Light Theme"
 msgstr "Helles Thema"
 
-#: theme_manager.cc:69
+#: theme_manager.cc:63
 msgid "Restore Defaults"
 msgstr "Standards wiederherstellen"
 
-#: theme_manager.cc:70
+#: theme_manager.cc:64
 msgid "Draw \"flat\" buttons"
 msgstr "Zeichne \"flache\" Schaltflächen"
 
-#: theme_manager.cc:71
+#: theme_manager.cc:65
 msgid "Blink Rec-Arm buttons"
 msgstr "Aufnahmebereitschaftsknopf blinkt"
 
-#: theme_manager.cc:72
+#: theme_manager.cc:66
 msgid "Color regions using their track's color"
 msgstr "Färbe Regionen in der Spurfarbe ein"
 
-#: theme_manager.cc:73
+#: theme_manager.cc:67
 msgid "Show waveform clipping"
 msgstr "Clipping der Wellenform anzeigen"
 
-#: theme_manager.cc:75
+#: theme_manager.cc:69
 msgid "Waveforms color gradient depth"
 msgstr "Farbverlaufs-Intensität der Wellenform"
 
-#: theme_manager.cc:77
+#: theme_manager.cc:71
 msgid "Timeline item gradient depth"
 msgstr "Farbverlaufs-Intensität von Zeitleisten-Objekten "
 
-#: theme_manager.cc:78
+#: theme_manager.cc:72
 msgid "All floating windows are dialogs"
 msgstr "Alle schwebenden Fenster sind Dialoge"
 
-#: theme_manager.cc:79
+#: theme_manager.cc:73
 msgid "Transient windows follow front window."
 msgstr "Transientenfenster folgt Hauptfenster"
 
-#: theme_manager.cc:80
+#: theme_manager.cc:74
+msgid "Float detached monitor-section window"
+msgstr "Abgelöstes Monitorsektionfenster schwebend"
+
+#: theme_manager.cc:75
 msgid "Icon Set"
 msgstr "Icon-Satz"
 
-#: theme_manager.cc:89
+#: theme_manager.cc:84
 msgid "Object"
 msgstr "Objekt"
 
-#: theme_manager.cc:165
+#: theme_manager.cc:162
 msgid "Items"
 msgstr "Objekte"
 
-#: theme_manager.cc:166
+#: theme_manager.cc:163
 msgid "Palette"
 msgstr "Palette"
 
-#: theme_manager.cc:167
+#: theme_manager.cc:164
 msgid "Transparency"
 msgstr "Transparenz"
 
-#: theme_manager.cc:197
+#: theme_manager.cc:195
 msgid ""
 "Mark all floating windows to be type \"Dialog\" rather than using \"Utility"
 "\" for some.\n"
@@ -13229,7 +13722,7 @@ msgstr ""
 "Dies kann bei einigen Fenstermanagern helfen. Sie müssen %1 starten, um "
 "diese Option zu aktivieren"
 
-#: theme_manager.cc:201
+#: theme_manager.cc:199
 msgid ""
 "Make transient windows follow the front window when toggling between the "
 "editor and mixer.\n"
@@ -13239,7 +13732,17 @@ msgstr ""
 "Vordergrund-Fenster.\n"
 "Dies erfordert einen Neustart von %1."
 
-#: theme_manager.cc:635
+#: theme_manager.cc:202
+msgid ""
+"When detaching the monitoring section, mark it as \"Utility\" window to stay "
+"in front.\n"
+"This requires a restart of %1 to take effect"
+msgstr ""
+"Beim Ablösen der Monitorsektion als \"Utility\"fenster markieren, damit es im "
+"Vordergrund bleibt.\n"
+"Dies erfordert einen Neustart von %1"
+
+#: theme_manager.cc:643
 msgid "Color Palette"
 msgstr "Farbpalette"
 
@@ -13247,7 +13750,7 @@ msgstr "Farbpalette"
 msgid "Track/Bus name (double click to edit)"
 msgstr "Spur-/Busname (Doppelklick zum Bearbeiten)"
 
-#: time_axis_view_item.cc:333
+#: time_axis_view_item.cc:326
 msgid "new duration %1 frame is out of bounds for %2"
 msgid_plural "new duration of %1 frames is out of bounds for %2"
 msgstr[0] "neue Dauer %1 Frame ist außerhalb des erlaubten Bereichs für %2"
@@ -13386,105 +13889,109 @@ msgstr "MIDI Transponieren"
 msgid "Transpose"
 msgstr "Transponieren"
 
-#: ui_config.cc:179 ui_config.cc:317
+#: ui_config.cc:230 ui_config.cc:368
 msgid "Loading default ui configuration file %1"
 msgstr "lade voreingestellte UI-Konfigurationsdatei %1"
 
-#: ui_config.cc:182 ui_config.cc:320
+#: ui_config.cc:233 ui_config.cc:371
 msgid "cannot read default ui configuration file \"%1\""
 msgstr "Kann die voreingestellte UI-Konfigurationsdatei \"%1\" nicht lesen"
 
-#: ui_config.cc:185 ui_config.cc:325
+#: ui_config.cc:236 ui_config.cc:376
 msgid "default ui configuration file \"%1\" not loaded successfully."
 msgstr ""
 "Die voreingestellte UI-Konfigurationsdatei \"%1\" konnte nicht geladen "
 "werden."
 
-#: ui_config.cc:193
+#: ui_config.cc:244
 msgid "Could not find default UI configuration file %1"
 msgstr "Konnte UI-Konfigurationsdatei für Voreinstellungen %1 nicht finden"
 
-#: ui_config.cc:236
+#: ui_config.cc:287
 msgid "Loading color file %1"
 msgstr "Lade Farbdatei %1"
 
-#: ui_config.cc:239
+#: ui_config.cc:290
 msgid "cannot read color file \"%1\""
 msgstr "kann Farbdatei \"%1\" nicht lesen"
 
-#: ui_config.cc:244
+#: ui_config.cc:295
 msgid "color file \"%1\" not loaded successfully."
 msgstr "Farbdatei \"%1\" konnte nicht geladen werden."
 
-#: ui_config.cc:250
+#: ui_config.cc:301
 msgid "Color file %1 not found"
 msgstr "Farbdatei %1 nicht gefunden"
 
-#: ui_config.cc:299 ui_config.cc:378
+#: ui_config.cc:350 ui_config.cc:429
 msgid "Color file %1 not saved"
 msgstr "Farbdatei %1 nicght gespeichert"
 
-#: ui_config.cc:334
+#: ui_config.cc:385
 msgid "Loading user ui configuration file %1"
 msgstr "Lade benutzerdefinierte UI-Konfigurationsdatei %1"
 
-#: ui_config.cc:337
+#: ui_config.cc:388
 msgid "cannot read ui configuration file \"%1\""
 msgstr "kann die UI-Konfigurationsdatei \"%1\" nicht lesen"
 
-#: ui_config.cc:342
+#: ui_config.cc:393
 msgid "user ui configuration file \"%1\" not loaded successfully."
 msgstr ""
 "Die benutzerdefinierte UI-Konfigurationsdatei \"%1\" konnte nicht geladen "
 "werden."
 
-#: ui_config.cc:350
+#: ui_config.cc:401
 msgid "could not find any ui configuration file, canvas will look broken."
 msgstr ""
 "Konnte keine UI-Konfigurationsdatei finden, die Arbeitsfläche wird nicht "
 "korrekt dargestellt werden."
 
-#: ui_config.cc:368
+#: ui_config.cc:419
 msgid "Config file %1 not saved"
 msgstr "Konfigurationsdatei %1 nicht gespeichert"
 
-#: ui_config.cc:609
+#: ui_config.cc:660
 msgid "Color %1 not found"
 msgstr "Farbe %1 nicht gefunden"
 
-#: ui_config.cc:679
+#: ui_config.cc:730
 msgid "Unable to find UI style file %1 in search path %2. %3 will look strange"
 msgstr ""
 "Kann den UI-Stil Datei %1 im Suchpfad %2 nicht finden. %3 wird merkwürdig "
 "aussehen"
 
-#: utils.cc:117 utils.cc:160
+#: utils.cc:114 utils.cc:157
 msgid "bad XPM header %1"
 msgstr "Fehlerhafter XPM Header %1"
 
-#: utils.cc:577
+#: utils.cc:574
 msgid "cannot find XPM file for %1"
 msgstr "Konnte XPM-Datei für %1 nicht finden"
 
-#: utils.cc:597 utils.cc:627 utils.cc:641
+#: utils.cc:594 utils.cc:624 utils.cc:638
 msgid "default"
 msgstr "voreingestellt"
 
-#: utils.cc:642
+#: utils.cc:639
 msgid "icon \"%1\" not found for icon set \"%2\", fallback to default"
 msgstr ""
 "Icon \"%1\" wurde im Icon-Satz \"%2\" nicht gefunden, greife auf "
 "Voreinstellung zurück"
 
-#: utils.cc:649
+#: utils.cc:646
 msgid "cannot find icon image for %1 using %2"
 msgstr "Konnte Icon-Bild für %1 unter %2 nicht finden"
 
-#: utils.cc:666 utils.cc:682
+#: utils.cc:663 utils.cc:679
 msgid "Caught exception while loading icon named %1"
 msgstr ""
 "Während des Ladens des Icons mit dem Namen %1 trat ein Ausnahmefehler auf"
 
+#: utils.cc:939
+msgid "Overwrite"
+msgstr "Ãœberschreiben"
+
 #: add_video_dialog.cc:54
 msgid "Set Video Track"
 msgstr "Videospur-Einstellungen"
@@ -13585,14 +14092,13 @@ msgstr ""
 msgid "Video-monitor 'xjadeo' cannot be launched."
 msgstr "Videomonitor 'xjadeo' kann nicht gestartet werden."
 
-#: video_timeline.cc:769
+#: video_timeline.cc:770
 msgid ""
-"Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.8.0 or "
+"Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.7.7 or "
 "later. http://xjadeo.sf.net/"
 msgstr ""
 "Videomonitor 'xjadeo' ist zu alt. Bitte installieren Sie xjadeo in Version "
-"0.8.0 oder "
-"höher. http://xjadeo.sf.net/"
+"0.7.7 oder höher. http://xjadeo.sf.net/"
 
 #: video_monitor.cc:285
 msgid "Video Monitor: File Not Found."
@@ -13600,9 +14106,9 @@ msgstr "Videomonitor: Datei nicht gefunden."
 
 #: transcode_ffmpeg.cc:56
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system.\n"
-"Video import and export is not possible until you install those tools.\n"
+"ffmpeg installation was not found on this system.\n"
 "%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
+"Video import and export is not possible until you install tools.\n"
 "\n"
 "The tools are included with the %1 releases from ardour.org and also "
 "available with the video-server at http://x42.github.com/harvid/\n"
@@ -13615,22 +14121,21 @@ msgid ""
 "\n"
 "see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
-"Die Programme ffprobe oder ffmpeg konnten auf diesem System nicht gefunden "
-"werden.\n"
-"Bis diese Werkzeuge installiert sind, ist Videoexport nicht möglich.\n"
-"%1 benötigt ffmpeg und ffprobe von ffmpeg.org in der Version 1.1 oder "
-"neuer.\n"
+"Auf diesem System konnte keine ffmpeg-Installation gefunden werden.\n"
+"%1 benötigt ffmpeg und ffprobe von ffmpeg.org - Version 1.1 oder neuer.\n"
+"Video-Im- und Export sind ohne Installation dieser Werkzeuge nicht möglich.\n"
 "\n"
-"Diese Werkzeuge sind in den %1-Paketen von ardour.org inkludiert und auch "
-"mit dem Videoserver auf http://x42.github.com/harvid/ erhältlich.\n"
+"Die Werkzeuge sind in den %1-Veröffentlichungen von ardour.org enthalten und "
+"ebenfalls mit dem Videoserver auf http://x42.github.com/harvid/ erhältlich.\n"
 "\n"
-"Wichtig:  die Dateien müssen in $PATH installiert sein und die Namen "
-"ffmpeg_harvid und ffprobe_harvid.\n"
-"Falls Sie bereits eine ffmpeg Installation auf Ihrem System haben, empfehlen "
-"wir, symbolische Links von ffmpeg zu ffmpeg_harvid und von ffprobe zu "
-"ffprobe_harvid anzulegen.\n"
+"Wichtig: Die Dateien müssen in $PATH installiert werden und nach "
+"ffmpeg_harvid "
+"und ffprobe_harvid umbenannt werden.\n"
+"Falls Sie eine geeignete ffmpeg-Installation auf Ihrem System haben, "
+"empfehlen wir, symbolische Verknüpfungen von ffmpeg auf ffmpeg_harvid und von "
+"ffprobe auf ffprobe_harvid zu erzeugen.\n"
 "\n"
-"Siehe auch http://manual.ardour.org/video-timeline/setup/"
+"Sehen Sie auch  http://manual.ardour.org/video-timeline/setup/"
 
 #: transcode_video_dialog.cc:56
 msgid "Transcode/Import Video File "
@@ -13649,10 +14154,14 @@ msgid "Height = "
 msgstr "Höhe ="
 
 #: transcode_video_dialog.cc:66
+msgid "Extract LTC from audio and align video"
+msgstr "Extrahiere LTC aus Audio und richte Video aus"
+
+#: transcode_video_dialog.cc:67
 msgid "Manual Override"
 msgstr "Manuelle Eingabe"
 
-#: transcode_video_dialog.cc:70 export_video_dialog.cc:99
+#: transcode_video_dialog.cc:71 export_video_dialog.cc:99
 msgid "Debug Mode: Print ffmpeg command and output to stdout."
 msgstr "Debug-Modus: gibt die ffmpeg-Befehlszeile und -Ausgabe an stdout aus."
 
@@ -13662,13 +14171,12 @@ msgstr "<b>Dateiinformationen</b>"
 
 #: transcode_video_dialog.cc:113
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system. Video Import "
-"is not possible until you install those tools. See the Log window for more "
-"information."
+"ffmpeg installation was not found. Video Import is not possible. See the Log "
+"window for more information."
 msgstr ""
-"Die Programme ffprobe oder ffmpeg konnten auf diesem System nicht gefunden "
-"werden. Bis diese Werkzeuge installiert sind, ist Videoimport nicht möglich. "
-"Sehen Sie im Log-Fenster nach weiteren Informationen."
+"Keine ffmpeg-Installation gefunden. Videoimport ist nicht möglich. Sehen Sie "
+"im "
+"Logfenster nach weiteren Informationen."
 
 #: transcode_video_dialog.cc:120
 msgid ""
@@ -13703,64 +14211,64 @@ msgstr "??"
 msgid "<b>Import Settings</b>"
 msgstr "<b>Importeinstellungen</b>"
 
-#: transcode_video_dialog.cc:186
-msgid "Reference From Current Location (Previously Transcoded Files Only)"
+#: transcode_video_dialog.cc:184
+msgid "Reference from Current Location (Previously Transcoded Files Only)"
 msgstr ""
 "Referenz von momentaner Position (vorher nur von transkodierten Dateien)"
 
-#: transcode_video_dialog.cc:187
+#: transcode_video_dialog.cc:185
 msgid "Import/Transcode Video to Session"
 msgstr "Video ins Projekt transkodieren/importieren"
 
-#: transcode_video_dialog.cc:190 transcode_video_dialog.cc:200
+#: transcode_video_dialog.cc:188 transcode_video_dialog.cc:198
 msgid "Do Not Import Video (Audio Import Only)"
 msgstr "Video nicht importieren (nur Audio)"
 
-#: transcode_video_dialog.cc:210
+#: transcode_video_dialog.cc:208
 msgid "Do Not Import Video"
 msgstr "Video nicht importieren"
 
-#: transcode_video_dialog.cc:226
+#: transcode_video_dialog.cc:224
 msgid "Scale Video: Width = "
 msgstr "Video skalieren: Breite = "
 
-#: transcode_video_dialog.cc:233
+#: transcode_video_dialog.cc:230
 msgid "Original Width"
 msgstr "Originalbreite"
 
-#: transcode_video_dialog.cc:248
+#: transcode_video_dialog.cc:245
 msgid "Bitrate (KBit/s):"
 msgstr "Bitrate (KBit/s):"
 
-#: transcode_video_dialog.cc:253
+#: transcode_video_dialog.cc:250
 msgid "Extract Audio:"
 msgstr "Audio extrahieren:"
 
-#: transcode_video_dialog.cc:258
+#: transcode_video_dialog.cc:255
 msgid "No Audio Track Present"
 msgstr "Keine Audiospur"
 
-#: transcode_video_dialog.cc:261
+#: transcode_video_dialog.cc:258
 msgid "Do Not Extract Audio"
 msgstr "Audio nicht extrahieren"
 
-#: transcode_video_dialog.cc:376
+#: transcode_video_dialog.cc:374
 msgid "Extracting Audio.."
 msgstr "Extrahiere Audio..."
 
-#: transcode_video_dialog.cc:379
+#: transcode_video_dialog.cc:377
 msgid "Audio Extraction Failed."
 msgstr "Extrahieren des Audio gescheitert."
 
-#: transcode_video_dialog.cc:405
+#: transcode_video_dialog.cc:403
 msgid "Transcoding Video.."
 msgstr "Transkodiere Video.."
 
-#: transcode_video_dialog.cc:439
+#: transcode_video_dialog.cc:437
 msgid "Transcoding Failed."
 msgstr "Transkodieren gescheitert"
 
-#: transcode_video_dialog.cc:529
+#: transcode_video_dialog.cc:541
 msgid "Save Transcoded Video File"
 msgstr "Sichere transkodierte Videodatei"
 
@@ -13779,9 +14287,10 @@ msgstr "Server Docroot:"
 #: video_server_dialog.cc:61
 msgid "Don't show this dialog again. (Reset in Edit->Preferences)."
 msgstr ""
-"Diesen Dialog nicht mehr anzeigen (kann in Einstellungen geändert werden)."
+"Diesen Dialog nicht mehr anzeigen (kann in Bearbeiten > Globale "
+"Einstellungen zurückgesetzt werden)."
 
-#: video_server_dialog.cc:97
+#: video_server_dialog.cc:94
 msgid ""
 "The external video server 'harvid' can not be found.\n"
 "The tool is included with the %1 releases from ardour.org, alternatively you "
@@ -13791,19 +14300,19 @@ msgid ""
 "see also http://manual.ardour.org/video-timeline/setup/"
 msgstr "key"
 
-#: video_server_dialog.cc:129
+#: video_server_dialog.cc:126
 msgid "Listen Address:"
 msgstr "Eingehende Adresse:"
 
-#: video_server_dialog.cc:134
+#: video_server_dialog.cc:131
 msgid "Listen Port:"
 msgstr "Eingehender Port:"
 
-#: video_server_dialog.cc:139
+#: video_server_dialog.cc:136
 msgid "Cache Size:"
 msgstr "Cachegröße"
 
-#: video_server_dialog.cc:145
+#: video_server_dialog.cc:142
 msgid ""
 "%1 relies on an external video server for the videotimeline.\n"
 "The server configured in Edit -> Preferences -> Video is not reachable.\n"
@@ -13814,19 +14323,19 @@ msgstr ""
 "nicht erreichbar.\n"
 "Möchten Sie, daß %1 \"harvid\" auf diesem Computer startet?"
 
-#: video_server_dialog.cc:189
+#: video_server_dialog.cc:186
 msgid "Set Video Server Executable"
 msgstr "Setze Video-Serverpfad"
 
-#: video_server_dialog.cc:209
+#: video_server_dialog.cc:206
 msgid "Server docroot"
 msgstr "Server-docroot"
 
-#: utils_videotl.cc:60
+#: utils_videotl.cc:61
 msgid "Destination is outside Video Server's docroot. "
 msgstr "Ziel ist ausserhalb der docroot des Videoservers."
 
-#: utils_videotl.cc:61
+#: utils_videotl.cc:62
 msgid ""
 "The destination file path is outside of the Video Server's docroot. The file "
 "will not be readable by the Video Server. Do you still want to continue?"
@@ -13835,20 +14344,15 @@ msgstr ""
 "Videoservers. Die Datei wird für den Videoserver nicht lesbar sein. Wollen "
 "Sie wirklich fortfahren?"
 
-#: utils_videotl.cc:64
+#: utils_videotl.cc:65
 msgid "Continue"
 msgstr "Fortfahren"
 
-#: utils_videotl.cc:70
+#: utils_videotl.cc:72
 msgid "Confirm Overwrite"
 msgstr "Bestätige das Überschreiben"
 
-#: utils_videotl.cc:71
-msgid "A file with the same name already exists.  Do you want to overwrite it?"
-msgstr ""
-"Eine Datei mit diesem Namen existiert bereits. Wollen Sie sie überschreiben?"
-
-#: utils_videotl.cc:81 utils_videotl.cc:97
+#: utils_videotl.cc:82 utils_videotl.cc:98
 msgid "Cannot create video folder \"%1\" (%2)"
 msgstr "Kann Videoordner \"%1\" nicht erstellen (%2)"
 
@@ -13902,13 +14406,12 @@ msgstr "Projekt-Metadaten verwenden"
 
 #: export_video_dialog.cc:115
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system. Video Export "
-"is not possible until you install those tools. See the Log window for more "
-"information."
+"ffmpeg installation was not found. Video Export is not possible. See the Log "
+"window for more information."
 msgstr ""
-"Die Programme ffprobe oder ffmpeg konnten auf diesem System nicht gefunden "
-"werden. Bis diese Werkzeuge installiert sind, ist Videoexport nicht möglich. "
-"Sehen Sie im Log-Fenster nach weiteren Informationen."
+"Keine ffmpeg-Installation gefunden. Videoexport ist nicht möglich. Sehen Sie "
+"im "
+"Logfenster nach weiteren Informationen."
 
 #: export_video_dialog.cc:126
 msgid "<b>Output:</b> (file extension defines format)"
@@ -13926,77 +14429,77 @@ msgstr "Audio:"
 msgid "Master Bus"
 msgstr "Masterbus"
 
-#: export_video_dialog.cc:154
+#: export_video_dialog.cc:153
 msgid "from the %1 session's start to the session's end"
 msgstr "von %1 Projektbeginn bis -ende"
 
-#: export_video_dialog.cc:157
+#: export_video_dialog.cc:156
 msgid "<b>Settings:</b>"
 msgstr "<b>Einstellungen:</b>"
 
-#: export_video_dialog.cc:165
+#: export_video_dialog.cc:164
 msgid "Range:"
 msgstr "Bereich:"
 
-#: export_video_dialog.cc:171
+#: export_video_dialog.cc:170
 msgid "Video Codec:"
 msgstr "Videocodec:"
 
-#: export_video_dialog.cc:174
+#: export_video_dialog.cc:173
 msgid "Video KBit/s:"
 msgstr "Video KBit/s:"
 
-#: export_video_dialog.cc:177
+#: export_video_dialog.cc:176
 msgid "Audio Codec:"
 msgstr "Audiocodec:"
 
-#: export_video_dialog.cc:180
+#: export_video_dialog.cc:179
 msgid "Audio KBit/s:"
 msgstr "Audio KBit/s:"
 
-#: export_video_dialog.cc:183
+#: export_video_dialog.cc:182
 msgid "Audio Samplerate:"
 msgstr "Audiosamplerate:"
 
-#: export_video_dialog.cc:218 export_video_dialog.cc:227
-#: export_video_dialog.cc:810 export_video_dialog.cc:813
+#: export_video_dialog.cc:215 export_video_dialog.cc:223
+#: export_video_dialog.cc:801 export_video_dialog.cc:804
 msgid "(default for format)"
 msgstr "(Voreinstellung für Format)"
 
-#: export_video_dialog.cc:238 export_video_dialog.cc:251
-#: export_video_dialog.cc:817 export_video_dialog.cc:826
+#: export_video_dialog.cc:233 export_video_dialog.cc:244
+#: export_video_dialog.cc:808 export_video_dialog.cc:817
 msgid "(default)"
 msgstr "(Voreinstellung)"
 
-#: export_video_dialog.cc:252 export_video_dialog.cc:820
+#: export_video_dialog.cc:245 export_video_dialog.cc:811
 msgid "(retain)"
 msgstr "(beibehalten)"
 
-#: export_video_dialog.cc:344
+#: export_video_dialog.cc:335
 msgid "from 00:00:00:00 to the video's end"
 msgstr "von 00:00:00:00 bis Videoende"
 
-#: export_video_dialog.cc:346
+#: export_video_dialog.cc:337
 msgid "from the video's start to the video's end"
 msgstr "von Videostart bis Videoende"
 
-#: export_video_dialog.cc:349
+#: export_video_dialog.cc:340
 msgid "Selected range"
 msgstr "Ausgewählter Bereich"
 
-#: export_video_dialog.cc:569
+#: export_video_dialog.cc:560
 msgid "Normalizing audio"
 msgstr "Audio normalisieren"
 
-#: export_video_dialog.cc:573
+#: export_video_dialog.cc:564
 msgid "Exporting audio"
 msgstr "Exportiere Audio"
 
-#: export_video_dialog.cc:628
+#: export_video_dialog.cc:619
 msgid "Exporting Audio..."
 msgstr "Exportiere Audio..."
 
-#: export_video_dialog.cc:685
+#: export_video_dialog.cc:676
 msgid ""
 "Export Video: Cannot query duration of video-file, using duration from "
 "timeline instead."
@@ -14004,37 +14507,37 @@ msgstr ""
 "Exportiere Video: Kann die Dauer der Videodatei nicht eruieren, verwende "
 "statt dessen die Dauer aus der Zeitleiste."
 
-#: export_video_dialog.cc:715
+#: export_video_dialog.cc:706
 msgid "Export Video: export-range does not include video."
 msgstr "Video Export: Exportbereich enthält kein Video."
 
-#: export_video_dialog.cc:728
+#: export_video_dialog.cc:719
 msgid "Export Video: No Master Out Ports to Connect for Audio Export"
 msgstr ""
 "Exportiere Video: Keine Master-Ausgangsports zum Verbinden für den "
 "Audioexport"
 
-#: export_video_dialog.cc:770
+#: export_video_dialog.cc:761
 msgid "Encoding Video..."
 msgstr "Enkodiere Video..."
 
-#: export_video_dialog.cc:790
+#: export_video_dialog.cc:781
 msgid "Export Video: Video input file cannot be read."
 msgstr "Exportiere Video: Die Videoquelldatei kann nicht gelesen werden."
 
-#: export_video_dialog.cc:896
+#: export_video_dialog.cc:887
 msgid "Encoding Video.. Pass 1/2"
 msgstr "Kodiere Video.. Durchgang 1/2"
 
-#: export_video_dialog.cc:908
+#: export_video_dialog.cc:899
 msgid "Encoding Video.. Pass 2/2"
 msgstr "Kodiere Video.. Durchgang 2/2"
 
-#: export_video_dialog.cc:1011
+#: export_video_dialog.cc:1002
 msgid "Transcoding failed."
 msgstr "Transkodieren fehlgeschlagen."
 
-#: export_video_dialog.cc:1247 export_video_dialog.cc:1267
+#: export_video_dialog.cc:1238 export_video_dialog.cc:1258
 msgid "Save Exported Video File"
 msgstr "Sichere exportierte Videodatei"
 
@@ -14054,15 +14557,23 @@ msgstr "<b>Videoexport Informationen</b>"
 
 #: export_video_infobox.cc:51
 msgid ""
+"%1 does not include commercial licenses for encoding audio/video. Visit "
+"mpegla.com for information about licensing various audio/video codecs.\n"
+"\n"
 "Video encoding is a non-trivial task with many details.\n"
 "\n"
-"Please see the manual at %1/video-timeline/operations/#export.\n"
+"Please see the manual at %2/video-timeline/operations/#export.\n"
 "\n"
 "Open Manual in Browser? "
 msgstr ""
-"Das Kodieren von Video ist eine komplexe Aufgabe mit vielen Details.\n"
+"%1 beinhaltet keine kommerziellen Lizenzen, um Audio/Video zu kodieren oder "
+"zu dekodieren. Besuchen Sie mpegla.com, für Informationen zur Lizenzierung "
+"diverser Audio/Video-Codecs.\n"
 "\n"
-"Lesen Sie bitte darüber im Handbuch unter %1/video-timeline/operations/"
-"#export nach.\n"
+"Das Kodieren von Videos ist eine nicht-triviale Aufgabe mit vielen zu "
+"beachtenden Details.\n"
+"\n"
+"Sehen Sie bitte im Handbuch unter %2/Video-Zeitleiste/Bearbeitung/#Export.\n"
 "\n"
 "Handbuch im Browser öffnen? "
+
diff --git a/gtk2_ardour/po/fr.po b/gtk2_ardour/po/fr.po
index b8717d9..9e4dc7a 100644
--- a/gtk2_ardour/po/fr.po
+++ b/gtk2_ardour/po/fr.po
@@ -454,7 +454,7 @@ msgstr "Configuration :"
 
 #: add_route_dialog.cc:58
 msgid "Record Mode:"
-msgstr ""
+msgstr "Mode d'enregistrement"
 
 #: add_route_dialog.cc:59
 msgid "Instrument:"
@@ -514,7 +514,7 @@ msgstr "Groupe :"
 #: add_route_dialog.cc:162
 #, fuzzy
 msgid "Insert:"
-msgstr "&Insérer"
+msgstr "Insérer :"
 
 #: add_route_dialog.cc:223 add_route_dialog.cc:232 add_route_dialog.cc:306
 #: ardour_ui_ed.cc:539 engine_dialog.cc:237 rc_option_editor.cc:1805
@@ -555,8 +555,9 @@ msgid ""
 msgstr ""
 "Les pistes Audio+MIDI doivent être utilisées <b>SEULEMENT</b> avec des "
 "greffons qui utilisent à la fois les entrées audio et MIDI.\n"
-"Si vous n'envisagez pas d'utiliser un tel plugin, utilisez plutôt une piste "
-"audio ou MIDI."
+"\n"
+"Si vous n'envisagez pas d'utiliser un tel greffon, utilisez plutôt une piste "
+"normale audio ou MIDI."
 
 #: add_route_dialog.cc:327 add_route_dialog.cc:346 editor_actions.cc:422
 #: editor_rulers.cc:251 time_axis_view.cc:1374
@@ -12373,23 +12374,23 @@ msgid ""
 "<i>If you do not understand what this is about, just accept the default.</i>"
 msgstr ""
 "Lors de l'enregistrement des instruments ou des voix, vous voudrez\n"
-"sûrement entendre le signal simultanément. C'est appelé « Monitoring ».\n"
-"Il existe différentes manières de le faire, selon matériel et "
-"configuration.\n"
-"Les deux plus courantes sont présentées ici.\n"
-"Merci d'en choisir une convenant à votre configuration.\n"
+"certainement entendre le signal simultanément à son enregistrement. Ceci\n"
+"est appelé le \"monitoring\".\n"
+"Il existe différentes manières de le faire, selon le matériel et sa"
+"configuration. Les deux manières les plus courantes sont présentées ici.\n"
+"Veuillez en choisir une convenant à votre configuration.\n"
 "\n"
-"<i>(Ce choix peut toujours être modifié, dans le menu Préférences)</i>\n"
+"<i>(Ce choix peut être modifié à tout moment, dans le dialogue des Préférences)</i>\n"
 "\n"
-"<i>Si vous ne savez que choisir, conservez l'option par défaut.</i>"
+"<i>Si vous ne savez pas quoi choisir, conservez l'option par défaut.</i>"
 
 #: startup.cc:262
 msgid "Monitoring Choices"
-msgstr "Choix du Monitoring"
+msgstr "Choix du monitoring"
 
 #: startup.cc:285
 msgid "Use a Master bus directly"
-msgstr "Utiliser directement le bus principal"
+msgstr "Utiliser directement le bus principal (le \"master\")"
 
 #: startup.cc:287
 msgid ""
@@ -12397,19 +12398,20 @@ msgid ""
 "for simple usage."
 msgstr ""
 "Connecter le bus principal directement aux sorties matérielles. Cette "
-"configuration est préférable pour un usage simplifié."
+"configuration est préférable pour une utilisation simple."
 
 #: startup.cc:296
 msgid "Use an additional Monitor bus"
-msgstr "Utiliser un Bus de Monitoring supplémentaire"
+msgstr "Utiliser un bus de monitoring supplémentaire"
 
 #: startup.cc:299
 msgid ""
 "Use a Monitor bus between Master bus and hardware outputs for \n"
 "greater control in monitoring without affecting the mix."
 msgstr ""
-"Insérer un Bus de Monitoring entre le Bus Master et les sorties\n"
-"matérielles pour mieux contrôler l'écoute sans impacter le mixage."
+"Insérer un bus de monitoring entre le bus principal (\"master\") et les\n"
+"sorties matérielles pour un plus grand contrôle de l'écoute monitoring\n"
+"sans affecter le mixage."
 
 #: startup.cc:321
 #, fuzzy
@@ -12419,8 +12421,8 @@ msgid ""
 "\n"
 "<i>If you do not understand what this is about, just accept the default.</i>"
 msgstr ""
-"<i>Ceci peut être changée à tout moment dans le menu Préférences.\n"
-"Vous pouvez aussi ajouter/retirer une section de Monitoring de la session.</"
+"<i>Ceci peut être changé à tout moment dans le dialogue de Préférences.\n"
+"Vous pouvez aussi ajouter ou retirer la section d'écoute de toute session.</"
 "i>\n"
 "\n"
 "<i>Si vous ne voyez pas de quoi il s'agit, acceptez le choix par défaut.</i>"
diff --git a/gtk2_ardour/po/ru.po b/gtk2_ardour/po/ru.po
index 5cfb07a..1593470 100644
--- a/gtk2_ardour/po/ru.po
+++ b/gtk2_ardour/po/ru.po
@@ -4,14 +4,14 @@
 #
 # Igor Blinov pitstop at nm.ru, 2004.
 # Александр Кольцов <ag1455 at mail.ru>, 2014, 2015.
-# Alexandre Prokoudine <alexandre.prokoudine at gmail.com>, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014, 2015.
+# Alexandre Prokoudine <alexandre.prokoudine at gmail.com>, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: Ardour 4\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-08-13 09:58+0300\n"
-"PO-Revision-Date: 2015-08-13 10:25+0300\n"
+"POT-Creation-Date: 2016-01-07 03:46+0300\n"
+"PO-Revision-Date: 2016-01-07 04:01+0300\n"
 "Last-Translator: Alexandre Prokoudine <alexandre.prokoudine at gmail.com>\n"
 "Language-Team: русский <>\n"
 "Language: ru\n"
@@ -23,259 +23,271 @@ msgstr ""
 "|| n%100>=20) ? 1 : 2);\n"
 "%100>=20) ? 1: 2);\n"
 
-#: about.cc:125
+#: about.cc:127
 msgid "Brian Ahr"
 msgstr "Brian Ahr"
 
-#: about.cc:126
+#: about.cc:128
 msgid "John Anderson"
 msgstr "John Anderson"
 
-#: about.cc:127
+#: about.cc:129
 msgid "Marcus Andersson"
 msgstr "Marcus Andersson"
 
-#: about.cc:128
+#: about.cc:130
 msgid "Nedko Arnaudov"
 msgstr "Nedko Arnaudov"
 
-#: about.cc:129
+#: about.cc:131
 msgid "Hans Baier"
 msgstr "Hans Baier"
 
-#: about.cc:130
+#: about.cc:132
 msgid "Ben Bell"
 msgstr "Ben Bell"
 
-#: about.cc:131
+#: about.cc:133
 msgid "Sakari Bergen"
 msgstr "Sakari Bergen"
 
-#: about.cc:132
+#: about.cc:134
 msgid "Christian Borss"
 msgstr "Christian Borss"
 
-#: about.cc:133
+#: about.cc:135
 msgid "Chris Cannam"
 msgstr "Chris Cannam"
 
-#: about.cc:134
+#: about.cc:136
 msgid "Jeremy Carter"
 msgstr "Jeremy Carter"
 
-#: about.cc:135
+#: about.cc:137
 msgid "Jesse Chappell"
 msgstr "Jesse Chappell"
 
-#: about.cc:136
+#: about.cc:138
 msgid "Thomas Charbonnel"
 msgstr "Thomas Charbonnel"
 
-#: about.cc:137
+#: about.cc:139
 msgid "Sam Chessman"
 msgstr "Sam Chessman"
 
-#: about.cc:138
+#: about.cc:140
 msgid "André Colomb"
 msgstr "André Colomb"
 
-#: about.cc:139
+#: about.cc:141
 msgid "Paul Davis"
 msgstr "Paul Davis"
 
-#: about.cc:140
+#: about.cc:142
 msgid "Gerard van Dongen"
 msgstr "Gerard van Dongen"
 
-#: about.cc:141
+#: about.cc:143
 msgid "John Emmas"
 msgstr "John Emmas"
 
-#: about.cc:142
+#: about.cc:144
 msgid "Colin Fletcher"
 msgstr "Colin Fletcher"
 
-#: about.cc:143
+#: about.cc:145
 msgid "Dave Flick"
 msgstr "Dave Flick"
 
-#: about.cc:144
+#: about.cc:146
 msgid "Hans Fugal"
 msgstr "Hans Fugal"
 
-#: about.cc:145
+#: about.cc:147
 msgid "Robin Gareus"
 msgstr "Robin Gareus"
 
-#: about.cc:146
+#: about.cc:148
+msgid "Nil Geisweiller"
+msgstr "Nil Geisweiller"
+
+#: about.cc:149
 msgid "Christopher George"
 msgstr "Christopher George"
 
-#: about.cc:147
+#: about.cc:150
 msgid "Chris Goddard"
 msgstr "Chris Goddard"
 
-#: about.cc:148
+#: about.cc:151
 msgid "J. Abelardo Gutierrez"
 msgstr "J. Abelardo Gutierrez"
 
-#: about.cc:149
+#: about.cc:152
 msgid "Jeremy Hall"
 msgstr "Jeremy Hall"
 
-#: about.cc:150
+#: about.cc:153
 msgid "Audun Halland"
 msgstr "Audun Halland"
 
-#: about.cc:151
+#: about.cc:154
 msgid "David Halter"
 msgstr "David Halter"
 
-#: about.cc:152
+#: about.cc:155
 msgid "Steve Harris"
 msgstr "Steve Harris"
 
-#: about.cc:153
+#: about.cc:156
 msgid "Melvin Ray Herr"
 msgstr "Melvin Ray Herr"
 
-#: about.cc:154
+#: about.cc:157
 msgid "Carl Hetherington"
 msgstr "Carl Hetherington"
 
-#: about.cc:155
+#: about.cc:158
 msgid "Rob Holland"
 msgstr "Rob Holland"
 
-#: about.cc:156
+#: about.cc:159
 msgid "Robert Jordens"
 msgstr "Robert Jordens"
 
-#: about.cc:157
+#: about.cc:160
 msgid "Stefan Kersten"
 msgstr "Stefan Kersten"
 
-#: about.cc:158
+#: about.cc:161
 msgid "Armand Klenk"
 msgstr "Armand Klenk"
 
-#: about.cc:159
+#: about.cc:162
 msgid "Julien de Kozak"
 msgstr "Julien de Kozak"
 
-#: about.cc:160
+#: about.cc:163
 msgid "Matt Krai"
 msgstr "Matt Krai"
 
-#: about.cc:161
+#: about.cc:164
 msgid "Georg Krause"
 msgstr "Georg Krause"
 
-#: about.cc:162
+#: about.cc:165
 msgid "Nick Lanham"
 msgstr "Nick Lanham"
 
-#: about.cc:163
+#: about.cc:166
 msgid "Colin Law"
 msgstr "Colin Law"
 
-#: about.cc:164
+#: about.cc:167
 msgid "Joshua Leach"
 msgstr "Joshua Leach"
 
-#: about.cc:165
+#: about.cc:168
 msgid "Ben Loftis"
 msgstr "Ben Loftis"
 
-#: about.cc:166
+#: about.cc:169
 msgid "Nick Mainsbridge"
 msgstr "Nick Mainsbridge"
 
-#: about.cc:167
+#: about.cc:170
 msgid "Tim Mayberry"
 msgstr "Tim Mayberry"
 
-#: about.cc:168
+#: about.cc:171
 msgid "Doug Mclain"
 msgstr "Doug Mclain"
 
-#: about.cc:169
+#: about.cc:172
 msgid "Todd Naugle"
 msgstr "Todd Naugle"
 
-#: about.cc:170
+#: about.cc:173
+msgid "André Nusser"
+msgstr "André Nusser"
+
+#: about.cc:174
+msgid "Bent Bisballe Nyeng"
+msgstr "Bent Bisballe Nyeng"
+
+#: about.cc:175
 msgid "Jack O'Quin"
 msgstr "Jack O'Quin"
 
-#: about.cc:171
+#: about.cc:176
 msgid "Nimal Ratnayake"
 msgstr "Nimal Ratnayake"
 
-#: about.cc:172
+#: about.cc:177
 msgid "David Robillard"
 msgstr "David Robillard"
 
-#: about.cc:173
+#: about.cc:178
 msgid "Taybin Rutkin"
 msgstr "Taybin Rutkin"
 
-#: about.cc:174
+#: about.cc:179
 msgid "Andreas Ruge"
 msgstr "Andreas Ruge"
 
-#: about.cc:175
+#: about.cc:180
 msgid "Sampo Savolainen"
 msgstr "Sampo Savolainen"
 
-#: about.cc:176
+#: about.cc:181
 msgid "Rodrigo Severo"
 msgstr "Rodrigo Severo"
 
-#: about.cc:177
+#: about.cc:182
 msgid "Per Sigmond"
 msgstr "Per Sigmond"
 
-#: about.cc:178
+#: about.cc:183
 msgid "Lincoln Spiteri"
 msgstr "Lincoln Spiteri"
 
-#: about.cc:179
+#: about.cc:184
 msgid "Mike Start"
 msgstr "Mike Start"
 
-#: about.cc:180
+#: about.cc:185
 msgid "Mark Stewart"
 msgstr "Mark Stewart"
 
-#: about.cc:181
+#: about.cc:186
 msgid "Roland Stigge"
 msgstr "Roland Stigge"
 
-#: about.cc:182
+#: about.cc:187
 msgid "Petter Sundlöf"
 msgstr "Petter Sundlöf"
 
-#: about.cc:183
+#: about.cc:188
 msgid "Mike Täht"
 msgstr "Mike Täht"
 
-#: about.cc:184
+#: about.cc:189
 msgid "Roy Vegard"
 msgstr "Roy Vegard"
 
-#: about.cc:185
+#: about.cc:190
 msgid "Thorsten Wilms"
 msgstr "Thorsten Wilms"
 
-#: about.cc:186
+#: about.cc:191
 msgid "Damien Zammit"
 msgstr "Damien Zammit"
 
-#: about.cc:187
+#: about.cc:192
 msgid "Grygorii Zharun"
 msgstr "Grygorii Zharun"
 
-#: about.cc:192
+#: about.cc:197
 msgid ""
 "French:\n"
 "\tAlain Fréhel <alain.frehel at free.fr>\n"
@@ -289,7 +301,7 @@ msgstr ""
 "\tMartin Blanchard\n"
 "\tRomain Arnaud <roming22 at gmail.com>\n"
 
-#: about.cc:193
+#: about.cc:198
 msgid ""
 "German:\n"
 "\tKarsten Petersen <kapet at kapet.de>\n"
@@ -309,7 +321,7 @@ msgstr ""
 "\tRichard Oax <richard at pagliacciempire.de>\n"
 "\tRobin Gloster <robin at loc-com.de>\n"
 
-#: about.cc:200
+#: about.cc:205
 msgid ""
 "Italian:\n"
 "\tFilippo Pappalardo <filippo at email.it>\n"
@@ -319,7 +331,7 @@ msgstr ""
 "\tFilippo Pappalardo <filippo at email.it>\n"
 "\tRaffaele Morelli <raffaele.morelli at gmail.com>\n"
 
-#: about.cc:201
+#: about.cc:206
 msgid ""
 "Portuguese:\n"
 "\tRui Nuno Capela <rncbc at rncbc.org>\n"
@@ -327,7 +339,7 @@ msgstr ""
 "Португальский:\n"
 "\tRui Nuno Capela <rncbc at rncbc.org>\n"
 
-#: about.cc:202
+#: about.cc:207
 msgid ""
 "Brazilian Portuguese:\n"
 "\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
@@ -337,7 +349,7 @@ msgstr ""
 "\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
 "\tChris Ross <chris at tebibyte.org>\n"
 
-#: about.cc:204
+#: about.cc:209
 msgid ""
 "Spanish:\n"
 "\t Alex Krohn <alexkrohn at fastmail.fm>\n"
@@ -347,7 +359,7 @@ msgstr ""
 "\t Alex Krohn <alexkrohn at fastmail.fm>\n"
 "\tPablo Fernández <pablo.fbus at gmail.com>\n"
 
-#: about.cc:205
+#: about.cc:210
 msgid ""
 "Russian:\n"
 "\t Igor Blinov <pitstop at nm.ru>\n"
@@ -358,7 +370,7 @@ msgstr ""
 "\tАлександр Прокудин <alexandre.prokoudine at gmail.com>\n"
 "\tАлександр Кольцов <ag1455 at mail.ru>"
 
-#: about.cc:207
+#: about.cc:212
 msgid ""
 "Greek:\n"
 "\t Klearchos Gourgourinis <muadib at in.gr>\n"
@@ -366,7 +378,7 @@ msgstr ""
 "Греческий:\n"
 "\t Klearchos Gourgourinis <muadib at in.gr>\n"
 
-#: about.cc:208
+#: about.cc:213
 msgid ""
 "Swedish:\n"
 "\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
@@ -374,7 +386,7 @@ msgstr ""
 "Шведский:\n"
 "\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
 
-#: about.cc:209
+#: about.cc:214
 msgid ""
 "Polish:\n"
 "\t Piotr Zaryk <pzaryk at gmail.com>\n"
@@ -382,7 +394,7 @@ msgstr ""
 "Польский:\n"
 "\t Piotr Zaryk <pzaryk at gmail.com>\n"
 
-#: about.cc:210
+#: about.cc:215
 msgid ""
 "Czech:\n"
 "\t Pavel Fric <pavelfric at seznam.cz>\n"
@@ -390,7 +402,7 @@ msgstr ""
 "Чешский:\n"
 "\t Pavel Fric <pavelfric at seznam.cz>\n"
 
-#: about.cc:211
+#: about.cc:216
 msgid ""
 "Norwegian:\n"
 "\t Eivind Ødegård\n"
@@ -398,7 +410,7 @@ msgstr ""
 "Норвежский:\n"
 "\t Eivind Ødegård\n"
 
-#: about.cc:212
+#: about.cc:217
 msgid ""
 "Chinese:\n"
 "\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
@@ -406,39 +418,65 @@ msgstr ""
 "Китайский:\n"
 "\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
 
-#: about.cc:592
+#: about.cc:597
+msgid "Intel 64-bit"
+msgstr "Intel 64-bit"
+
+#: about.cc:599
+msgid "Intel 32-bit"
+msgstr "Intel 32-bit"
+
+#: about.cc:601
+msgid "PowerPC 64-bit"
+msgstr "PowerPC 64-bit"
+
+#: about.cc:603
+msgid "PowerPC 32-bit"
+msgstr "PowerPC 32-bit"
+
+#: about.cc:605
+msgid "64-bit"
+msgstr "64-bit"
+
+#: about.cc:607
+msgid "32-bit"
+msgstr "32-bit"
+
+#: about.cc:615
 msgid "Copyright (C) 1999-2015 Paul Davis\n"
 msgstr "Авторские права (C) 1999-2015 Paul Davis\n"
 
-#: about.cc:596
+#: about.cc:619
 msgid "http://ardour.org/"
 msgstr "http://ardour.org/"
 
-#: about.cc:597
+#: about.cc:620
 msgid ""
 "%1%2\n"
-"(built from revision %3)"
+"(built from revision %3)\n"
+"%4"
 msgstr ""
 "%1%2\n"
-"(собрано из редакции %3)"
+"(собрано из редакции %3)\n"
+"%4"
 
-#: about.cc:601
+#: about.cc:625
 msgid "Config"
 msgstr "Конфигурация сборки"
 
-#: actions.cc:85
+#: actions.cc:83
 msgid "Loading menus from %1"
 msgstr "Загружается меню из %1"
 
-#: actions.cc:88 actions.cc:89
+#: actions.cc:86 actions.cc:87
 msgid "badly formatted menu definition file: %1"
 msgstr "Неправильный формат файла определения меню: %1"
 
-#: actions.cc:91
+#: actions.cc:89
 msgid "%1 menu definition file not found"
 msgstr "Файл определения меню %1 не найден"
 
-#: actions.cc:95 actions.cc:96
+#: actions.cc:93 actions.cc:94
 msgid "%1 will not work without a valid menu definition file"
 msgstr "%1 не будет работать без правильного меню описания файла"
 
@@ -474,15 +512,15 @@ msgstr "Смешанные дорожки (Звук+MIDI)"
 msgid "Busses"
 msgstr "Шины"
 
-#: add_route_dialog.cc:83 add_route_dialog.cc:559
+#: add_route_dialog.cc:83 add_route_dialog.cc:554
 msgid "First"
 msgstr "В начало"
 
-#: add_route_dialog.cc:84 add_route_dialog.cc:563
+#: add_route_dialog.cc:84 add_route_dialog.cc:558
 msgid "Before Selection"
 msgstr "Перед выделенным"
 
-#: add_route_dialog.cc:85 add_route_dialog.cc:561
+#: add_route_dialog.cc:85 add_route_dialog.cc:556
 msgid "After Selection"
 msgstr "После выделенного"
 
@@ -495,11 +533,11 @@ msgid "Add:"
 msgstr "Добавить:"
 
 #: add_route_dialog.cc:116 time_fx_dialog.cc:91 add_video_dialog.cc:135
-#: video_server_dialog.cc:121
+#: video_server_dialog.cc:118
 msgid "<b>Options</b>"
 msgstr "<b>Параметры</b>"
 
-#: add_route_dialog.cc:126 bundle_manager.cc:193 region_editor.cc:50
+#: add_route_dialog.cc:126 bundle_manager.cc:193 region_editor.cc:52
 #: route_group_dialog.cc:71
 msgid "Name:"
 msgstr "Имя:"
@@ -513,23 +551,25 @@ msgid "Insert:"
 msgstr "Вставить:"
 
 #: add_route_dialog.cc:223 add_route_dialog.cc:232 add_route_dialog.cc:306
-#: ardour_ui_ed.cc:548 engine_dialog.cc:240 rc_option_editor.cc:2279
-#: rc_option_editor.cc:2281 rc_option_editor.cc:2283 rc_option_editor.cc:2301
-#: rc_option_editor.cc:2303 rc_option_editor.cc:2311 rc_option_editor.cc:2313
-#: rc_option_editor.cc:2331 rc_option_editor.cc:2344 rc_option_editor.cc:2346
-#: rc_option_editor.cc:2348 rc_option_editor.cc:2393 rc_option_editor.cc:2395
-#: rc_option_editor.cc:2397 rc_option_editor.cc:2405 rc_option_editor.cc:2413
-#: rc_option_editor.cc:2415 rc_option_editor.cc:2423
+#: ardour_ui_ed.cc:574 engine_dialog.cc:242 rc_option_editor.cc:2257
+#: rc_option_editor.cc:2259 rc_option_editor.cc:2261 rc_option_editor.cc:2279
+#: rc_option_editor.cc:2281 rc_option_editor.cc:2290 rc_option_editor.cc:2292
+#: rc_option_editor.cc:2310 rc_option_editor.cc:2323 rc_option_editor.cc:2326
+#: rc_option_editor.cc:2328 rc_option_editor.cc:2373 rc_option_editor.cc:2375
+#: rc_option_editor.cc:2377 rc_option_editor.cc:2385 rc_option_editor.cc:2393
+#: rc_option_editor.cc:2395 rc_option_editor.cc:2403
 msgid "Audio"
 msgstr "Аудио"
 
 #: add_route_dialog.cc:224 add_route_dialog.cc:235 add_route_dialog.cc:307
-#: editor_actions.cc:109 engine_dialog.cc:242 missing_file_dialog.cc:56
-#: rc_option_editor.cc:2558 rc_option_editor.cc:2568 rc_option_editor.cc:2576
-#: rc_option_editor.cc:2584 rc_option_editor.cc:2593 rc_option_editor.cc:2601
-#: rc_option_editor.cc:2609 rc_option_editor.cc:2617 rc_option_editor.cc:2626
-#: rc_option_editor.cc:2635 rc_option_editor.cc:2644 rc_option_editor.cc:2652
-#: rc_option_editor.cc:2660 rc_option_editor.cc:2668 rc_option_editor.cc:2691
+#: editor_actions.cc:110 engine_dialog.cc:244 missing_file_dialog.cc:60
+#: rc_option_editor.cc:2536 rc_option_editor.cc:2538 rc_option_editor.cc:2548
+#: rc_option_editor.cc:2557 rc_option_editor.cc:2565 rc_option_editor.cc:2573
+#: rc_option_editor.cc:2581 rc_option_editor.cc:2589 rc_option_editor.cc:2591
+#: rc_option_editor.cc:2599 rc_option_editor.cc:2601 rc_option_editor.cc:2609
+#: rc_option_editor.cc:2618 rc_option_editor.cc:2620 rc_option_editor.cc:2628
+#: rc_option_editor.cc:2636 rc_option_editor.cc:2645 rc_option_editor.cc:2654
+#: rc_option_editor.cc:2677
 msgid "MIDI"
 msgstr "MIDI"
 
@@ -556,8 +596,8 @@ msgstr ""
 "Если вы не собираетесь использовать такие плагины, используйте обычные "
 "звуковые и MIDI-дорожки."
 
-#: add_route_dialog.cc:327 add_route_dialog.cc:346 editor_actions.cc:431
-#: editor_rulers.cc:251 time_axis_view.cc:1385
+#: add_route_dialog.cc:327 add_route_dialog.cc:346 editor_actions.cc:438
+#: editor_rulers.cc:250 time_axis_view.cc:1383
 msgid "Normal"
 msgstr "Обычный"
 
@@ -569,7 +609,7 @@ msgstr "Бесслойный"
 msgid "Tape"
 msgstr "Плёночный"
 
-#: add_route_dialog.cc:431 monitor_section.cc:296
+#: add_route_dialog.cc:431 monitor_section.cc:272
 msgid "Mono"
 msgstr "Моно"
 
@@ -601,7 +641,7 @@ msgstr "8 каналов"
 msgid "12 Channel"
 msgstr "3 канала"
 
-#: add_route_dialog.cc:483 mixer_strip.cc:1898 mixer_strip.cc:2306
+#: add_route_dialog.cc:483 mixer_strip.cc:1918 mixer_strip.cc:2351
 msgid "Custom"
 msgstr "На заказ"
 
@@ -617,7 +657,7 @@ msgstr "Нет группы"
 msgid "Ambiguous File"
 msgstr "Неоднозначный файл"
 
-#: ambiguous_file_dialog.cc:35
+#: ambiguous_file_dialog.cc:37
 msgid ""
 "%1 has found the file <i>%2</i> in the following places:\n"
 "\n"
@@ -625,7 +665,7 @@ msgstr ""
 "%1 обнаружил файл <i>%2</i> в следующих папках:\n"
 "\n"
 
-#: ambiguous_file_dialog.cc:44
+#: ambiguous_file_dialog.cc:46
 msgid ""
 "\n"
 "\n"
@@ -635,7 +675,7 @@ msgstr ""
 "\n"
 "Выберите, из какой папки загрузить этот файл."
 
-#: ambiguous_file_dialog.cc:46 missing_file_dialog.cc:46
+#: ambiguous_file_dialog.cc:48 missing_file_dialog.cc:50
 msgid "Done"
 msgstr "Готово"
 
@@ -675,16 +715,15 @@ msgstr "Нормировать значения"
 msgid "FFT analysis window"
 msgstr "Спектральный анализ"
 
-#: analysis_window.cc:60 editor.cc:1835
+#: analysis_window.cc:60 editor.cc:1848
 msgid "Spectral Analysis"
 msgstr "Спектральный анализ"
 
-#: analysis_window.cc:67 editor_actions.cc:142 session_metadata_dialog.cc:667
+#: analysis_window.cc:67 editor_actions.cc:143 session_metadata_dialog.cc:667
 msgid "Track"
 msgstr "Дорожка"
 
-#: analysis_window.cc:68 editor_actions.cc:657 mixer_ui.cc:131
-#: mixer_ui.cc:1874
+#: analysis_window.cc:68 editor_actions.cc:664 mixer_ui.cc:135 mixer_ui.cc:2040
 msgid "Show"
 msgstr "Показать"
 
@@ -700,7 +739,7 @@ msgstr "Кнопка не может видеть состояние несущ
 msgid "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
 msgstr "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
 
-#: ardour_ui.cc:172
+#: ardour_ui.cc:174
 msgid ""
 "%1 %2.x has discovered configuration files from %1 %3.x.\n"
 "\n"
@@ -714,82 +753,82 @@ msgstr ""
 "\n"
 "(%1 придётся перезапустить.)\n"
 
-#: ardour_ui.cc:252 editor_actions.cc:651 region_editor.cc:51
+#: ardour_ui.cc:253 editor_actions.cc:658 region_editor.cc:53
 msgid "Audition"
 msgstr "Контроль"
 
-#: ardour_ui.cc:253 editor_actions.cc:136 mixer_strip.cc:2078
-#: monitor_section.cc:376 rc_option_editor.cc:2433 route_time_axis.cc:254
-#: route_time_axis.cc:2739
+#: ardour_ui.cc:254 editor_actions.cc:137 mixer_strip.cc:2101
+#: monitor_section.cc:328 rc_option_editor.cc:2413 route_time_axis.cc:255
+#: route_time_axis.cc:2748
 msgid "Solo"
 msgstr "Соло"
 
-#: ardour_ui.cc:254 rc_option_editor.cc:1192
+#: ardour_ui.cc:255 rc_option_editor.cc:1356
 msgid "Feedback"
 msgstr "Отклик"
 
-#: ardour_ui.cc:265 speaker_dialog.cc:36
+#: ardour_ui.cc:264 speaker_dialog.cc:36
 msgid "Speaker Configuration"
 msgstr "Конфигурация громкоговорителей"
 
-#: ardour_ui.cc:266 keyeditor.cc:53
+#: ardour_ui.cc:265 keyeditor.cc:53
 msgid "Key Bindings"
 msgstr "Клавиатурные комбинации"
 
-#: ardour_ui.cc:267
+#: ardour_ui.cc:266
 msgid "Preferences"
 msgstr "Параметры"
 
-#: ardour_ui.cc:268 ardour_ui.cc:275
+#: ardour_ui.cc:267 ardour_ui.cc:274
 msgid "Add Tracks/Busses"
 msgstr "Добавить дорожки/шины"
 
-#: ardour_ui.cc:269
+#: ardour_ui.cc:268
 msgid "About"
 msgstr "О программе"
 
-#: ardour_ui.cc:270 location_ui.cc:1141 session_option_editor.cc:189
-#: session_option_editor.cc:195 session_option_editor.cc:202
+#: ardour_ui.cc:269 location_ui.cc:1143 session_option_editor.cc:210
+#: session_option_editor.cc:216 session_option_editor.cc:223
 msgid "Locations"
 msgstr "Позиции"
 
-#: ardour_ui.cc:271 route_params_ui.cc:59 route_params_ui.cc:630
+#: ardour_ui.cc:270 route_params_ui.cc:59 route_params_ui.cc:630
 msgid "Tracks and Busses"
 msgstr "Дорожки и шины"
 
-#: ardour_ui.cc:272 engine_dialog.cc:74
+#: ardour_ui.cc:271 engine_dialog.cc:73
 msgid "Audio/MIDI Setup"
 msgstr "Настройка звука и MIDI"
 
-#: ardour_ui.cc:273
+#: ardour_ui.cc:272
 msgid "Video Export Dialog"
 msgstr "Диалог экспорта видео"
 
-#: ardour_ui.cc:274
+#: ardour_ui.cc:273
 msgid "Properties"
 msgstr "Свойства"
 
-#: ardour_ui.cc:276 bundle_manager.cc:264
+#: ardour_ui.cc:275 bundle_manager.cc:264
 msgid "Bundle Manager"
 msgstr "Управление пакетами"
 
-#: ardour_ui.cc:277 big_clock_window.cc:37
+#: ardour_ui.cc:276 big_clock_window.cc:37
 msgid "Big Clock"
 msgstr "Большой счётчик"
 
-#: ardour_ui.cc:278
+#: ardour_ui.cc:277
 msgid "Audio Connections"
 msgstr "Звуковые соединения"
 
-#: ardour_ui.cc:279
+#: ardour_ui.cc:278
 msgid "MIDI Connections"
 msgstr "Соединения MIDI"
 
-#: ardour_ui.cc:293
+#: ardour_ui.cc:295
 msgid "Your configuration files were copied. You can now restart %1."
 msgstr "Ваши файлы с настройками скопированы. Можно перезапустить %1."
 
-#: ardour_ui.cc:519
+#: ardour_ui.cc:527
 msgid ""
 "The audio backend was shutdown because:\n"
 "\n"
@@ -799,7 +838,7 @@ msgstr ""
 "\n"
 "%1"
 
-#: ardour_ui.cc:521
+#: ardour_ui.cc:529
 msgid ""
 "The audio backend has either been shutdown or it\n"
 "disconnected %1 because %1\n"
@@ -811,7 +850,7 @@ msgstr ""
 "работал недостаточно быстро. Попробуйте снова\n"
 "запустить подсистему и сохранить сессию."
 
-#: ardour_ui.cc:545
+#: ardour_ui.cc:553
 msgid ""
 "Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. "
 "Please see the log window for further details."
@@ -819,39 +858,39 @@ msgstr ""
 "Не удалось просканировать плагины Audio Unit. Автоматическое сканирование AU "
 "выключено. Подробности указаны в окне журнала."
 
-#: ardour_ui.cc:546
+#: ardour_ui.cc:554
 msgid "Audio Unit Plugin Scan Failed:"
 msgstr "Не удалось просканировать плагины Audio Unit:"
 
-#: ardour_ui.cc:877
+#: ardour_ui.cc:903
 msgid "NSM server did not announce itself"
 msgstr "Сервер NSM не объявлял о себе"
 
-#: ardour_ui.cc:890
+#: ardour_ui.cc:916
 msgid "NSM: no client ID provided"
 msgstr "NSM: не предоставлен ни один ID-клиент"
 
-#: ardour_ui.cc:897
+#: ardour_ui.cc:923
 msgid "NSM: no session created"
 msgstr "NSM: нет созданной сессии"
 
-#: ardour_ui.cc:920
+#: ardour_ui.cc:946
 msgid "NSM: initialization failed"
 msgstr "NSM: сбой инициализации"
 
-#: ardour_ui.cc:952
+#: ardour_ui.cc:978
 msgid "Free/Demo Version Warning"
 msgstr "Предупреждение демоверсии"
 
-#: ardour_ui.cc:954
+#: ardour_ui.cc:980
 msgid "Subscribe and support development of %1"
 msgstr "Подписаться и поддержать разработку %1"
 
-#: ardour_ui.cc:955
+#: ardour_ui.cc:981
 msgid "Don't warn me about this again"
 msgstr "Больше не предупреждать"
 
-#: ardour_ui.cc:957
+#: ardour_ui.cc:983
 msgid ""
 "<span weight=\"bold\" size=\"large\">%1</span>\n"
 "\n"
@@ -869,15 +908,15 @@ msgstr ""
 "\n"
 "%4"
 
-#: ardour_ui.cc:958
+#: ardour_ui.cc:984
 msgid "This is a free/demo version of %1"
 msgstr "Это демонстрационная версия %1"
 
-#: ardour_ui.cc:959
+#: ardour_ui.cc:985
 msgid "It will not restore OR save any plugin settings"
 msgstr "Она не сохраняет и не восстанавливает параметры плагинов."
 
-#: ardour_ui.cc:960
+#: ardour_ui.cc:986
 msgid ""
 "If you load an existing session with plugin settings\n"
 "they will not be used and will be lost."
@@ -885,7 +924,7 @@ msgstr ""
 "Если вы загрузите существующую сессию, все собственные \n"
 "параметры плагинов будут сброшены и потеряны при сохранении."
 
-#: ardour_ui.cc:962 plugin_ui.cc:579
+#: ardour_ui.cc:988 plugin_ui.cc:579
 msgid ""
 "To get full access to updates without this limitation\n"
 "consider becoming a subscriber for a low cost every month."
@@ -893,19 +932,19 @@ msgstr ""
 "Чтобы получить полный доступ к обновлениям без ограничений,\n"
 "необходима ежемесячная подписка по низкой цене."
 
-#: ardour_ui.cc:972
+#: ardour_ui.cc:998
 msgid "Quit now"
 msgstr "Выйти"
 
-#: ardour_ui.cc:973
+#: ardour_ui.cc:999
 msgid "Continue using %1"
 msgstr "Продолжить работу"
 
-#: ardour_ui.cc:1006 startup.cc:346
+#: ardour_ui.cc:1032 startup.cc:348
 msgid "%1 is ready for use"
 msgstr "%1 готов к работе"
 
-#: ardour_ui.cc:1048
+#: ardour_ui.cc:1074
 msgid ""
 "WARNING: Your system has a limit for maximum amount of locked memory. This "
 "might cause %1 to run out of memory before your system runs out of memory. \n"
@@ -920,23 +959,23 @@ msgstr ""
 "Вы можете узнать установленный предел при помощи команды 'ulimit -l'. Обычно "
 "это контролируется в %2."
 
-#: ardour_ui.cc:1065
+#: ardour_ui.cc:1091
 msgid "Do not show this window again"
 msgstr "Больше не показывать это окно"
 
-#: ardour_ui.cc:1109
+#: ardour_ui.cc:1135
 msgid "Don't quit"
 msgstr "Не выходить"
 
-#: ardour_ui.cc:1110
+#: ardour_ui.cc:1136
 msgid "Just quit"
 msgstr "Просто выйти"
 
-#: ardour_ui.cc:1111 ardour_ui.cc:4903
+#: ardour_ui.cc:1137 ardour_ui.cc:5010
 msgid "Save and quit"
 msgstr "Сохранить и выйти"
 
-#: ardour_ui.cc:1121
+#: ardour_ui.cc:1147
 msgid ""
 "%1 was unable to save your session.\n"
 "\n"
@@ -951,11 +990,11 @@ msgstr ""
 "\n"
 "«Просто выйти»."
 
-#: ardour_ui.cc:1171
+#: ardour_ui.cc:1197
 msgid "Unsaved Session"
 msgstr "Сессия не сохранена"
 
-#: ardour_ui.cc:1192
+#: ardour_ui.cc:1218
 msgid ""
 "The session \"%1\"\n"
 "has not been saved.\n"
@@ -973,7 +1012,7 @@ msgstr ""
 "\n"
 "Что вы хотите сделать?"
 
-#: ardour_ui.cc:1195
+#: ardour_ui.cc:1221
 msgid ""
 "The snapshot \"%1\"\n"
 "has not been saved.\n"
@@ -991,93 +1030,106 @@ msgstr ""
 "\n"
 "Что вы хотите сделать?"
 
-#: ardour_ui.cc:1209
+#: ardour_ui.cc:1235
 msgid "Prompter"
 msgstr "Суфлер"
 
-#: ardour_ui.cc:1322 ardour_ui.cc:1330
+#: ardour_ui.cc:1349 ardour_ui.cc:1357
 msgid "Audio: <span foreground=\"red\">none</span>"
 msgstr "Звук: <span foreground=\"red\">нет</span>"
 
-#: ardour_ui.cc:1334
+#: ardour_ui.cc:1361
 #, c-format
 msgid "Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"
 msgstr "Звук: <span foreground=\"green\">%.1f КГц / %4.1f мс</span>"
 
-#: ardour_ui.cc:1338
+#: ardour_ui.cc:1365
 #, c-format
 msgid "Audio: <span foreground=\"green\">%<PRId64> kHz / %4.1f ms</span>"
 msgstr "Звук: <span foreground=\"green\">%<PRId64> КГц / %4.1f мс</span>"
 
-#: ardour_ui.cc:1356 export_video_dialog.cc:76
+#: ardour_ui.cc:1383 export_video_dialog.cc:76
 msgid "File:"
 msgstr "Файл:"
 
-#: ardour_ui.cc:1360
+#: ardour_ui.cc:1387
 msgid "BWF"
 msgstr "BWF"
 
-#: ardour_ui.cc:1363
+#: ardour_ui.cc:1390
 msgid "WAV"
 msgstr "WAV"
 
-#: ardour_ui.cc:1366
+#: ardour_ui.cc:1393
 msgid "WAV64"
 msgstr "WAV64"
 
-#: ardour_ui.cc:1369 session_option_editor.cc:185
+#: ardour_ui.cc:1396 session_option_editor.cc:202
 msgid "CAF"
 msgstr "CAF"
 
-#: ardour_ui.cc:1372
+#: ardour_ui.cc:1399
 msgid "AIFF"
 msgstr "AIFF"
 
-#: ardour_ui.cc:1375
+#: ardour_ui.cc:1402
 msgid "iXML"
 msgstr "iXML"
 
-#: ardour_ui.cc:1378
+#: ardour_ui.cc:1405 session_option_editor.cc:203
 msgid "RF64"
 msgstr "RF64"
 
-#: ardour_ui.cc:1386
+#: ardour_ui.cc:1408
+msgid "RF64/WAV"
+msgstr "RF64/WAV"
+
+#: ardour_ui.cc:1411
+msgid "MBWF"
+msgstr "MBWF"
+
+#: ardour_ui.cc:1419
 msgid "32-float"
 msgstr "32-float"
 
-#: ardour_ui.cc:1389
+#: ardour_ui.cc:1422
 msgid "24-int"
 msgstr "24-int"
 
-#: ardour_ui.cc:1392
+#: ardour_ui.cc:1425
 msgid "16-int"
 msgstr "16-int"
 
-#: ardour_ui.cc:1413
+#: ardour_ui.cc:1446
 #, c-format
 msgid "X: <span foreground=\"%s\">>10K</span>"
 msgstr ""
 
-#: ardour_ui.cc:1415
+#: ardour_ui.cc:1448
 #, c-format
 msgid "X: <span foreground=\"%s\">%u</span>"
-msgstr ""
+msgstr "X: <span foreground=\"%s\">%u</span>"
 
-#: ardour_ui.cc:1418
+#: ardour_ui.cc:1451
 #, c-format
 msgid "X: <span foreground=\"%s\">?</span>"
-msgstr ""
+msgstr "X: <span foreground=\"%s\">?</span>"
 
-#: ardour_ui.cc:1421
+#: ardour_ui.cc:1454
 msgid "Audio dropouts. Shift+click to reset"
 msgstr ""
 
-#: ardour_ui.cc:1434
+#: ardour_ui.cc:1467
 #, c-format
 msgid "DSP: <span foreground=\"%s\">%5.1f%%</span>"
 msgstr "ЦП: <span foreground=\"%s\">%5.1f%%</span>"
 
-#: ardour_ui.cc:1453
+#: ardour_ui.cc:1477
+#, c-format
+msgid "PkBld: <span foreground=\"%s\">%d</span>"
+msgstr ""
+
+#: ardour_ui.cc:1499
 #, c-format
 msgid ""
 "Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">"
@@ -1088,34 +1140,29 @@ msgstr ""
 "%%</span> <span foreground=\"green\">c:</span><span foreground=\"%s\">"
 "%<PRIu32>%%</span>"
 
-#: ardour_ui.cc:1494
+#: ardour_ui.cc:1540
 msgid "Disk: <span foreground=\"green\">Unknown</span>"
 msgstr "На диске: <span foreground=\"green\">неизвестно</span>"
 
-#: ardour_ui.cc:1496
+#: ardour_ui.cc:1542
 msgid "Disk: <span foreground=\"green\">24hrs+</span>"
 msgstr "На диске: <span foreground=\"green\">24ч+</span>"
 
-#: ardour_ui.cc:1514
+#: ardour_ui.cc:1560
 msgid "Disk: <span foreground=\"green\">>24 hrs</span>"
 msgstr "На диске: <span foreground=\"green\">>24ч</span>"
 
-#: ardour_ui.cc:1525
+#: ardour_ui.cc:1571
 #, c-format
 msgid "Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"
 msgstr "На диске:  <span foreground=\"%s\">%02dч:%02dм:%02dс</span>"
 
-#: ardour_ui.cc:1551
+#: ardour_ui.cc:1597
 #, c-format
 msgid "Timecode|TC: <span foreground=\"%s\">%s</span>"
 msgstr "ТК: <span foreground=\"%s\">%s</span>"
 
-#: ardour_ui.cc:1672 ardour_ui.cc:1681 session_dialog.cc:318
-#: session_dialog.cc:323
-msgid "Recent Sessions"
-msgstr "Недавние сессии"
-
-#: ardour_ui.cc:1760
+#: ardour_ui.cc:1675
 msgid ""
 "%1 is not connected to any audio backend.\n"
 "You cannot open or close sessions in this condition"
@@ -1123,27 +1170,27 @@ msgstr ""
 "%1 не соединен с какой-либо звуковой подсистемой.\n"
 "Открытие и закрытие сессий невозможно."
 
-#: ardour_ui.cc:1784
+#: ardour_ui.cc:1693
 msgid "Open Session"
 msgstr "Открыть сессию"
 
-#: ardour_ui.cc:1809 session_dialog.cc:349 session_import_dialog.cc:170
+#: ardour_ui.cc:1717 session_dialog.cc:407 session_import_dialog.cc:170
 #: session_metadata_dialog.cc:858
 msgid "%1 sessions"
 msgstr "Cеансы %1"
 
-#: ardour_ui.cc:1846
+#: ardour_ui.cc:1748
 msgid "You cannot add a track without a session already loaded."
 msgstr "Вы не можете добавить дорожку без загруженной сессии."
 
-#: ardour_ui.cc:1854
+#: ardour_ui.cc:1756
 msgid "could not create %1 new mixed track"
 msgid_plural "could not create %1 new mixed tracks"
 msgstr[0] "Не удалось создать %1 новую смешанную дорожку"
 msgstr[1] "Не удалось создать %1 новых смешанных дорожки"
 msgstr[2] "Не удалось создать %1 новых смешанных дорожек"
 
-#: ardour_ui.cc:1860 ardour_ui.cc:1921
+#: ardour_ui.cc:1762 ardour_ui.cc:1823
 msgid ""
 "There are insufficient ports available\n"
 "to create a new track or bus.\n"
@@ -1154,25 +1201,25 @@ msgstr ""
 "Вам необходимо сохранить %1 и \n"
 "перезапустить программу с большим количеством портов."
 
-#: ardour_ui.cc:1895
+#: ardour_ui.cc:1797
 msgid "You cannot add a track or bus without a session already loaded."
 msgstr "Вы не можете добавить дорожку или шину без открытой сессии."
 
-#: ardour_ui.cc:1904
+#: ardour_ui.cc:1806
 msgid "could not create %1 new audio track"
 msgid_plural "could not create %1 new audio tracks"
 msgstr[0] "Не удалось создать %1 новую звуковую дорожку"
 msgstr[1] "Не удалось создать %2 новых звуковых дорожки"
 msgstr[2] "Не удалось создать %2 новых звуковых дорожек"
 
-#: ardour_ui.cc:1913
+#: ardour_ui.cc:1815
 msgid "could not create %1 new audio bus"
 msgid_plural "could not create %1 new audio busses"
 msgstr[0] "Не удалось создать %1 новую звуковую шину"
 msgstr[1] "Не удалось создать %1 новых звуковых шины"
 msgstr[2] "Не удалось создать %1 новых звуковых шин"
 
-#: ardour_ui.cc:2066
+#: ardour_ui.cc:1968
 msgid ""
 "Please create one or more tracks before trying to record.\n"
 "You can do this with the \"Add Track or Bus\" option in the Session menu."
@@ -1181,36 +1228,20 @@ msgstr ""
 "как пытаться что-либо записать.\n"
 "Используйте меню «Сессия > Добавить дорожку/шину»."
 
-#: ardour_ui.cc:2444
+#: ardour_ui.cc:2359
 #, c-format
 msgid "Copied %<PRId64> of %<PRId64>"
 msgstr "Скопировано %<PRId64> из %<PRId64>"
 
-#: ardour_ui.cc:2498 save_as_dialog.cc:33
+#: ardour_ui.cc:2413 save_as_dialog.cc:33
 msgid "Save As"
 msgstr "Сохранить как"
 
-#: ardour_ui.cc:2526
+#: ardour_ui.cc:2441
 msgid "Save As failed: %1"
 msgstr "Не удалось сохранить под другим именем: %1"
 
-#: ardour_ui.cc:2548
-msgid "Save as..."
-msgstr "Сохранить как..."
-
-#: ardour_ui.cc:2549 ardour_ui.cc:2628
-msgid "New session name"
-msgstr "Новое название сессии"
-
-#: ardour_ui.cc:2551
-msgid "Take Snapshot"
-msgstr "Создать снимок"
-
-#: ardour_ui.cc:2552
-msgid "Name of new snapshot"
-msgstr "Название нового снимка"
-
-#: ardour_ui.cc:2577
+#: ardour_ui.cc:2463
 msgid ""
 "To ensure compatibility with various systems\n"
 "snapshot names may not contain a '%1' character"
@@ -1218,23 +1249,35 @@ msgstr ""
 "Для обеспечения совместимости с различными системами\n"
 "названия снимков не могут содержать символ '%1'."
 
-#: ardour_ui.cc:2589
+#: ardour_ui.cc:2477
 msgid "Confirm Snapshot Overwrite"
 msgstr "Подтвердите перезапись снимка"
 
-#: ardour_ui.cc:2590
-msgid "A snapshot already exists with that name.  Do you want to overwrite it?"
-msgstr "Снимок с таким названием уже есть. Перезаписать его?"
+#: ardour_ui.cc:2478
+msgid "A snapshot already exists with that name. Do you want to overwrite it?"
+msgstr "Снимок с таким названием уже существует. Перезаписать его?"
 
-#: ardour_ui.cc:2593 utils_videotl.cc:74
-msgid "Overwrite"
-msgstr "Перезаписать"
+#: ardour_ui.cc:2503
+msgid "Save as..."
+msgstr "Сохранить как..."
+
+#: ardour_ui.cc:2504 ardour_ui.cc:2555
+msgid "New session name"
+msgstr "Новое название сессии"
 
-#: ardour_ui.cc:2627
+#: ardour_ui.cc:2506
+msgid "Take Snapshot"
+msgstr "Создать снимок"
+
+#: ardour_ui.cc:2507
+msgid "Name of new snapshot"
+msgstr "Название нового снимка"
+
+#: ardour_ui.cc:2554
 msgid "Rename Session"
 msgstr "Переименовать сессию"
 
-#: ardour_ui.cc:2642 ardour_ui.cc:3056 ardour_ui.cc:3094
+#: ardour_ui.cc:2569 ardour_ui.cc:3049 ardour_ui.cc:3087
 msgid ""
 "To ensure compatibility with various systems\n"
 "session names may not contain a '%1' character"
@@ -1242,12 +1285,12 @@ msgstr ""
 "Для обеспечения совместимости с различными системами\n"
 "названия сессий не могут содержать символ '%1'."
 
-#: ardour_ui.cc:2650
+#: ardour_ui.cc:2577
 msgid ""
 "That name is already in use by another directory/folder. Please try again."
 msgstr "Папка с таким названием уже есть. Укажите другое."
 
-#: ardour_ui.cc:2659
+#: ardour_ui.cc:2586
 msgid ""
 "Renaming this session failed.\n"
 "Things could be seriously messed up at this point"
@@ -1255,19 +1298,27 @@ msgstr ""
 "Не удалось переименовать эту сессию.\n"
 "Всё может быть очень, очень плохо."
 
-#: ardour_ui.cc:2774
+#: ardour_ui.cc:2702 route_ui.cc:1871
+msgid "Confirm Template Overwrite"
+msgstr "Подтвердите перезапись шаблона"
+
+#: ardour_ui.cc:2703 route_ui.cc:1872
+msgid "A template already exists with that name. Do you want to overwrite it?"
+msgstr "Шаблон с таким названием уже существует. Перезаписать его?"
+
+#: ardour_ui.cc:2727
 msgid "Save Template"
 msgstr "Сохранить шаблон"
 
-#: ardour_ui.cc:2775
+#: ardour_ui.cc:2728
 msgid "Name for template:"
 msgstr "Название шаблона:"
 
-#: ardour_ui.cc:2776
+#: ardour_ui.cc:2729
 msgid "-template"
 msgstr "-шаблон"
 
-#: ardour_ui.cc:2813
+#: ardour_ui.cc:2766
 msgid ""
 "This session\n"
 "%1\n"
@@ -1277,35 +1328,39 @@ msgstr ""
 "%1\n"
 "уже существует. Открыть её?"
 
-#: ardour_ui.cc:2823
+#: ardour_ui.cc:2776
 msgid "Open Existing Session"
 msgstr "Открыть существующую сессю"
 
-#: ardour_ui.cc:3084
+#: ardour_ui.cc:3077
 msgid "There is no existing session at \"%1\""
 msgstr "По адресу \"%1\" не существующей сессии"
 
-#: ardour_ui.cc:3176
+#: ardour_ui.cc:3171
 msgid "Please wait while %1 loads your session"
 msgstr "Дождитесь завершения загрузки сессии в %1"
 
-#: ardour_ui.cc:3191
+#: ardour_ui.cc:3186
 msgid "Port Registration Error"
 msgstr "Ошибка регистрации порта"
 
-#: ardour_ui.cc:3192
+#: ardour_ui.cc:3187
 msgid "Click the Close button to try again."
 msgstr "Щелкните кнопку «Закрыть» для возврата к предыдущему диалогу."
 
-#: ardour_ui.cc:3213
-msgid "Session \"%1 (snapshot %2)\" did not load successfully"
-msgstr "Не удалось загрузить сессию \"%1 (снимок %2)\""
+#: ardour_ui.cc:3206
+msgid "Session \"%1 (snapshot %2)\" did not load successfully: %3"
+msgstr "Не удалось успешно загрузить сеанс \"%1 (снимок %2)\": %3"
 
-#: ardour_ui.cc:3219
+#: ardour_ui.cc:3212 ardour_ui.cc:3233 ardour_ui.cc:3330 ardour_ui.cc:3339
 msgid "Loading Error"
 msgstr "Ошибка при загрузке"
 
-#: ardour_ui.cc:3241
+#: ardour_ui.cc:3227
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "Не удалось загрузить сессию \"%1 (снимок %2)\""
+
+#: ardour_ui.cc:3255
 msgid ""
 "This session has been opened in read-only mode.\n"
 "\n"
@@ -1315,24 +1370,59 @@ msgstr ""
 "\n"
 "Вы не сможете записывать или сохранять."
 
-#: ardour_ui.cc:3246
+#: ardour_ui.cc:3260
 msgid "Read-only Session"
 msgstr "Сессия в режиме чтения"
 
-#: ardour_ui.cc:3312
+#: ardour_ui.cc:3329
+msgid "Could not create session in \"%1\": %2"
+msgstr "Не удалось создать сессию в \"%1\": %2"
+
+#: ardour_ui.cc:3338
 msgid "Could not create session in \"%1\""
 msgstr "Не удалось создать сессию «%1»"
 
-#: ardour_ui.cc:3461
+#: ardour_ui.cc:3378
+msgid ""
+"<b>Just ask and wait for an answer.\n"
+"It may take from minutes to hours.</b>"
+msgstr ""
+"<b>Просто спросите и терпеливо подождите ответа.\n"
+"Это может занять от нескольких минут до пары часов.</b>"
+
+#: ardour_ui.cc:3380
+msgid "About the Chat"
+msgstr "О чате"
+
+#: ardour_ui.cc:3381
+msgid ""
+"When you're inside the chat just ask your question and wait for an answer. "
+"The chat is occupied by real people with real lives so many of them are "
+"passively online and might not read your question before minutes or hours "
+"later.\n"
+"So please be patient and wait for an answer.\n"
+"\n"
+"You should just leave the chat window open and check back regularly until "
+"someone has answered your question."
+msgstr ""
+"Попав в чат, задайте свой вопрос и подождите ответа. Большинство участников "
+"чата — такие же люди, у которых есть свои дела. Многие увидят ваше сообщение "
+"лишь по прошествии некоторого времени.\n"
+"Поэтому запаситесь, пожалуйста, терпением и подождите ответа.\n"
+"\n"
+"Оставьте окно чата открытым и периодически заглядывайте туда, чтобы узнать, "
+"не ответил ли вам кто."
+
+#: ardour_ui.cc:3500
 msgid "No files were ready for clean-up"
 msgstr "Нет готовых к удалению звуковых файлов"
 
-#: ardour_ui.cc:3465 ardour_ui.cc:3475 ardour_ui.cc:3608 ardour_ui.cc:3615
-#: ardour_ui_ed.cc:103
+#: ardour_ui.cc:3504 ardour_ui.cc:3514 ardour_ui.cc:3647 ardour_ui.cc:3654
+#: ardour_ui_ed.cc:104
 msgid "Clean-up"
 msgstr "Очистить"
 
-#: ardour_ui.cc:3466
+#: ardour_ui.cc:3505
 msgid ""
 "If this seems suprising, \n"
 "check for any existing snapshots.\n"
@@ -1344,19 +1434,19 @@ msgstr ""
 "Они могут включать области, которым\n"
 "нужны неиспользуемые файлы."
 
-#: ardour_ui.cc:3525
+#: ardour_ui.cc:3564
 msgid "kilo"
 msgstr "Кило"
 
-#: ardour_ui.cc:3528
+#: ardour_ui.cc:3567
 msgid "mega"
 msgstr "Мега"
 
-#: ardour_ui.cc:3531
+#: ardour_ui.cc:3570
 msgid "giga"
 msgstr "Гига"
 
-#: ardour_ui.cc:3536
+#: ardour_ui.cc:3575
 msgid ""
 "The following file was deleted from %2,\n"
 "releasing %3 %4bytes of disk space"
@@ -1376,7 +1466,7 @@ msgstr[2] ""
 "освободив при этом %3 %4байт\n"
 "дискового пространства."
 
-#: ardour_ui.cc:3543
+#: ardour_ui.cc:3582
 msgid ""
 "The following file was not in use and \n"
 "has been moved to: %2\n"
@@ -1423,11 +1513,11 @@ msgstr[2] ""
 "\n"
 "дополнительно освободит %3 %4байт дискового пространства.\n"
 
-#: ardour_ui.cc:3603
+#: ardour_ui.cc:3642
 msgid "Are you sure you want to clean-up?"
 msgstr "Вы уверены, что хотите выполнить очистку?"
 
-#: ardour_ui.cc:3610
+#: ardour_ui.cc:3649
 msgid ""
 "Clean-up is a destructive operation.\n"
 "ALL undo/redo information will be lost if you clean-up.\n"
@@ -1438,39 +1528,39 @@ msgstr ""
 "неиспользуемые звуковые файлы\n"
 "будут перемещены в «мертвую» зону."
 
-#: ardour_ui.cc:3618
+#: ardour_ui.cc:3657
 msgid "CleanupDialog"
 msgstr "Очистка"
 
-#: ardour_ui.cc:3648
+#: ardour_ui.cc:3687
 msgid "Cleaned Files"
 msgstr "Очищенные файлы"
 
-#: ardour_ui.cc:3665
+#: ardour_ui.cc:3704
 msgid "deleted file"
 msgstr "Удалён файл"
 
-#: ardour_ui.cc:3803
+#: ardour_ui.cc:3897
 msgid "Video-Server was not launched by %1. The request to stop it is ignored."
 msgstr "Видеосервер не был запущен %1. Запрос его остановки игнорируется."
 
-#: ardour_ui.cc:3807
+#: ardour_ui.cc:3901
 msgid "Stop Video-Server"
 msgstr "Остановить видеосервер"
 
-#: ardour_ui.cc:3808
+#: ardour_ui.cc:3902
 msgid "Do you really want to stop the Video Server?"
 msgstr "Вы действительно хотите остановить видеосервер?"
 
-#: ardour_ui.cc:3811
+#: ardour_ui.cc:3905
 msgid "Yes, Stop It"
 msgstr "Да, остановить"
 
-#: ardour_ui.cc:3837
+#: ardour_ui.cc:3931
 msgid "The Video Server is already started."
 msgstr "Видеосервер уже запущен."
 
-#: ardour_ui.cc:3839
+#: ardour_ui.cc:3933
 msgid ""
 "An external Video Server is configured and can be reached. Not starting a "
 "new instance."
@@ -1478,7 +1568,7 @@ msgstr ""
 "Внешний видеосервер настроен и может быть доступен, не начиная новый "
 "экземпляр."
 
-#: ardour_ui.cc:3847 ardour_ui.cc:3952
+#: ardour_ui.cc:3941 ardour_ui.cc:4046
 msgid ""
 "Could not connect to the Video Server. Start it or configure its access URL "
 "in Preferences."
@@ -1486,39 +1576,47 @@ msgstr ""
 "Не удалось соединиться с видеосервером. Запустите его, либо укажите URL "
 "доступа к нему в диалоге параметров программы."
 
-#: ardour_ui.cc:3877
+#: ardour_ui.cc:3971
 msgid "Specified docroot is not an existing directory."
 msgstr "Указан DOC-корень не существующего каталога."
 
-#: ardour_ui.cc:3883 ardour_ui.cc:3889
+#: ardour_ui.cc:3977 ardour_ui.cc:3983
 msgid "Given Video Server is not an executable file."
 msgstr "Данный видеосервер не является исполняемым файлом."
 
-#: ardour_ui.cc:3923
+#: ardour_ui.cc:4017
 msgid "Cannot launch the video-server"
 msgstr "Не удалось запустить видеосервер"
 
-#: ardour_ui.cc:3933
+#: ardour_ui.cc:4027
 msgid "Video-server was started but does not respond to requests..."
 msgstr "Видеосервер запущен, но не откликается."
 
-#: ardour_ui.cc:3978 editor_audio_import.cc:644
+#: ardour_ui.cc:4072 editor_audio_import.cc:644
 msgid "could not open %1"
 msgstr "Не удалось открыть %1"
 
-#: ardour_ui.cc:3982
+#: ardour_ui.cc:4076
 msgid "no video-file selected"
 msgstr "Не выбран видеофайл"
 
-#: ardour_ui.cc:4174
+#: ardour_ui.cc:4172
+msgid "No LTC detected, video will not be aligned."
+msgstr ""
+
+#: ardour_ui.cc:4178
+msgid "Align video-start to %1 [samples]"
+msgstr ""
+
+#: ardour_ui.cc:4312
 msgid "xrun"
 msgstr ""
 
-#: ardour_ui.cc:4183
+#: ardour_ui.cc:4321
 msgid "Recording was stopped because your system could not keep up."
 msgstr "Запись остановлена из-за недостаточного быстродействия системы"
 
-#: ardour_ui.cc:4212
+#: ardour_ui.cc:4350
 msgid ""
 "The disk system on your computer\n"
 "was not able to keep up with %1.\n"
@@ -1532,23 +1630,23 @@ msgstr ""
 "В частности ей не удалось записать данные на диск\n"
 "достаточно быстро для фиксации захваченных данных.\n"
 
-#: ardour_ui.cc:4285
+#: ardour_ui.cc:4423
 msgid "Scanning for plugins"
 msgstr "Сканирование плагинов"
 
-#: ardour_ui.cc:4287
+#: ardour_ui.cc:4425
 msgid "Cancel plugin scan"
 msgstr "Отменить сканирование плагинов"
 
-#: ardour_ui.cc:4296
+#: ardour_ui.cc:4434
 msgid "Stop Timeout"
 msgstr "Тайм-аут остановки"
 
-#: ardour_ui.cc:4303
+#: ardour_ui.cc:4441
 msgid "Scan Timeout"
 msgstr "Тайм-аут сканирования"
 
-#: ardour_ui.cc:4347
+#: ardour_ui.cc:4485
 msgid ""
 "The disk system on your computer\n"
 "was not able to keep up with %1.\n"
@@ -1562,11 +1660,11 @@ msgstr ""
 "В частности ей не удалось прочитать данные\n"
 "с диска достаточно быстро для воспроизведения.\n"
 
-#: ardour_ui.cc:4387
+#: ardour_ui.cc:4525
 msgid "Crash Recovery"
 msgstr "Восстановление данных"
 
-#: ardour_ui.cc:4388
+#: ardour_ui.cc:4526
 msgid ""
 "This session appears to have been in the\n"
 "middle of recording when %1 or\n"
@@ -1582,19 +1680,19 @@ msgstr ""
 "%1 может восстановить записанные данные,\n"
 "либо проигнорировать их. Примите решение.\n"
 
-#: ardour_ui.cc:4400
+#: ardour_ui.cc:4538
 msgid "Ignore crash data"
 msgstr "Проигнорировать"
 
-#: ardour_ui.cc:4401
+#: ardour_ui.cc:4539
 msgid "Recover from crash"
 msgstr "Восстановить данные"
 
-#: ardour_ui.cc:4421
+#: ardour_ui.cc:4559
 msgid "Sample Rate Mismatch"
 msgstr "Несовпадение частот сэмплирования"
 
-#: ardour_ui.cc:4422
+#: ardour_ui.cc:4560
 msgid ""
 "This session was created with a sample rate of %1 Hz, but\n"
 "%2 is currently running at %3 Hz.  If you load this session,\n"
@@ -1606,23 +1704,15 @@ msgstr ""
 "Если вы загрузите эту сессию, звуковые данные могут быть\n"
 "воспроизведены с некорректной частотой сэмплирования.\n"
 
-#: ardour_ui.cc:4431
+#: ardour_ui.cc:4569
 msgid "Do not load session"
 msgstr "Не загружать сессию"
 
-#: ardour_ui.cc:4432
+#: ardour_ui.cc:4570
 msgid "Load session anyway"
 msgstr "Все равно загрузить"
 
-#: ardour_ui.cc:4459
-msgid "Could not disconnect from Audio/MIDI engine"
-msgstr "Не удалось отсоединиться от аудио/MIDI-подсистемы."
-
-#: ardour_ui.cc:4476 ardour_ui.cc:4479
-msgid "Could not reconnect to the Audio/MIDI engine"
-msgstr "Не удалось повторно соединиться с аудио/MIDI-подсистемой."
-
-#: ardour_ui.cc:4763
+#: ardour_ui.cc:4862
 msgid ""
 "%4This is a session from an older version of %3%5\n"
 "\n"
@@ -1648,38 +1738,38 @@ msgstr ""
 "\n"
 "Отныне, используйте 2-х версии со старыми сессиями %3"
 
-#: ardour_ui.cc:4872
+#: ardour_ui.cc:4979
 msgid "This is a free/demo copy of %1. It has just switched to silent mode."
 msgstr ""
 "Демонстрационная версия %1 только что переключилась в беззвучный режим."
 
-#: ardour_ui.cc:4878
+#: ardour_ui.cc:4985
 msgid "%1 is now silent"
 msgstr "%1 переключился в беззвучный режим"
 
-#: ardour_ui.cc:4880
+#: ardour_ui.cc:4987
 msgid ""
 "Please consider paying for a copy of %1 - you can pay whatever you want."
 msgstr ""
 "Возможно, вы хотите заплатить за копию %1 — цену вы можете установить сами."
 
-#: ardour_ui.cc:4881
+#: ardour_ui.cc:4988
 msgid "Better yet become a subscriber - subscriptions start at US$1 per month."
 msgstr "Вы также можете выбрать подписку (от US$1 в месяц)."
 
-#: ardour_ui.cc:4882
+#: ardour_ui.cc:4989
 msgid "Pay for a copy (via the web)"
 msgstr "Заплатить один раз"
 
-#: ardour_ui.cc:4883
+#: ardour_ui.cc:4990
 msgid "Become a subscriber (via the web)"
 msgstr "Стать подписчиком"
 
-#: ardour_ui.cc:4902
+#: ardour_ui.cc:5009
 msgid "Remain silent"
 msgstr "Оставить беззвучным"
 
-#: ardour_ui.cc:4904
+#: ardour_ui.cc:5011
 msgid "Give me more time"
 msgstr "Дайте ещё поработать"
 
@@ -1736,8 +1826,8 @@ msgid "Return to last playback start when stopped"
 msgstr "Вернуться к точке начала воспроизведения"
 
 #: ardour_ui2.cc:137
-msgid "Playhead follows Range Selections and Edits"
-msgstr "Указатель воспроизведения следует за выделением областей и правкам"
+msgid "Playhead follows range selections and edits"
+msgstr ""
 
 #: ardour_ui2.cc:138
 msgid "Be sensible about input monitoring"
@@ -1747,7 +1837,7 @@ msgstr "Будьте разумны насчёт входного монитор
 msgid "Enable/Disable audio click"
 msgstr "Включить или выключить метроном"
 
-#: ardour_ui2.cc:140 monitor_section.cc:117
+#: ardour_ui2.cc:140 monitor_section.cc:127
 msgid ""
 "When active, something is soloed.\n"
 "Click to de-solo everything"
@@ -1757,11 +1847,9 @@ msgstr ""
 
 #: ardour_ui2.cc:141
 msgid ""
-"When active, auditioning is taking place\n"
+"When active, auditioning is taking place.\n"
 "Click to stop the audition"
 msgstr ""
-"Включено, если выполняется прослушивание.\n"
-"Щёлкните, чтобы прекратить его."
 
 #: ardour_ui2.cc:142
 msgid "When active, there is a feedback loop."
@@ -1813,441 +1901,468 @@ msgstr "[ПРЕДУПРЕЖДЕНИЕ]:"
 msgid "[INFO]: "
 msgstr "[СПРАВКА]:"
 
-#: ardour_ui2.cc:255 ardour_ui_ed.cc:408
+#: ardour_ui2.cc:255 ardour_ui_ed.cc:430
 msgid "Auto Return"
 msgstr "Автовозврат"
 
-#: ardour_ui2.cc:257 ardour_ui_ed.cc:411
+#: ardour_ui2.cc:257 ardour_ui_ed.cc:433
 msgid "Follow Edits"
 msgstr "Следовать правкам"
 
-#: ardour_ui2.cc:716 rc_option_editor.cc:2786
+#: ardour_ui2.cc:704 rc_option_editor.cc:2895
 msgid "GUI"
 msgstr "Интерфейс"
 
-#: ardour_ui2.cc:733 rc_option_editor.cc:1778 rc_option_editor.cc:1796
-#: rc_option_editor.cc:1799 rc_option_editor.cc:1801 rc_option_editor.cc:1803
-#: rc_option_editor.cc:1811 rc_option_editor.cc:1819 rc_option_editor.cc:1821
-#: rc_option_editor.cc:1829 rc_option_editor.cc:1836 rc_option_editor.cc:1845
-#: rc_option_editor.cc:1847 rc_option_editor.cc:1849 rc_option_editor.cc:1857
-#: rc_option_editor.cc:1859 rc_option_editor.cc:1868
-#: session_option_editor.cc:321 session_option_editor.cc:323
-#: session_option_editor.cc:344 session_option_editor.cc:346
-#: session_option_editor.cc:348 session_option_editor.cc:355
-#: session_option_editor.cc:362 session_option_editor.cc:366
+#: ardour_ui2.cc:721 rc_option_editor.cc:1734 rc_option_editor.cc:1752
+#: rc_option_editor.cc:1755 rc_option_editor.cc:1757 rc_option_editor.cc:1759
+#: rc_option_editor.cc:1767 rc_option_editor.cc:1769 rc_option_editor.cc:1777
+#: rc_option_editor.cc:1785 rc_option_editor.cc:1792 rc_option_editor.cc:1801
+#: rc_option_editor.cc:1803 rc_option_editor.cc:1805 rc_option_editor.cc:1813
+#: rc_option_editor.cc:1815 rc_option_editor.cc:1824
+#: session_option_editor.cc:342 session_option_editor.cc:344
+#: session_option_editor.cc:365 session_option_editor.cc:367
+#: session_option_editor.cc:369 session_option_editor.cc:376
+#: session_option_editor.cc:383 session_option_editor.cc:387
 msgid "Misc"
 msgstr "Прочее"
 
-#: ardour_ui_dependents.cc:76
+#: ardour_ui_dependents.cc:77
 msgid "Setup Editor"
 msgstr "Настройка редактора"
 
-#: ardour_ui_dependents.cc:78
+#: ardour_ui_dependents.cc:79
 msgid "Setup Mixer"
 msgstr "Настройка микшера"
 
-#: ardour_ui_dependents.cc:84
+#: ardour_ui_dependents.cc:85
 msgid "Reload Session History"
 msgstr "Повторная загрузка истории сессий"
 
-#: ardour_ui_dialogs.cc:250
+#: ardour_ui_dialogs.cc:251
 msgid "Don't close"
 msgstr "Не закрывать"
 
-#: ardour_ui_dialogs.cc:251
+#: ardour_ui_dialogs.cc:252
 msgid "Just close"
 msgstr "Просто закрыть"
 
-#: ardour_ui_dialogs.cc:252
+#: ardour_ui_dialogs.cc:253
 msgid "Save and close"
 msgstr "Сохранить и закрыть"
 
-#: ardour_ui_dialogs.cc:362
+#: ardour_ui_dialogs.cc:363
 msgid "This screen is not tall enough to display the mixer window"
 msgstr "Экран недостаточно высок, чтобы показать окно микшера"
 
-#: ardour_ui_ed.cc:102
+#: ardour_ui_ed.cc:103
 msgid "Session"
 msgstr "Сессия"
 
-#: ardour_ui_ed.cc:105 editor_actions.cc:138 editor_regions.cc:116
-#: port_group.cc:458 session_option_editor.cc:82 session_option_editor.cc:89
+#: ardour_ui_ed.cc:106 editor_actions.cc:139 editor_regions.cc:119
+#: port_group.cc:468 session_option_editor.cc:82 session_option_editor.cc:89
 msgid "Sync"
 msgstr "Синхронизация"
 
-#: ardour_ui_ed.cc:106
+#: ardour_ui_ed.cc:107
 msgid "Options"
 msgstr "Параметры"
 
-#: ardour_ui_ed.cc:107
+#: ardour_ui_ed.cc:108
 msgid "Window"
 msgstr "Окна"
 
-#: ardour_ui_ed.cc:108
+#: ardour_ui_ed.cc:109
 msgid "Help"
 msgstr "Справка"
 
-#: ardour_ui_ed.cc:109
+#: ardour_ui_ed.cc:110
 msgid "Misc. Shortcuts"
 msgstr "Прочие действия"
 
-#: ardour_ui_ed.cc:110
+#: ardour_ui_ed.cc:111
 msgid "Audio File Format"
 msgstr "Формат звуковых файлов"
 
-#: ardour_ui_ed.cc:111
+#: ardour_ui_ed.cc:112
 msgid "File Type"
 msgstr "Тип файла"
 
-#: ardour_ui_ed.cc:112 export_format_dialog.cc:67
+#: ardour_ui_ed.cc:113 export_format_dialog.cc:67
 msgid "Sample Format"
 msgstr "Формат сэмпла"
 
-#: ardour_ui_ed.cc:113 rc_option_editor.cc:2719 rc_option_editor.cc:2731
+#: ardour_ui_ed.cc:114 rc_option_editor.cc:2705 rc_option_editor.cc:2717
 msgid "Control Surfaces"
 msgstr "Устройства управления"
 
-#: ardour_ui_ed.cc:114 rc_option_editor.cc:2395 rc_option_editor.cc:2738
+#: ardour_ui_ed.cc:115 rc_option_editor.cc:2375 rc_option_editor.cc:2723
+#: rc_option_editor.cc:2725 rc_option_editor.cc:2735 rc_option_editor.cc:2742
+#: rc_option_editor.cc:2750 rc_option_editor.cc:2762 rc_option_editor.cc:2767
+#: rc_option_editor.cc:2769 rc_option_editor.cc:2774 rc_option_editor.cc:2781
+#: rc_option_editor.cc:2786 rc_option_editor.cc:2795 rc_option_editor.cc:2799
+#: rc_option_editor.cc:2808 rc_option_editor.cc:2816 rc_option_editor.cc:2820
+#: rc_option_editor.cc:2825 rc_option_editor.cc:2832 rc_option_editor.cc:2833
 msgid "Plugins"
 msgstr "Плагины"
 
-#: ardour_ui_ed.cc:115 rc_option_editor.cc:2853
+#: ardour_ui_ed.cc:116 rc_option_editor.cc:2969
 msgid "Metering"
 msgstr "Индикаторы"
 
-#: ardour_ui_ed.cc:116
+#: ardour_ui_ed.cc:117
 msgid "Fall Off Rate"
 msgstr "Частота спада"
 
-#: ardour_ui_ed.cc:117
+#: ardour_ui_ed.cc:118
 msgid "Hold Time"
 msgstr "Время задержки"
 
-#: ardour_ui_ed.cc:118
+#: ardour_ui_ed.cc:119
 msgid "Denormal Handling"
 msgstr "Обработка отклонений"
 
-#: ardour_ui_ed.cc:122 route_time_axis.cc:1689
+#: ardour_ui_ed.cc:123 route_time_axis.cc:1694
 msgid "New..."
 msgstr "Создать..."
 
-#: ardour_ui_ed.cc:124
+#: ardour_ui_ed.cc:125
 msgid "Open..."
 msgstr "Открыть..."
 
-#: ardour_ui_ed.cc:125
+#: ardour_ui_ed.cc:126
 msgid "Recent..."
 msgstr "Недавние сессии..."
 
-#: ardour_ui_ed.cc:126 panner_editor.cc:29 playlist_selector.cc:64
+#: ardour_ui_ed.cc:127 panner_editor.cc:29 playlist_selector.cc:64
 msgid "Close"
 msgstr "Закрыть"
 
-#: ardour_ui_ed.cc:129
+#: ardour_ui_ed.cc:130
 msgid "Add Track or Bus..."
 msgstr "Добавить дорожку или шину..."
 
-#: ardour_ui_ed.cc:134
+#: ardour_ui_ed.cc:135
+msgid "Duplicate Tracks/Busses..."
+msgstr "Создать копии дорожек и шин..."
+
+#: ardour_ui_ed.cc:141
+msgid "Cancel Solo"
+msgstr ""
+
+#: ardour_ui_ed.cc:146
 msgid "Open Video"
 msgstr "Добавить видео"
 
-#: ardour_ui_ed.cc:137
+#: ardour_ui_ed.cc:149
 msgid "Remove Video"
 msgstr "Удалить видео"
 
-#: ardour_ui_ed.cc:140
-msgid "Export To Video File"
-msgstr "Видеофайл"
+#: ardour_ui_ed.cc:152
+msgid "Export to Video File"
+msgstr "Экспортировать в видеофайл"
 
-#: ardour_ui_ed.cc:144
+#: ardour_ui_ed.cc:156
 msgid "Snapshot (& keep working on current version) ..."
 msgstr "Сделать снимок и работать с текущей версией..."
 
-#: ardour_ui_ed.cc:148
+#: ardour_ui_ed.cc:160
 msgid "Snapshot (& switch to new version) ..."
 msgstr "Сделать снимок и перейти к новой версии..."
 
-#: ardour_ui_ed.cc:152
+#: ardour_ui_ed.cc:164
 msgid "Save As..."
 msgstr "Сохранить как..."
 
-#: ardour_ui_ed.cc:156 editor_actions.cc:1783 editor_markers.cc:896
-#: editor_snapshots.cc:124 mixer_strip.cc:1564 route_time_axis.cc:1685
+#: ardour_ui_ed.cc:168 editor_actions.cc:1790 editor_markers.cc:903
+#: editor_snapshots.cc:136 mixer_strip.cc:1578 route_time_axis.cc:1690
 msgid "Rename..."
 msgstr "Переименовать..."
 
-#: ardour_ui_ed.cc:160
+#: ardour_ui_ed.cc:172
 msgid "Save Template..."
 msgstr "Сохранить шаблон..."
 
-#: ardour_ui_ed.cc:163
+#: ardour_ui_ed.cc:175
 msgid "Metadata"
 msgstr "Метаданные"
 
-#: ardour_ui_ed.cc:166
+#: ardour_ui_ed.cc:178
 msgid "Edit Metadata..."
 msgstr "Изменить метаданные..."
 
-#: ardour_ui_ed.cc:169
+#: ardour_ui_ed.cc:181
 msgid "Import Metadata..."
 msgstr "Импортировать метаданные..."
 
-#: ardour_ui_ed.cc:172
-msgid "Export To Audio File(s)..."
-msgstr "В звуковые файлы..."
+#: ardour_ui_ed.cc:184
+msgid "Export to Audio File(s)..."
+msgstr "Экспортировать в звуковые файлы..."
 
-#: ardour_ui_ed.cc:175
+#: ardour_ui_ed.cc:187
 msgid "Stem export..."
 msgstr "Каждую дорожку в свой файл..."
 
-#: ardour_ui_ed.cc:178 editor_export_audio.cc:65
-#: export_channel_selector.cc:190 export_channel_selector.cc:576
-#: export_dialog.cc:129 export_video_dialog.cc:80
+#: ardour_ui_ed.cc:190 editor_export_audio.cc:66 export_channel_selector.cc:190
+#: export_channel_selector.cc:576 export_dialog.cc:129
+#: export_video_dialog.cc:80
 msgid "Export"
 msgstr "Экспортировать"
 
-#: ardour_ui_ed.cc:181
+#: ardour_ui_ed.cc:193
 msgid "Clean-up Unused Sources..."
 msgstr "Очистить неиспользуемые источники..."
 
-#: ardour_ui_ed.cc:185
-msgid "Flush Wastebasket"
+#: ardour_ui_ed.cc:197
+msgid "Reset Peak Files"
+msgstr ""
+
+#: ardour_ui_ed.cc:201
+msgid "Flush Wastebasket"
 msgstr "Очистить корзину"
 
-#: ardour_ui_ed.cc:192
+#: ardour_ui_ed.cc:208
 msgid "Quit"
 msgstr "Выход"
 
-#: ardour_ui_ed.cc:193 automation_time_axis.cc:543 editor_actions.cc:654
-#: editor_markers.cc:895 location_ui.cc:57 plugin_selector.cc:86
-#: route_time_axis.cc:865
+#: ardour_ui_ed.cc:209 automation_time_axis.cc:543 editor_actions.cc:661
+#: editor_markers.cc:902 location_ui.cc:59 plugin_selector.cc:97
+#: route_time_axis.cc:866
 msgid "Hide"
 msgstr "Скрыть"
 
-#: ardour_ui_ed.cc:197
+#: ardour_ui_ed.cc:213
 msgid "Maximise Editor Space"
 msgstr "Редактор на полный экран"
 
-#: ardour_ui_ed.cc:198
+#: ardour_ui_ed.cc:214
 msgid "Maximise Mixer Space"
 msgstr "Развернуть окно микшера"
 
-#: ardour_ui_ed.cc:199
+#: ardour_ui_ed.cc:215
 msgid "Show Toolbars"
 msgstr "Показывать панели"
 
-#: ardour_ui_ed.cc:203
+#: ardour_ui_ed.cc:218
+msgid "Toggle Mixer List"
+msgstr ""
+
+#: ardour_ui_ed.cc:221
+msgid "Toggle Monitor Section Visibility"
+msgstr "Переключить видимость секции мониторинга"
+
+#: ardour_ui_ed.cc:225
 msgid "Show more UI preferences"
 msgstr "Показать больше предустановок UI"
 
-#: ardour_ui_ed.cc:205 mixer_ui.cc:1945 mixer_ui.cc:1951
+#: ardour_ui_ed.cc:227 mixer_ui.cc:2112 mixer_ui.cc:2118
 msgid "Window|Mixer"
 msgstr "Микшер"
 
-#: ardour_ui_ed.cc:206
+#: ardour_ui_ed.cc:228
 msgid "Toggle Editor+Mixer"
 msgstr "Редактор или микшер на переднем плане"
 
-#: ardour_ui_ed.cc:207 meterbridge.cc:217 meterbridge.cc:223
+#: ardour_ui_ed.cc:229 meterbridge.cc:216 meterbridge.cc:222
 msgid "Window|Meterbridge"
 msgstr "Панель индикаторов"
 
-#: ardour_ui_ed.cc:209
+#: ardour_ui_ed.cc:231
 msgid "Reattach All Tearoffs"
 msgstr "Заново прикрепить разрывы"
 
-#: ardour_ui_ed.cc:211 midi_tracer.cc:45
+#: ardour_ui_ed.cc:233 midi_tracer.cc:45
 msgid "MIDI Tracer"
 msgstr "Журнал MIDI-событий"
 
-#: ardour_ui_ed.cc:213
+#: ardour_ui_ed.cc:235
 msgid "Chat"
 msgstr "Пообщаться"
 
-#: ardour_ui_ed.cc:215
+#: ardour_ui_ed.cc:237
 msgid "Help|Manual"
 msgstr "Справка"
 
-#: ardour_ui_ed.cc:216
-msgid "Reference"
-msgstr "Справка в Интернете"
+#: ardour_ui_ed.cc:238
+msgid "Manual|Reference"
+msgstr ""
 
-#: ardour_ui_ed.cc:217
-msgid "Report A Bug"
+#: ardour_ui_ed.cc:239
+msgid "Report a Bug"
 msgstr "Сообщить об ошибке"
 
-#: ardour_ui_ed.cc:218
+#: ardour_ui_ed.cc:240
 msgid "Cheat Sheet"
 msgstr "Шпаргалка"
 
-#: ardour_ui_ed.cc:219
+#: ardour_ui_ed.cc:241
 msgid "Ardour Website"
 msgstr "Сайт Ardour"
 
-#: ardour_ui_ed.cc:220
+#: ardour_ui_ed.cc:242
 msgid "Ardour Development"
 msgstr "Разработка Ardour"
 
-#: ardour_ui_ed.cc:221
+#: ardour_ui_ed.cc:243
 msgid "User Forums"
 msgstr "Форумы для пользователей"
 
-#: ardour_ui_ed.cc:222
-msgid "How to report a bug"
+#: ardour_ui_ed.cc:244
+msgid "How to Report a Bug"
 msgstr "Как сообщить об ошибке"
 
-#: ardour_ui_ed.cc:224 plugin_ui.cc:419
+#: ardour_ui_ed.cc:246 plugin_ui.cc:419
 msgid "Save"
 msgstr "Сохранить"
 
-#: ardour_ui_ed.cc:232 rc_option_editor.cc:1879 rc_option_editor.cc:1890
-#: rc_option_editor.cc:1901 rc_option_editor.cc:1912 rc_option_editor.cc:1921
-#: rc_option_editor.cc:1934 rc_option_editor.cc:1947 rc_option_editor.cc:1956
-#: rc_option_editor.cc:1966 rc_option_editor.cc:1968 rc_option_editor.cc:1977
-#: rc_option_editor.cc:1993 rc_option_editor.cc:2014 rc_option_editor.cc:2032
-#: rc_option_editor.cc:2034 rc_option_editor.cc:2050 rc_option_editor.cc:2053
-#: rc_option_editor.cc:2055 rc_option_editor.cc:2072 rc_option_editor.cc:2083
+#: ardour_ui_ed.cc:254 rc_option_editor.cc:1835 rc_option_editor.cc:1846
+#: rc_option_editor.cc:1857 rc_option_editor.cc:1868 rc_option_editor.cc:1877
+#: rc_option_editor.cc:1890 rc_option_editor.cc:1903 rc_option_editor.cc:1912
+#: rc_option_editor.cc:1922 rc_option_editor.cc:1939 rc_option_editor.cc:1941
+#: rc_option_editor.cc:1950 rc_option_editor.cc:1966 rc_option_editor.cc:1987
+#: rc_option_editor.cc:2005 rc_option_editor.cc:2007 rc_option_editor.cc:2024
+#: rc_option_editor.cc:2027 rc_option_editor.cc:2029 rc_option_editor.cc:2046
+#: rc_option_editor.cc:2057
 msgid "Transport"
 msgstr "Транспорт"
 
-#: ardour_ui_ed.cc:238
+#: ardour_ui_ed.cc:260 engine_dialog.cc:88
 msgid "Stop"
 msgstr "Стоп"
 
-#: ardour_ui_ed.cc:241
+#: ardour_ui_ed.cc:263
 msgid "Roll"
 msgstr "Перевернуть"
 
-#: ardour_ui_ed.cc:245 ardour_ui_ed.cc:248
+#: ardour_ui_ed.cc:267 ardour_ui_ed.cc:270
 msgid "Start/Stop"
 msgstr "Старт/Стоп"
 
-#: ardour_ui_ed.cc:251
+#: ardour_ui_ed.cc:273
 msgid "Start/Continue/Stop"
 msgstr "Старт/Продолжить/Стоп"
 
-#: ardour_ui_ed.cc:254
+#: ardour_ui_ed.cc:276
 msgid "Stop and Forget Capture"
 msgstr "Остановиться и забыть захват"
 
-#: ardour_ui_ed.cc:264
-msgid "Transition To Roll"
-msgstr "В обычном направлении"
+#: ardour_ui_ed.cc:286
+msgid "Transition to Roll"
+msgstr ""
 
-#: ardour_ui_ed.cc:268
-msgid "Transition To Reverse"
-msgstr "В обратном направлении"
+#: ardour_ui_ed.cc:290
+msgid "Transition to Reverse"
+msgstr ""
 
-#: ardour_ui_ed.cc:272
+#: ardour_ui_ed.cc:294
 msgid "Play Loop Range"
 msgstr "Воспроизвести петлю"
 
-#: ardour_ui_ed.cc:275
+#: ardour_ui_ed.cc:297
 msgid "Play Selection"
 msgstr "Воспроизводить выделение"
 
-#: ardour_ui_ed.cc:278
+#: ardour_ui_ed.cc:300
 msgid "Play Selection w/Preroll"
 msgstr "Играть выбранный w/Preroll"
 
-#: ardour_ui_ed.cc:282
+#: ardour_ui_ed.cc:304
 msgid "Enable Record"
 msgstr "Разрешить запись"
 
-#: ardour_ui_ed.cc:285 ardour_ui_ed.cc:289
+#: ardour_ui_ed.cc:307 ardour_ui_ed.cc:311
 msgid "Start Recording"
 msgstr "Начать запись"
 
-#: ardour_ui_ed.cc:293
+#: ardour_ui_ed.cc:315
 msgid "Rewind"
 msgstr "Перемотать назад"
 
-#: ardour_ui_ed.cc:296
+#: ardour_ui_ed.cc:318
 msgid "Rewind (Slow)"
 msgstr "Перемотать назад (медленно)"
 
-#: ardour_ui_ed.cc:299
+#: ardour_ui_ed.cc:321
 msgid "Rewind (Fast)"
 msgstr "Перемотать назад (быстро)"
 
-#: ardour_ui_ed.cc:302
+#: ardour_ui_ed.cc:324
 msgid "Forward"
 msgstr "Перемотать вперёд"
 
-#: ardour_ui_ed.cc:305
+#: ardour_ui_ed.cc:327
 msgid "Forward (Slow)"
 msgstr "Перемотать вперёд (медленно)"
 
-#: ardour_ui_ed.cc:308
+#: ardour_ui_ed.cc:330
 msgid "Forward (Fast)"
 msgstr "Перемотать вперёд (быстро)"
 
-#: ardour_ui_ed.cc:311
+#: ardour_ui_ed.cc:333
 msgid "Go to Zero"
 msgstr "К нулевой отметке"
 
-#: ardour_ui_ed.cc:314 ardour_ui_ed.cc:317
+#: ardour_ui_ed.cc:336 ardour_ui_ed.cc:339
 msgid "Go to Start"
 msgstr "К началу"
 
-#: ardour_ui_ed.cc:320
+#: ardour_ui_ed.cc:342
 msgid "Go to End"
 msgstr "В конец"
 
-#: ardour_ui_ed.cc:323
+#: ardour_ui_ed.cc:345
 msgid "Go to Wall Clock"
 msgstr "К  текущему времени"
 
-#: ardour_ui_ed.cc:328 ardour_ui_ed.cc:331
+#: ardour_ui_ed.cc:350 ardour_ui_ed.cc:353
 msgid "Numpad Decimal"
 msgstr "Десятичный разделитель на цифровой клавиатуре"
 
-#: ardour_ui_ed.cc:334
+#: ardour_ui_ed.cc:356
 msgid "Numpad 0"
 msgstr "Numpad 0"
 
-#: ardour_ui_ed.cc:337
+#: ardour_ui_ed.cc:359
 msgid "Numpad 1"
 msgstr "Numpad 1"
 
-#: ardour_ui_ed.cc:340
+#: ardour_ui_ed.cc:362
 msgid "Numpad 2"
 msgstr "Numpad 2"
 
-#: ardour_ui_ed.cc:343
+#: ardour_ui_ed.cc:365
 msgid "Numpad 3"
 msgstr "Numpad 3"
 
-#: ardour_ui_ed.cc:346
+#: ardour_ui_ed.cc:368
 msgid "Numpad 4"
 msgstr "Numpad 3"
 
-#: ardour_ui_ed.cc:349
+#: ardour_ui_ed.cc:371
 msgid "Numpad 5"
 msgstr "Numpad 5"
 
-#: ardour_ui_ed.cc:352
+#: ardour_ui_ed.cc:374
 msgid "Numpad 6"
 msgstr "Numpad 6"
 
-#: ardour_ui_ed.cc:355
+#: ardour_ui_ed.cc:377
 msgid "Numpad 7"
 msgstr "Numpad 7"
 
-#: ardour_ui_ed.cc:358
+#: ardour_ui_ed.cc:380
 msgid "Numpad 8"
 msgstr "Numpad 8"
 
-#: ardour_ui_ed.cc:361
+#: ardour_ui_ed.cc:383
 msgid "Numpad 9"
 msgstr "Numpad 9"
 
-#: ardour_ui_ed.cc:365
+#: ardour_ui_ed.cc:387
 msgid "Focus On Clock"
 msgstr "Изменить время вручную"
 
-#: ardour_ui_ed.cc:369 ardour_ui_ed.cc:378 audio_clock.cc:2114 editor.cc:259
-#: editor_actions.cc:578 editor_actions.cc:587 export_timespan_selector.cc:88
+#: ardour_ui_ed.cc:391 ardour_ui_ed.cc:400 audio_clock.cc:2116 editor.cc:261
+#: editor_actions.cc:585 editor_actions.cc:594 export_timespan_selector.cc:85
 #: session_option_editor.cc:41 session_option_editor.cc:61
 #: session_option_editor.cc:80 session_option_editor.cc:96
 #: session_option_editor.cc:109 session_option_editor.cc:122
@@ -2255,129 +2370,133 @@ msgstr "Изменить время вручную"
 msgid "Timecode"
 msgstr "Тайм-код"
 
-#: ardour_ui_ed.cc:371 ardour_ui_ed.cc:380 editor_actions.cc:576
+#: ardour_ui_ed.cc:393 ardour_ui_ed.cc:402 editor_actions.cc:583
 msgid "Bars & Beats"
 msgstr "Такты и доли"
 
-#: ardour_ui_ed.cc:373 ardour_ui_ed.cc:382
+#: ardour_ui_ed.cc:395 ardour_ui_ed.cc:404
 msgid "Minutes & Seconds"
 msgstr "Минуты и секунды"
 
-#: ardour_ui_ed.cc:375 ardour_ui_ed.cc:384 audio_clock.cc:2118 editor.cc:260
-#: editor_actions.cc:577
+#: ardour_ui_ed.cc:397 ardour_ui_ed.cc:406 audio_clock.cc:2120 editor.cc:262
+#: editor_actions.cc:584
 msgid "Samples"
 msgstr "Сэмплы"
 
-#: ardour_ui_ed.cc:387
+#: ardour_ui_ed.cc:409
 msgid "Punch In"
 msgstr "Начало врезки"
 
-#: ardour_ui_ed.cc:388 mixer_strip.cc:1881 mixer_strip.cc:2069 route_ui.cc:164
+#: ardour_ui_ed.cc:410 mixer_strip.cc:1901 mixer_strip.cc:2089 route_ui.cc:175
 #: time_info_box.cc:116
 msgid "In"
 msgstr "Вход"
 
-#: ardour_ui_ed.cc:391
+#: ardour_ui_ed.cc:413
 msgid "Punch Out"
 msgstr "Конец врезки"
 
-#: ardour_ui_ed.cc:392 mixer_strip.cc:1893 time_info_box.cc:117
+#: ardour_ui_ed.cc:414 mixer_strip.cc:1913 time_info_box.cc:117
 msgid "Out"
 msgstr "Выход"
 
-#: ardour_ui_ed.cc:395
+#: ardour_ui_ed.cc:417
 msgid "Punch In/Out"
 msgstr "Врезка"
 
-#: ardour_ui_ed.cc:396
+#: ardour_ui_ed.cc:418
 msgid "In/Out"
 msgstr "Ð’Ñ…/Ð’Ñ‹Ñ…"
 
-#: ardour_ui_ed.cc:399 rc_option_editor.cc:1845
+#: ardour_ui_ed.cc:421 rc_option_editor.cc:1801
 msgid "Click"
 msgstr "Метроном"
 
-#: ardour_ui_ed.cc:402
+#: ardour_ui_ed.cc:424
 msgid "Auto Input"
 msgstr "Автовход"
 
-#: ardour_ui_ed.cc:405
+#: ardour_ui_ed.cc:427
 msgid "Auto Play"
 msgstr "Автовоспр."
 
-#: ardour_ui_ed.cc:416
+#: ardour_ui_ed.cc:438
 msgid "Sync Startup to Video"
 msgstr "Синхронизировать начало с видео"
 
-#: ardour_ui_ed.cc:418
+#: ardour_ui_ed.cc:440
 msgid "Time Master"
 msgstr "Ведущий времени"
 
-#: ardour_ui_ed.cc:420
+#: ardour_ui_ed.cc:442
 msgid "Use External Positional Sync Source"
 msgstr ""
 
-#: ardour_ui_ed.cc:425
+#: ardour_ui_ed.cc:447
 msgid "Toggle Record Enable Track %1"
 msgstr "Переключить записываемость дорожки %1"
 
-#: ardour_ui_ed.cc:432
+#: ardour_ui_ed.cc:454
 msgid "Percentage"
 msgstr "Проценты"
 
-#: ardour_ui_ed.cc:433 shuttle_control.cc:187
+#: ardour_ui_ed.cc:455 shuttle_control.cc:188
 msgid "Semitones"
 msgstr "Полутона"
 
-#: ardour_ui_ed.cc:437
+#: ardour_ui_ed.cc:459
 msgid "Send MTC"
 msgstr "Передавать MTC"
 
-#: ardour_ui_ed.cc:439
+#: ardour_ui_ed.cc:461
 msgid "Send MMC"
 msgstr "Передавать MMC"
 
-#: ardour_ui_ed.cc:441
+#: ardour_ui_ed.cc:463
 msgid "Use MMC"
 msgstr "Использовать MMC"
 
-#: ardour_ui_ed.cc:443 rc_option_editor.cc:2571
+#: ardour_ui_ed.cc:465 rc_option_editor.cc:2594
 msgid "Send MIDI Clock"
 msgstr "Отправлять MIDI Clock"
 
-#: ardour_ui_ed.cc:445
+#: ardour_ui_ed.cc:467
 msgid "Send MIDI Feedback"
 msgstr "Отправлять MIDI Feedback"
 
-#: ardour_ui_ed.cc:451
+#: ardour_ui_ed.cc:473
 msgid "Panic"
 msgstr "Паника"
 
-#: ardour_ui_ed.cc:542
+#: ardour_ui_ed.cc:567
 msgid "Wall Clock"
 msgstr "Текущее время"
 
-#: ardour_ui_ed.cc:544
+#: ardour_ui_ed.cc:569
 msgid "Disk Space"
 msgstr "Диск. пространство"
 
-#: ardour_ui_ed.cc:545
+#: ardour_ui_ed.cc:570
 msgid "DSP"
 msgstr "DSP"
 
-#: ardour_ui_ed.cc:546
+#: ardour_ui_ed.cc:571
 msgid "X-run"
 msgstr ""
 
-#: ardour_ui_ed.cc:547
+#: ardour_ui_ed.cc:572
+msgid "Active Peak-file Work"
+msgstr ""
+
+#: ardour_ui_ed.cc:573
 msgid "Buffers"
 msgstr "Буферы"
 
-#: ardour_ui_ed.cc:549
+#: ardour_ui_ed.cc:575
 msgid "Timecode Format"
 msgstr "Формат тайм-кода"
 
-#: ardour_ui_ed.cc:550
+#: ardour_ui_ed.cc:576
 msgid "File Format"
 msgstr "Формат файлов"
 
@@ -2393,133 +2512,133 @@ msgstr ""
 msgid "Internal"
 msgstr "Внутр. синхронизация"
 
-#: ardour_ui_options.cc:503
+#: ardour_ui_options.cc:509
 msgid "Enable/Disable external positional sync"
 msgstr "Включить или выключить внешнюю синхронизацию позиционирования"
 
-#: ardour_ui_options.cc:505
+#: ardour_ui_options.cc:511
 msgid "Sync to JACK is not possible: video pull up/down is set"
 msgstr ""
 "Синхронизация с JACK не возможна: установлена растяжка видео вверх/вниз"
 
-#: audio_clock.cc:1052 audio_clock.cc:1071
+#: audio_clock.cc:1051 audio_clock.cc:1070
 msgid "--pending--"
 msgstr "--в ожидании--"
 
-#: audio_clock.cc:1123
+#: audio_clock.cc:1122
 msgid "SR"
 msgstr "SR"
 
-#: audio_clock.cc:1129 audio_clock.cc:1133
+#: audio_clock.cc:1128 audio_clock.cc:1132
 msgid "Pull"
 msgstr "Подтягивание"
 
-#: audio_clock.cc:1131
+#: audio_clock.cc:1130
 #, c-format
 msgid "%+.4f%%"
 msgstr "%+.4f%%"
 
-#: audio_clock.cc:1287 editor.cc:261 editor_actions.cc:139
-#: editor_actions.cc:570
+#: audio_clock.cc:1286 editor.cc:263 editor_actions.cc:140
+#: editor_actions.cc:577
 msgid "Tempo"
 msgstr "Темп"
 
-#: audio_clock.cc:1291 editor.cc:262 editor_actions.cc:571
+#: audio_clock.cc:1290 editor.cc:264 editor_actions.cc:578
 msgid "Meter"
 msgstr "Размер"
 
-#: audio_clock.cc:1869 audio_streamview.cc:116 editor_actions.cc:1101
+#: audio_clock.cc:1871 audio_streamview.cc:116 editor_actions.cc:1108
 #: session_metadata_dialog.cc:452 session_metadata_dialog.cc:500
 #: session_metadata_dialog.cc:556 session_metadata_dialog.cc:845
-#: streamview.cc:470
+#: streamview.cc:469
 msgid "programming error: %1"
 msgstr "Ошибка в программе: %1"
 
-#: audio_clock.cc:2002 audio_clock.cc:2030
+#: audio_clock.cc:2004 audio_clock.cc:2032
 msgid "programming error: %1 %2"
 msgstr "Ошибка в программе: %1 %2"
 
-#: audio_clock.cc:2116 editor.cc:258 export_timespan_selector.cc:98
+#: audio_clock.cc:2118 editor.cc:260 export_timespan_selector.cc:95
 msgid "Bars:Beats"
 msgstr "Такты : Доли"
 
-#: audio_clock.cc:2117 export_timespan_selector.cc:93
+#: audio_clock.cc:2119 export_timespan_selector.cc:90
 msgid "Minutes:Seconds"
 msgstr "Минуты : Секунды"
 
-#: audio_clock.cc:2122
-msgid "Set From Playhead"
-msgstr "По указателю воспроизведения"
+#: audio_clock.cc:2124
+msgid "Set from Playhead"
+msgstr ""
 
-#: audio_clock.cc:2123
+#: audio_clock.cc:2125
 msgid "Locate to This Time"
 msgstr "Перейти к этой позиции"
 
-#: audio_clock.cc:2126
+#: audio_clock.cc:2128
 msgid "Copy to clipboard"
 msgstr "Скопировать в буфер обмена"
 
-#: audio_region_editor.cc:64 control_point_dialog.cc:49 rhythm_ferret.cc:124
+#: audio_region_editor.cc:65 control_point_dialog.cc:49 rhythm_ferret.cc:124
 #: rhythm_ferret.cc:129 rhythm_ferret.cc:134
 msgid "dB"
 msgstr "Дб"
 
-#: audio_region_editor.cc:67
+#: audio_region_editor.cc:68
 msgid "Region gain:"
 msgstr "Усиление области:"
 
-#: audio_region_editor.cc:77 export_format_dialog.cc:43
+#: audio_region_editor.cc:78 export_format_dialog.cc:43
 msgid "dBFS"
 msgstr "dBFS"
 
-#: audio_region_editor.cc:80
+#: audio_region_editor.cc:81
 msgid "Peak amplitude:"
 msgstr "Пиковая амплитуда:"
 
-#: audio_region_editor.cc:91
+#: audio_region_editor.cc:92
 msgid "Calculating..."
 msgstr "Производится вычисление..."
 
-#: audio_region_view.cc:1254
+#: audio_region_view.cc:1371
 msgid "add gain control point"
 msgstr "Добавление точки контроля усиления"
 
-#: automation_controller.cc:287 automation_controller.cc:303
+#: automation_controller.cc:292 automation_controller.cc:308
 msgid "Select Note..."
 msgstr "Выбрать ноту..."
 
-#: automation_controller.cc:294
+#: automation_controller.cc:299
 msgid "Halve"
 msgstr "Половина"
 
-#: automation_controller.cc:297
+#: automation_controller.cc:302
 msgid "Double"
 msgstr "Двойной"
 
-#: automation_controller.cc:308
+#: automation_controller.cc:313
 msgid "Set to %1 beat"
 msgid_plural "Set to %1 beats"
 msgstr[0] "Сделать равным %1 удару"
 msgstr[1] "Сделать равным %1 ударам"
 msgstr[2] "Сделать равным %1 ударам"
 
-#: automation_line.cc:287 editor_drag.cc:4129
+#: automation_line.cc:285 editor_drag.cc:4255
 msgid "automation event move"
 msgstr "Смещение события автоматизации"
 
-#: automation_line.cc:884 region_gain_line.cc:75
+#: automation_line.cc:881 region_gain_line.cc:75
 msgid "remove control point"
 msgstr "Удаление контрольной точки"
 
-#: automation_line.cc:1008
+#: automation_line.cc:1006
 msgid "Ignoring illegal points on AutomationLine \"%1\""
 msgstr "Игнорирование некорреткных точек на линии автоматизации \"%1\""
 
-#: automation_region_view.cc:190 automation_time_axis.cc:644
+#: automation_region_view.cc:193 automation_time_axis.cc:647
 msgid "add automation event"
 msgstr "Новое событие автоматизации"
 
-#: automation_streamview.cc:95
+#: automation_streamview.cc:94
 msgid "unable to display automation region for control without list"
 msgstr "без списка невозможно показать область автоматизации для управления"
 
@@ -2532,33 +2651,33 @@ msgid "hide track"
 msgstr "Скрыть дорожку"
 
 #: automation_time_axis.cc:308 automation_time_axis.cc:360
-#: automation_time_axis.cc:554 gain_meter.cc:222 generic_pluginui.cc:524
-#: generic_pluginui.cc:818 panner_ui.cc:149
+#: automation_time_axis.cc:554 gain_meter.cc:222 generic_pluginui.cc:526
+#: generic_pluginui.cc:820 panner_ui.cc:151
 msgid "Automation|Manual"
 msgstr "Вручную"
 
 #: automation_time_axis.cc:310 automation_time_axis.cc:371
-#: automation_time_axis.cc:559 editor.cc:1916 editor.cc:1994
-#: editor_actions.cc:122 editor_actions.cc:1932 gain_meter.cc:225
-#: generic_pluginui.cc:100 generic_pluginui.cc:527 generic_pluginui.cc:820
-#: midi_time_axis.cc:1607 midi_time_axis.cc:1610 midi_time_axis.cc:1613
-#: panner_ui.cc:152
+#: automation_time_axis.cc:559 editor.cc:1928 editor.cc:2006
+#: editor_actions.cc:123 editor_actions.cc:1939 gain_meter.cc:225
+#: generic_pluginui.cc:102 generic_pluginui.cc:529 generic_pluginui.cc:822
+#: midi_time_axis.cc:1614 midi_time_axis.cc:1617 midi_time_axis.cc:1620
+#: panner_ui.cc:154
 msgid "Play"
 msgstr "Проигрывание"
 
 #: automation_time_axis.cc:312 automation_time_axis.cc:382
-#: automation_time_axis.cc:564 gain_meter.cc:228 generic_pluginui.cc:102
-#: generic_pluginui.cc:530 generic_pluginui.cc:822 panner_ui.cc:155
+#: automation_time_axis.cc:564 gain_meter.cc:228 generic_pluginui.cc:104
+#: generic_pluginui.cc:532 generic_pluginui.cc:824 panner_ui.cc:157
 msgid "Write"
 msgstr "Запись"
 
 #: automation_time_axis.cc:314 automation_time_axis.cc:393
-#: automation_time_axis.cc:569 gain_meter.cc:231 generic_pluginui.cc:104
-#: generic_pluginui.cc:533 generic_pluginui.cc:824 panner_ui.cc:158
+#: automation_time_axis.cc:569 gain_meter.cc:231 generic_pluginui.cc:106
+#: generic_pluginui.cc:535 generic_pluginui.cc:826 panner_ui.cc:160
 msgid "Touch"
 msgstr "Касание"
 
-#: automation_time_axis.cc:404 generic_pluginui.cc:536 meter_patterns.cc:116
+#: automation_time_axis.cc:404 generic_pluginui.cc:538 meter_patterns.cc:118
 msgid "???"
 msgstr "???"
 
@@ -2566,7 +2685,8 @@ msgstr "???"
 msgid "clear automation"
 msgstr "Очистить автоматизацию"
 
-#: automation_time_axis.cc:545
+#: automation_time_axis.cc:545 rc_option_editor.cc:2770
+#: rc_option_editor.cc:2775 rc_option_editor.cc:2821 rc_option_editor.cc:2826
 msgid "Clear"
 msgstr "Очистить"
 
@@ -2582,7 +2702,7 @@ msgstr "Дискретный"
 msgid "Linear"
 msgstr "Линейная"
 
-#: automation_time_axis.cc:604 rhythm_ferret.cc:109 shuttle_control.cc:206
+#: automation_time_axis.cc:604 rhythm_ferret.cc:109 shuttle_control.cc:207
 msgid "Mode"
 msgstr "Режим"
 
@@ -2598,31 +2718,31 @@ msgstr "Изменение пакета"
 msgid "Direction:"
 msgstr "Направление:"
 
-#: bundle_manager.cc:206 bundle_manager.cc:210 engine_dialog.cc:881
-#: mixer_strip.cc:165 mixer_strip.cc:379 mixer_strip.cc:2302
-#: rc_option_editor.cc:2828
+#: bundle_manager.cc:206 bundle_manager.cc:210 engine_dialog.cc:949
+#: mixer_strip.cc:168 mixer_strip.cc:382 mixer_strip.cc:2347
+#: rc_option_editor.cc:2944
 msgid "Input"
 msgstr "Вход"
 
 #: bundle_manager.cc:207 bundle_manager.cc:212 bundle_manager.cc:246
-#: engine_dialog.cc:883 mixer_strip.cc:169 mixer_strip.cc:383
-#: mixer_strip.cc:2305 monitor_section.cc:329 monitor_section.cc:333
-#: rc_option_editor.cc:2832
+#: engine_dialog.cc:951 mixer_strip.cc:172 mixer_strip.cc:386
+#: mixer_strip.cc:2350 monitor_section.cc:295 monitor_section.cc:299
+#: rc_option_editor.cc:2948
 msgid "Output"
 msgstr "Выход"
 
-#: bundle_manager.cc:265 editor.cc:1958 editor_actions.cc:94
-#: editor_actions.cc:104 rc_option_editor.cc:1539 rc_option_editor.cc:1546
+#: bundle_manager.cc:265 editor.cc:1970 editor_actions.cc:95
+#: editor_actions.cc:105 rc_option_editor.cc:2782 rc_option_editor.cc:2796
 msgid "Edit"
 msgstr "Правка"
 
-#: bundle_manager.cc:266 editor.cc:5921 editor.cc:5949 editor_actions.cc:345
-#: editor_actions.cc:346 plugin_ui.cc:420 processor_box.cc:2525
+#: bundle_manager.cc:266 editor.cc:5948 editor.cc:5978 editor_actions.cc:346
+#: editor_actions.cc:347 plugin_ui.cc:420 processor_box.cc:2832
 msgid "Delete"
 msgstr "Удалить"
 
-#: bundle_manager.cc:272 bundle_manager.cc:439 editor_route_groups.cc:97
-#: editor_routes.cc:207 midi_list_editor.cc:107 session_metadata_dialog.cc:646
+#: bundle_manager.cc:272 bundle_manager.cc:439 editor_route_groups.cc:98
+#: editor_routes.cc:208 midi_list_editor.cc:107 session_metadata_dialog.cc:646
 msgid "Name"
 msgstr "Имя"
 
@@ -2654,6 +2774,30 @@ msgstr "Контрольная точка"
 msgid "Value"
 msgstr "Значение"
 
+#: duplicate_routes_dialog.cc:35
+msgid "Duplicate Tracks & Busses"
+msgstr "Создать копии дорожек и шин"
+
+#: duplicate_routes_dialog.cc:36
+msgid "Copy playlists"
+msgstr "Скопировать списки воспроизведения"
+
+#: duplicate_routes_dialog.cc:37
+msgid "Create new (empty) playlists"
+msgstr "Создать новые (пустые) списки воспроизведения"
+
+#: duplicate_routes_dialog.cc:38
+msgid "Share playlists"
+msgstr "Использовать общие списки воспроизведения"
+
+#: duplicate_routes_dialog.cc:41
+msgid "Duplicate each track/bus this number of times:"
+msgstr "Сколько копий каждой дорожки/шины создать:"
+
+#: duplicate_routes_dialog.cc:176
+msgid "1 or more tracks/busses could not be duplicated"
+msgstr "Не удалось продублировать одну или больше дорожек/шин"
+
 #: edit_note_dialog.cc:42
 msgid "Note"
 msgstr "Нота"
@@ -2695,9 +2839,9 @@ msgstr "Сила нажатия"
 msgid "Time"
 msgstr "Время"
 
-#: edit_note_dialog.cc:98 editor_regions.cc:115
-#: export_timespan_selector.cc:378 export_timespan_selector.cc:440
-#: location_ui.cc:320 midi_list_editor.cc:115 time_info_box.cc:108
+#: edit_note_dialog.cc:98 editor_regions.cc:118 export_timespan_selector.cc:375
+#: export_timespan_selector.cc:437 location_ui.cc:322 midi_list_editor.cc:115
+#: time_info_box.cc:108
 msgid "Length"
 msgstr "Длительность"
 
@@ -2705,582 +2849,579 @@ msgstr "Длительность"
 msgid "edit note"
 msgstr "Правка ноты"
 
-#: editor.cc:148
+#: editor.cc:150
 msgid "CD Frames"
 msgstr "Выборки CD"
 
-#: editor.cc:149
+#: editor.cc:151
 msgid "TC Frames"
 msgstr "TC кадры"
 
-#: editor.cc:150
+#: editor.cc:152
 msgid "TC Seconds"
 msgstr "TC секунды"
 
-#: editor.cc:151
+#: editor.cc:153
 msgid "TC Minutes"
 msgstr "TC минуты"
 
-#: editor.cc:152
+#: editor.cc:154
 msgid "Seconds"
 msgstr "Секунды"
 
-#: editor.cc:153
+#: editor.cc:155
 msgid "Minutes"
 msgstr "Минуты"
 
-#: editor.cc:154 quantize_dialog.cc:37 quantize_dialog.cc:141
+#: editor.cc:156 quantize_dialog.cc:37 quantize_dialog.cc:141
 msgid "Beats/128"
 msgstr "Доли/128"
 
-#: editor.cc:155 quantize_dialog.cc:38 quantize_dialog.cc:143
+#: editor.cc:157 quantize_dialog.cc:38 quantize_dialog.cc:143
 msgid "Beats/64"
 msgstr "Доли/64"
 
-#: editor.cc:156 quantize_dialog.cc:39 quantize_dialog.cc:145
+#: editor.cc:158 quantize_dialog.cc:39 quantize_dialog.cc:145
 msgid "Beats/32"
 msgstr "Доли/32"
 
-#: editor.cc:157
+#: editor.cc:159
 msgid "Beats/28"
 msgstr "Доли/28"
 
-#: editor.cc:158
+#: editor.cc:160
 msgid "Beats/24"
 msgstr "Доли/24"
 
-#: editor.cc:159
+#: editor.cc:161
 msgid "Beats/20"
 msgstr "Доли/20"
 
-#: editor.cc:160 quantize_dialog.cc:40 quantize_dialog.cc:147
+#: editor.cc:162 quantize_dialog.cc:40 quantize_dialog.cc:147
 msgid "Beats/16"
 msgstr "Доли/16"
 
-#: editor.cc:161
+#: editor.cc:163
 msgid "Beats/14"
 msgstr "Доли/14"
 
-#: editor.cc:162
+#: editor.cc:164
 msgid "Beats/12"
 msgstr "Доли/12"
 
-#: editor.cc:163
+#: editor.cc:165
 msgid "Beats/10"
 msgstr "Доли/10"
 
-#: editor.cc:164 quantize_dialog.cc:41 quantize_dialog.cc:149
+#: editor.cc:166 quantize_dialog.cc:41 quantize_dialog.cc:149
 msgid "Beats/8"
 msgstr "Доли/8"
 
-#: editor.cc:165
+#: editor.cc:167
 msgid "Beats/7"
 msgstr "Доли/7"
 
-#: editor.cc:166
+#: editor.cc:168
 msgid "Beats/6"
 msgstr "Доли/6"
 
-#: editor.cc:167
+#: editor.cc:169
 msgid "Beats/5"
 msgstr "Доли/5"
 
-#: editor.cc:168 quantize_dialog.cc:42 quantize_dialog.cc:151
+#: editor.cc:170 quantize_dialog.cc:42 quantize_dialog.cc:151
 msgid "Beats/4"
 msgstr "Доли/4"
 
-#: editor.cc:169 quantize_dialog.cc:43 quantize_dialog.cc:153
+#: editor.cc:171 quantize_dialog.cc:43 quantize_dialog.cc:153
 msgid "Beats/3"
 msgstr "Доли/3"
 
-#: editor.cc:170 quantize_dialog.cc:44 quantize_dialog.cc:155
+#: editor.cc:172 quantize_dialog.cc:44 quantize_dialog.cc:155
 msgid "Beats/2"
 msgstr "Доли/2"
 
-#: editor.cc:171 quantize_dialog.cc:45 quantize_dialog.cc:157
+#: editor.cc:173 quantize_dialog.cc:45 quantize_dialog.cc:157
 msgid "Beats"
 msgstr "Доли"
 
-#: editor.cc:172
+#: editor.cc:174
 msgid "Bars"
 msgstr "Такты"
 
-#: editor.cc:173
+#: editor.cc:175
 msgid "Marks"
 msgstr "Маркеры"
 
-#: editor.cc:174
+#: editor.cc:176
 msgid "Region starts"
 msgstr "Начала областей"
 
-#: editor.cc:175
+#: editor.cc:177
 msgid "Region ends"
 msgstr "Концы областей"
 
-#: editor.cc:176
+#: editor.cc:178
 msgid "Region syncs"
 msgstr "Синхр. областей"
 
-#: editor.cc:177
+#: editor.cc:179
 msgid "Region bounds"
 msgstr "Границы областей"
 
-#: editor.cc:182 editor_actions.cc:519
+#: editor.cc:184 editor_actions.cc:526
 msgid "No Grid"
 msgstr "Без сетки"
 
-#: editor.cc:183 editor_actions.cc:520
+#: editor.cc:185 editor_actions.cc:527
 msgid "Grid"
 msgstr "По сетке"
 
-#: editor.cc:184 editor_actions.cc:521
+#: editor.cc:186 editor_actions.cc:528
 msgid "Magnetic"
 msgstr "Магнит"
 
-#: editor.cc:189 editor.cc:207 editor_actions.cc:121 editor_actions.cc:502
+#: editor.cc:191 editor.cc:209 editor_actions.cc:122 editor_actions.cc:509
 msgid "Playhead"
 msgstr "Указатель воспроизведения"
 
-#: editor.cc:190 editor_actions.cc:504
+#: editor.cc:192 editor_actions.cc:511
 msgid "Marker"
 msgstr "Маркер"
 
-#: editor.cc:191 editor.cc:208 editor_actions.cc:503
+#: editor.cc:193 editor.cc:210 editor_actions.cc:510
 msgid "Mouse"
 msgstr "Мышь"
 
-#: editor.cc:196 editor_actions.cc:511
+#: editor.cc:198 editor_actions.cc:518
 msgid "Slide"
 msgstr "Слайд"
 
-#: editor.cc:197
+#: editor.cc:199
 msgid "Splice"
 msgstr "Стыковка"
 
-#: editor.cc:198 editor_actions.cc:510
+#: editor.cc:200 editor_actions.cc:517
 msgid "Ripple"
 msgstr "Рябь"
 
-#: editor.cc:199 editor_actions.cc:1801 editor_markers.cc:898
-#: editor_rulers.cc:260 location_ui.cc:58
+#: editor.cc:201 editor_actions.cc:1808 editor_markers.cc:905
+#: editor_rulers.cc:259 location_ui.cc:60
 msgid "Lock"
 msgstr "Блок"
 
-#: editor.cc:204 mono_panner_editor.cc:42
+#: editor.cc:206 mono_panner_editor.cc:44
 msgid "Left"
 msgstr "Влево"
 
-#: editor.cc:205 mono_panner_editor.cc:47
+#: editor.cc:207 mono_panner_editor.cc:49
 msgid "Right"
 msgstr "Вправо"
 
-#: editor.cc:206
+#: editor.cc:208
 msgid "Center"
 msgstr "По центру"
 
-#: editor.cc:209 editor.cc:3248
+#: editor.cc:211
 msgid "Edit point"
 msgstr "Курсор редактора"
 
-#: editor.cc:215
+#: editor.cc:217
 msgid "Mushy"
 msgstr "Мягкое"
 
-#: editor.cc:216
+#: editor.cc:218
 msgid "Smooth"
 msgstr "Сглаживание"
 
-#: editor.cc:217
+#: editor.cc:219
 msgid "Balanced multitimbral mixture"
 msgstr "Сбалансированный многотембральный микс"
 
-#: editor.cc:218
+#: editor.cc:220
 msgid "Unpitched percussion with stable notes"
 msgstr "Перкуссионное соло без коррекции высоты тона с выделяющимися нотами"
 
-#: editor.cc:219
+#: editor.cc:221
 msgid "Crisp monophonic instrumental"
 msgstr "Чистое монофоническое инструментальное соло"
 
-#: editor.cc:220
+#: editor.cc:222
 msgid "Unpitched solo percussion"
 msgstr "Перкуссионное соло без коррекции высоты тона"
 
-#: editor.cc:221
+#: editor.cc:223
 msgid "Resample without preserving pitch"
 msgstr "Ресэмплировать, не сохраняя высоту тона"
 
-#: editor.cc:257
+#: editor.cc:259
 msgid "Mins:Secs"
 msgstr "Минуты:Секунды"
 
-#: editor.cc:263
+#: editor.cc:265
 msgid "Location Markers"
 msgstr "Маркеры позиций"
 
-#: editor.cc:264
+#: editor.cc:266
 msgid "Range Markers"
 msgstr "Маркеры выделений"
 
-#: editor.cc:265
+#: editor.cc:267
 msgid "Loop/Punch Ranges"
 msgstr "Диапазоны петель/врезок"
 
-#: editor.cc:266 editor_actions.cc:574
+#: editor.cc:268 editor_actions.cc:581
 msgid "CD Markers"
 msgstr "Маркеры CD"
 
-#: editor.cc:267
+#: editor.cc:269
 msgid "Video Timeline"
 msgstr "Видеолинейка"
 
-#: editor.cc:284
+#: editor.cc:286
 msgid "mode"
 msgstr "Режим"
 
-#: editor.cc:462 editor_actions.cc:114 editor_actions.cc:573
+#: editor.cc:465 editor_actions.cc:115 editor_actions.cc:580
 msgid "Markers"
 msgstr "Маркеры"
 
-#: editor.cc:580 rc_option_editor.cc:2413
+#: editor.cc:583 rc_option_editor.cc:2393
 msgid "Regions"
 msgstr "Области"
 
-#: editor.cc:581
+#: editor.cc:584
 msgid "Tracks & Busses"
 msgstr "Дорожки и шины"
 
-#: editor.cc:582
+#: editor.cc:585
 msgid "Snapshots"
 msgstr "Снимки"
 
-#: editor.cc:583
+#: editor.cc:586
 msgid "Track & Bus Groups"
 msgstr "Группы дорожек и шин"
 
-#: editor.cc:584
+#: editor.cc:587
 msgid "Ranges & Marks"
 msgstr "Области и маркеры"
 
-#: editor.cc:731 editor.cc:5773 rc_option_editor.cc:2090
-#: rc_option_editor.cc:2098 rc_option_editor.cc:2106 rc_option_editor.cc:2114
-#: rc_option_editor.cc:2138 rc_option_editor.cc:2150 rc_option_editor.cc:2161
-#: rc_option_editor.cc:2163 rc_option_editor.cc:2171 rc_option_editor.cc:2179
-#: rc_option_editor.cc:2199 rc_option_editor.cc:2211 rc_option_editor.cc:2213
-#: rc_option_editor.cc:2215 rc_option_editor.cc:2223 rc_option_editor.cc:2231
-#: rc_option_editor.cc:2246 rc_option_editor.cc:2250 rc_option_editor.cc:2274
+#: editor.cc:734 editor.cc:5800 rc_option_editor.cc:2061
+#: rc_option_editor.cc:2075 rc_option_editor.cc:2079 rc_option_editor.cc:2087
+#: rc_option_editor.cc:2095 rc_option_editor.cc:2104 rc_option_editor.cc:2113
+#: rc_option_editor.cc:2121 rc_option_editor.cc:2129 rc_option_editor.cc:2139
+#: rc_option_editor.cc:2141 rc_option_editor.cc:2165 rc_option_editor.cc:2177
+#: rc_option_editor.cc:2188 rc_option_editor.cc:2206 rc_option_editor.cc:2208
+#: rc_option_editor.cc:2211 rc_option_editor.cc:2220 rc_option_editor.cc:2238
+#: rc_option_editor.cc:2250 rc_option_editor.cc:2252
 msgid "Editor"
 msgstr "Редактор"
 
-#: editor.cc:1335 editor.cc:4757 editor_actions.cc:134 editor_actions.cc:1877
+#: editor.cc:1348 editor.cc:4783 editor_actions.cc:135 editor_actions.cc:1884
 msgid "Loop"
 msgstr "Петля"
 
-#: editor.cc:1341 editor.cc:4784 editor_actions.cc:135 time_info_box.cc:68
+#: editor.cc:1354 editor.cc:4810 editor_actions.cc:136 time_info_box.cc:68
 msgid "Punch"
 msgstr "Врезка"
 
-#: editor.cc:1453 rc_option_editor.cc:2132
+#: editor.cc:1466 rc_option_editor.cc:2159
 msgid "Linear (for highly correlated material)"
 msgstr "Линейно (для схожего материала)"
 
-#: editor.cc:1463 rc_option_editor.cc:2133
+#: editor.cc:1476 rc_option_editor.cc:2160
 msgid "Constant power"
 msgstr "С постоянной силой"
 
-#: editor.cc:1472 rc_option_editor.cc:2134
+#: editor.cc:1485 rc_option_editor.cc:2161
 msgid "Symmetric"
 msgstr "Симметрично"
 
-#: editor.cc:1482 rc_option_editor.cc:2135
+#: editor.cc:1495 rc_option_editor.cc:2162
 msgid "Slow"
 msgstr "Медленно"
 
-#: editor.cc:1491 rc_option_editor.cc:2136 sfdb_ui.cc:1770 sfdb_ui.cc:1880
+#: editor.cc:1504 rc_option_editor.cc:2163 sfdb_ui.cc:1767 sfdb_ui.cc:1878
 msgid "Fast"
 msgstr "Быстро"
 
-#: editor.cc:1513 editor.cc:1538
+#: editor.cc:1526 editor.cc:1551
 msgid "Deactivate"
 msgstr "Деактивировать"
 
-#: editor.cc:1515 editor.cc:1540
+#: editor.cc:1528 editor.cc:1553
 msgid "Activate"
 msgstr "Активировать"
 
-#: editor.cc:1641 editor.cc:1649 editor_ops.cc:3933
+#: editor.cc:1654 editor.cc:1662 editor_ops.cc:3855
 msgid "Freeze"
 msgstr "Заморозить"
 
-#: editor.cc:1645
+#: editor.cc:1658
 msgid "Unfreeze"
 msgstr "Разморозить"
 
-#: editor.cc:1784
+#: editor.cc:1797
 msgid "Selected Regions"
 msgstr "Выделенные области"
 
-#: editor.cc:1828 editor_markers.cc:933
+#: editor.cc:1841 editor_markers.cc:940
 msgid "Play Range"
 msgstr "Воспроизвести выделение"
 
-#: editor.cc:1829 editor_markers.cc:936
+#: editor.cc:1842 editor_markers.cc:943
 msgid "Loop Range"
 msgstr "Создать петлю из выделения"
 
-#: editor.cc:1832 editor_markers.cc:943
+#: editor.cc:1845 editor_markers.cc:950
 msgid "Zoom to Range"
 msgstr "Масштабировать в выделение"
 
-#: editor.cc:1841 editor_actions.cc:376
+#: editor.cc:1854 editor_actions.cc:383
 msgid "Move Range Start to Previous Region Boundary"
 msgstr "Переместить начало выделения к границе предыдущей области"
 
-#: editor.cc:1848 editor_actions.cc:383
+#: editor.cc:1861 editor_actions.cc:390
 msgid "Move Range Start to Next Region Boundary"
 msgstr "Переместить начало выделения к границе следующей области"
 
-#: editor.cc:1855 editor_actions.cc:390
+#: editor.cc:1868 editor_actions.cc:397
 msgid "Move Range End to Previous Region Boundary"
 msgstr "Переместить конец выделения к границе предыдущей области"
 
-#: editor.cc:1862 editor_actions.cc:397
+#: editor.cc:1875 editor_actions.cc:404
 msgid "Move Range End to Next Region Boundary"
 msgstr "Переместить конец выделения к границе следующей области"
 
-#: editor.cc:1868 editor_actions.cc:133 editor_actions.cc:332
+#: editor.cc:1881 editor_actions.cc:134 editor_actions.cc:333
 msgid "Separate"
 msgstr "Разделить"
 
-#: editor.cc:1869
+#: editor.cc:1882
 msgid "Convert to Region in Region List"
 msgstr "Преобразовать в область в списке областей"
 
-#: editor.cc:1872 editor_markers.cc:963
+#: editor.cc:1885 editor_markers.cc:970
 msgid "Select All in Range"
 msgstr "Выбрать всё в выделении"
 
-#: editor.cc:1875 editor_actions.cc:304
+#: editor.cc:1888 editor_actions.cc:305
 msgid "Set Loop from Selection"
 msgstr "Создать петлю из выделения"
 
-#: editor.cc:1876 editor_actions.cc:305
+#: editor.cc:1889 editor_actions.cc:306
 msgid "Set Punch from Selection"
 msgstr "Создать врезку из выделения"
 
-#: editor.cc:1877 editor_actions.cc:306
+#: editor.cc:1890 editor_actions.cc:307
 msgid "Set Session Start/End from Selection"
 msgstr "Задать начало и конец по выделению"
 
-#: editor.cc:1880
+#: editor.cc:1893
 msgid "Add Range Markers"
 msgstr "Добавить маркеры областей"
 
-#: editor.cc:1883
+#: editor.cc:1896
 msgid "Crop Region to Range"
 msgstr "Обрезать область по выделению"
 
-#: editor.cc:1884
-msgid "Fill Range with Region"
-msgstr "Заполнить диапазон областью"
-
-#: editor.cc:1885 editor_actions.cc:318
+#: editor.cc:1897 editor_actions.cc:319
 msgid "Duplicate Range"
 msgstr "Продублировать диапазон"
 
-#: editor.cc:1888
+#: editor.cc:1900
 msgid "Consolidate Range"
 msgstr "Объединить диапазон"
 
-#: editor.cc:1889
-msgid "Consolidate Range With Processing"
-msgstr "Объединить диапазон с обработкой"
+#: editor.cc:1901
+msgid "Consolidate Range with Processing"
+msgstr ""
 
-#: editor.cc:1890
+#: editor.cc:1902
 msgid "Bounce Range to Region List"
 msgstr "Свести диапазон в список областей"
 
-#: editor.cc:1891
-msgid "Bounce Range to Region List With Processing"
-msgstr "Свести выделение в список областей с обработкой"
+#: editor.cc:1903
+msgid "Bounce Range to Region List with Processing"
+msgstr ""
 
-#: editor.cc:1892 editor_markers.cc:946
+#: editor.cc:1904 editor_markers.cc:953
 msgid "Export Range..."
 msgstr "Экспортировать выделение…"
 
-#: editor.cc:1894
+#: editor.cc:1906
 msgid "Export Video Range..."
 msgstr "Экспортировать фрагмент видео..."
 
-#: editor.cc:1910 editor.cc:1992 editor_actions.cc:310
-msgid "Play From Edit Point"
-msgstr "Воспроизвести от курсора редактора"
+#: editor.cc:1922 editor.cc:2004 editor_actions.cc:311
+msgid "Play from Edit Point"
+msgstr "Воспроизвести от точки редактирования"
 
-#: editor.cc:1911 editor.cc:1993
-msgid "Play From Start"
-msgstr "Воспроизвести с начала"
+#: editor.cc:1923 editor.cc:2005
+msgid "Play from Start"
+msgstr "Воспроизвести от начала"
 
-#: editor.cc:1912
+#: editor.cc:1924
 msgid "Play Region"
 msgstr "Воспроизвести область"
 
-#: editor.cc:1914
+#: editor.cc:1926
 msgid "Loop Region"
 msgstr "Создать петлю из области"
 
-#: editor.cc:1924 editor.cc:2002
+#: editor.cc:1936 editor.cc:2014
 msgid "Select All in Track"
 msgstr "Выделить всё на дорожке"
 
-#: editor.cc:1925 editor.cc:2003 editor_actions.cc:194
+#: editor.cc:1937 editor.cc:2015 editor_actions.cc:195
 msgid "Select All Objects"
 msgstr "Выделить все объекты"
 
-#: editor.cc:1926 editor.cc:2004
+#: editor.cc:1938 editor.cc:2016
 msgid "Invert Selection in Track"
 msgstr "Обратить выделение на дорожке"
 
-#: editor.cc:1927 editor.cc:2005 editor_actions.cc:197
+#: editor.cc:1939 editor.cc:2017 editor_actions.cc:198
 msgid "Invert Selection"
 msgstr "Обратить выделение"
 
-#: editor.cc:1929
+#: editor.cc:1941 editor_actions.cc:200
 msgid "Set Range to Loop Range"
 msgstr "Установить диапазон по диапазону петли"
 
-#: editor.cc:1930 editor_actions.cc:200
+#: editor.cc:1942 editor_actions.cc:201
 msgid "Set Range to Punch Range"
 msgstr "Установить диапазон по диапазону врезки"
 
-#: editor.cc:1931 editor_actions.cc:201
+#: editor.cc:1943 editor_actions.cc:202
 msgid "Set Range to Selected Regions"
 msgstr ""
 
-#: editor.cc:1933 editor.cc:2007 editor_actions.cc:203 editor_actions.cc:204
+#: editor.cc:1945 editor.cc:2019 editor_actions.cc:204 editor_actions.cc:205
 msgid "Select All After Edit Point"
 msgstr "Выделить всё после курсора редактора"
 
-#: editor.cc:1934 editor.cc:2008 editor_actions.cc:205 editor_actions.cc:206
+#: editor.cc:1946 editor.cc:2020 editor_actions.cc:206 editor_actions.cc:207
 msgid "Select All Before Edit Point"
 msgstr "Выделить всё до курсора редактора"
 
-#: editor.cc:1935 editor.cc:2009
+#: editor.cc:1947 editor.cc:2021
 msgid "Select All After Playhead"
 msgstr "Выделить всё после указателя"
 
-#: editor.cc:1936 editor.cc:2010
+#: editor.cc:1948 editor.cc:2022
 msgid "Select All Before Playhead"
 msgstr "Выделить всё до указателя"
 
-#: editor.cc:1937
+#: editor.cc:1949
 msgid "Select All Between Playhead and Edit Point"
 msgstr "Выделить всё между указателем и курсором редактора"
 
-#: editor.cc:1938
+#: editor.cc:1950
 msgid "Select All Within Playhead and Edit Point"
 msgstr "Выделить всё между указателем и точкой редактирования"
 
-#: editor.cc:1939
+#: editor.cc:1951
 msgid "Select Range Between Playhead and Edit Point"
 msgstr "Создать выделение между указателем и курсором редактора"
 
-#: editor.cc:1941 editor.cc:2012 editor_actions.cc:131 editor_actions.cc:132
+#: editor.cc:1953 editor.cc:2024 editor_actions.cc:132 editor_actions.cc:133
 msgid "Select"
 msgstr "Выделить"
 
-#: editor.cc:1949 editor.cc:2020 editor_actions.cc:344 processor_box.cc:2518
+#: editor.cc:1961 editor.cc:2032 editor_actions.cc:345 processor_box.cc:2828
 msgid "Cut"
 msgstr "Вырезать"
 
-#: editor.cc:1950 editor.cc:2021 editor_actions.cc:348 processor_box.cc:2521
+#: editor.cc:1962 editor.cc:2033 editor_actions.cc:349 processor_box.cc:2830
 msgid "Copy"
 msgstr "Копировать"
 
-#: editor.cc:1951 editor.cc:2022 editor_actions.cc:349 processor_box.cc:2529
+#: editor.cc:1963 editor.cc:2034 editor_actions.cc:350 processor_box.cc:2835
 msgid "Paste"
 msgstr "Вставить"
 
-#: editor.cc:1955 editor_actions.cc:91
+#: editor.cc:1967 editor_actions.cc:92
 msgid "Align"
 msgstr "Выровнять"
 
-#: editor.cc:1956
+#: editor.cc:1968
 msgid "Align Relative"
 msgstr "Выровнять относительно"
 
-#: editor.cc:1963
+#: editor.cc:1975
 msgid "Insert Selected Region"
 msgstr "Вставить выделенную область"
 
-#: editor.cc:1964
+#: editor.cc:1976
 msgid "Insert Existing Media"
 msgstr "Вставить существующие данные"
 
-#: editor.cc:1973 editor.cc:2029
+#: editor.cc:1985 editor.cc:2041
 msgid "Nudge Entire Track Later"
 msgstr "Толкнуть всю дорожку вперёд"
 
-#: editor.cc:1974 editor.cc:2030
+#: editor.cc:1986 editor.cc:2042
 msgid "Nudge Track After Edit Point Later"
 msgstr "Толкнуть дорожку вперёд после курсора редактора"
 
-#: editor.cc:1975 editor.cc:2031
+#: editor.cc:1987 editor.cc:2043
 msgid "Nudge Entire Track Earlier"
 msgstr "Толкнуть всю дорожку назад"
 
-#: editor.cc:1976 editor.cc:2032
+#: editor.cc:1988 editor.cc:2044
 msgid "Nudge Track After Edit Point Earlier"
 msgstr "Толкнуть дорожку назад после курсора редактора"
 
-#: editor.cc:1978 editor.cc:2034
+#: editor.cc:1990 editor.cc:2046
 msgid "Nudge"
 msgstr "Толкнуть"
 
-#: editor.cc:2249
+#: editor.cc:2261
 msgid ""
 "Playhead position stored with a negative value - ignored (use zero instead)"
 msgstr ""
 "Позиция указателя воспроизведения сохранена с негативным значением и будет "
 "проигнорирована. Вместо неё будет использовано начало сеанса."
 
-#: editor.cc:3027 editor.cc:3724 editor.cc:3795 midi_channel_selector.cc:157
+#: editor.cc:3039 editor.cc:3738 editor.cc:3809 midi_channel_selector.cc:157
 #: midi_channel_selector.cc:395 midi_channel_selector.cc:431
 msgid "All"
 msgstr "Все"
 
-#: editor.cc:3227
-msgid "Smart Mode (add Range functions to Grab mode)"
-msgstr "Универсальный режим (захват + работа с диапазонами)"
+#: editor.cc:3239
+msgid "Smart Mode (add range functions to Grab Mode)"
+msgstr ""
 
-#: editor.cc:3228
+#: editor.cc:3240
 msgid "Grab Mode (select/move objects)"
 msgstr "Захват (выделение и перемещение объектов)"
 
-#: editor.cc:3229
+#: editor.cc:3241
 msgid "Cut Mode (split regions)"
 msgstr "Нарезка (разделение областей)"
 
-#: editor.cc:3230
+#: editor.cc:3242
 msgid "Range Mode (select time ranges)"
 msgstr "Диапазоны (выделение диапазонов времени)"
 
-#: editor.cc:3231
+#: editor.cc:3243
 msgid "Draw Mode (draw and edit gain/notes/automation)"
 msgstr "Рисование (рисование и правка усиления, нот и автоматизации)"
 
-#: editor.cc:3232
+#: editor.cc:3244
 msgid "Stretch Mode (time-stretch audio and midi regions, preserving pitch)"
 msgstr "Растягивание (аудио и MIDI во времени с сохранением высоты тона)"
 
-#: editor.cc:3233
+#: editor.cc:3245
 msgid "Audition Mode (listen to regions)"
 msgstr "Прослушивание (областей)"
 
-#: editor.cc:3234
+#: editor.cc:3246
 msgid "Internal Edit Mode (edit notes and automation points)"
 msgstr "Правка содержимого областей (правка нот и точек автоматизации)"
 
-#: editor.cc:3235
+#: editor.cc:3247
 msgid ""
 "Groups: click to (de)activate\n"
 "Context-click for other operations"
@@ -3288,59 +3429,63 @@ msgstr ""
 "Группы: щёлкните для (де)активации\n"
 "Щелчок другой клавишей вызывает контекстное меню"
 
-#: editor.cc:3236
+#: editor.cc:3248
 msgid "Nudge Region/Selection Later"
 msgstr "Толкнуть область или выделение вперёд"
 
-#: editor.cc:3237
+#: editor.cc:3249
 msgid "Nudge Region/Selection Earlier"
 msgstr "Толкнуть область или выделение назад"
 
-#: editor.cc:3238 editor_actions.cc:269
+#: editor.cc:3250 editor_actions.cc:270
 msgid "Zoom In"
 msgstr "Увеличить"
 
-#: editor.cc:3239 editor_actions.cc:268
+#: editor.cc:3251 editor_actions.cc:269
 msgid "Zoom Out"
 msgstr "Уменьшить"
 
-#: editor.cc:3240
+#: editor.cc:3252
 msgid "Zoom to Time Scale"
 msgstr "Увеличить до шкалы времени"
 
-#: editor.cc:3241 editor.cc:3746 editor_actions.cc:270
+#: editor.cc:3253 editor.cc:3760 editor_actions.cc:271
 msgid "Zoom to Session"
 msgstr "Показать всё"
 
-#: editor.cc:3242
-msgid "Zoom focus"
+#: editor.cc:3254 editor_actions.cc:113 editor_actions.cc:146
+msgid "Zoom Focus"
 msgstr "Фокус при масштабировании"
 
-#: editor.cc:3243
+#: editor.cc:3255
 msgid "Expand Tracks"
 msgstr "Увеличить дорожки по высоте"
 
-#: editor.cc:3244
+#: editor.cc:3256
 msgid "Shrink Tracks"
 msgstr "Уменьшить дорожки по высоте"
 
-#: editor.cc:3245
+#: editor.cc:3257
 msgid "Number of visible tracks"
 msgstr "Количество видимых дорожек"
 
-#: editor.cc:3246
+#: editor.cc:3258
 msgid "Snap/Grid Units"
 msgstr "Единица привязки/сетки"
 
-#: editor.cc:3247
+#: editor.cc:3259
 msgid "Snap/Grid Mode"
 msgstr "Режим привязки/сетки"
 
-#: editor.cc:3249
+#: editor.cc:3260 editor_actions.cc:99
+msgid "Edit Point"
+msgstr "Точка редактирования"
+
+#: editor.cc:3261
 msgid "Edit Mode"
 msgstr "Режим редактирования"
 
-#: editor.cc:3250
+#: editor.cc:3262
 msgid ""
 "Nudge Clock\n"
 "(controls distance used to nudge regions and selections)"
@@ -3348,124 +3493,124 @@ msgstr ""
 "Сдвиг часов\n"
 "(расстояние, на которое подтолкнуть области и выделения)"
 
-#: editor.cc:3518 editor_actions.cc:320
+#: editor.cc:3530 editor_actions.cc:321
 msgid "Command|Undo"
 msgstr "Отменить"
 
-#: editor.cc:3520
+#: editor.cc:3532
 msgid "Command|Undo (%1)"
 msgstr "Отменить (%1)"
 
-#: editor.cc:3527 editor_actions.cc:322 editor_actions.cc:323
-#: editor_actions.cc:324
+#: editor.cc:3539 editor_actions.cc:323 editor_actions.cc:324
+#: editor_actions.cc:325
 msgid "Redo"
 msgstr "Вернуть"
 
-#: editor.cc:3529
+#: editor.cc:3542
 msgid "Redo (%1)"
 msgstr "Вернуть (%1)"
 
-#: editor.cc:3548 editor.cc:3572 editor_actions.cc:110 editor_actions.cc:1858
+#: editor.cc:3562 editor.cc:3586 editor_actions.cc:111 editor_actions.cc:1865
 msgid "Duplicate"
 msgstr "Продублировать"
 
-#: editor.cc:3549
+#: editor.cc:3563
 msgid "Number of duplications:"
 msgstr "Количество копий:"
 
-#: editor.cc:3723 route_group_dialog.cc:51 time_info_box.cc:67
+#: editor.cc:3737 route_group_dialog.cc:51 time_info_box.cc:67
 msgid "Selection"
 msgstr "Выделение"
 
-#: editor.cc:3726
+#: editor.cc:3740
 msgid "Fit 1 track"
 msgstr "Уместить 1 дорожку"
 
-#: editor.cc:3727
+#: editor.cc:3741
 msgid "Fit 2 tracks"
 msgstr "Уместить 2 дорожки"
 
-#: editor.cc:3728
+#: editor.cc:3742
 msgid "Fit 4 tracks"
 msgstr "Уместить 4 дорожки"
 
-#: editor.cc:3729
+#: editor.cc:3743
 msgid "Fit 8 tracks"
 msgstr "Уместить 8 дорожек"
 
-#: editor.cc:3730
+#: editor.cc:3744
 msgid "Fit 16 tracks"
 msgstr "Уместить 16 дорожек"
 
-#: editor.cc:3731
+#: editor.cc:3745
 msgid "Fit 24 tracks"
 msgstr "Уместить 24 дорожки"
 
-#: editor.cc:3732
+#: editor.cc:3746
 msgid "Fit 32 tracks"
 msgstr "Уместить 32 дорожки"
 
-#: editor.cc:3733
+#: editor.cc:3747
 msgid "Fit 48 tracks"
 msgstr "Уместить 48 дорожек"
 
-#: editor.cc:3734
+#: editor.cc:3748
 msgid "Fit All tracks"
 msgstr "Уместить все дорожки"
 
-#: editor.cc:3735
+#: editor.cc:3749
 msgid "Fit Selection"
 msgstr "Уместить выделение"
 
-#: editor.cc:3737
+#: editor.cc:3751
 msgid "Zoom to 10 ms"
 msgstr "Отмасштабировать до 10 мс"
 
-#: editor.cc:3738
+#: editor.cc:3752
 msgid "Zoom to 100 ms"
 msgstr "Отмасштабировать до 100 мс"
 
-#: editor.cc:3739
+#: editor.cc:3753
 msgid "Zoom to 1 sec"
 msgstr "Отмасштабировать до 1 сек"
 
-#: editor.cc:3740
+#: editor.cc:3754
 msgid "Zoom to 10 sec"
 msgstr "Отмасштабировать до 10 сек"
 
-#: editor.cc:3741
+#: editor.cc:3755
 msgid "Zoom to 1 min"
 msgstr "Отмасштабировать до 1 мин"
 
-#: editor.cc:3742
+#: editor.cc:3756
 msgid "Zoom to 10 min"
 msgstr "Отмасштабировать до 10 мин"
 
-#: editor.cc:3743
+#: editor.cc:3757
 msgid "Zoom to 1 hour"
 msgstr "Отмасштабировать до 1 часа"
 
-#: editor.cc:3744
+#: editor.cc:3758
 msgid "Zoom to 8 hours"
 msgstr "Отмасштабировать до 8 час"
 
-#: editor.cc:3745
+#: editor.cc:3759
 msgid "Zoom to 24 hours"
 msgstr "Отмасштабировать до 24 час"
 
-#: editor.cc:3747
+#: editor.cc:3761
 msgid "Zoom to Range/Region Selection"
 msgstr "Отмасштабировать до выбранного диапазона/области"
 
-#: editor.cc:3817
+#: editor.cc:3831
 msgid "*"
 msgstr "*"
 
-#: editor.cc:4137
+#: editor.cc:4151
 msgid "Playlist Deletion"
 msgstr "Удаление списка воспроизведения"
 
-#: editor.cc:4138
+#: editor.cc:4152
 msgid ""
 "Playlist %1 is currently unused.\n"
 "If it is kept, its audio files will not be cleaned.\n"
@@ -3475,1316 +3620,1330 @@ msgstr ""
 "Если его оставить, связанные звуковые файлы не будут подчищены.\n"
 "Если его удалить, будут подчищены и связанные звуковые файлы."
 
-#: editor.cc:4148
+#: editor.cc:4162
+msgid "Delete All Unused"
+msgstr "Удалить все неиспользуемые"
+
+#: editor.cc:4163
 msgid "Delete Playlist"
 msgstr "Удалить список"
 
-#: editor.cc:4149
+#: editor.cc:4164
 msgid "Keep Playlist"
 msgstr "Сохранить список"
 
-#: editor.cc:4150 editor_audio_import.cc:597 editor_ops.cc:6407
-#: engine_dialog.cc:2679 sfdb_freesound_mootcher.cc:69 processor_box.cc:2286
-#: processor_box.cc:2311
+#: editor.cc:4165
+msgid "Keep Remaining"
+msgstr ""
+
+#: editor.cc:4166 editor_audio_import.cc:597 editor_ops.cc:6456
+#: engine_dialog.cc:2909 sfdb_freesound_mootcher.cc:69 processor_box.cc:2596
+#: processor_box.cc:2621
 msgid "Cancel"
 msgstr "Отмена"
 
-#: editor.cc:4292
+#: editor.cc:4318
 msgid "new playlists"
 msgstr "Создать списки воспроизведения"
 
-#: editor.cc:4308
+#: editor.cc:4334
 msgid "copy playlists"
 msgstr "Скопировать списки воспроизведения"
 
-#: editor.cc:4323
+#: editor.cc:4349
 msgid "clear playlists"
 msgstr "Очистить списки воспроизведения"
 
-#: editor.cc:5068
+#: editor.cc:5095
 msgid "Please wait while %1 loads visual data."
 msgstr "Дождитесь загрузки визуальных данных в %1."
 
-#: editor.cc:5920 editor.cc:5951 editor_markers.cc:978 panner_ui.cc:410
-#: processor_box.cc:2549
+#: editor.cc:5947 editor.cc:5982 editor_markers.cc:985 panner_ui.cc:412
+#: processor_box.cc:2855
 msgid "Edit..."
 msgstr "Изменить"
 
-#: editor.cc:5953 editor_actions.cc:1953
+#: editor.cc:5988 editor_actions.cc:1844
+msgid "Transpose..."
+msgstr "Транспозиция…"
+
+#: editor.cc:5992 editor_actions.cc:1960
 msgid "Legatize"
 msgstr "Добавить легато"
 
-#: editor.cc:5955 editor_actions.cc:1952
+#: editor.cc:5998 editor_actions.cc:1959
 msgid "Quantize..."
 msgstr "Квантование..."
 
-#: editor.cc:5957 editor_actions.cc:1955
+#: editor.cc:6001 editor_actions.cc:1962
 msgid "Remove Overlap"
 msgstr "Убрать перекрытие"
 
-#: editor.cc:5959 editor_actions.cc:1954
+#: editor.cc:6007 editor_actions.cc:1961
 msgid "Transform..."
 msgstr "Преобразовать..."
 
-#: editor_actions.cc:92
+#: editor_actions.cc:93
 msgid "Autoconnect"
 msgstr "Автосоединение"
 
-#: editor_actions.cc:93
+#: editor_actions.cc:94
 msgid "Crossfades"
 msgstr "Кроссфейды"
 
-#: editor_actions.cc:95
+#: editor_actions.cc:96
 msgid "Move Selected Marker"
 msgstr "Переместить выделенный маркер"
 
-#: editor_actions.cc:96
+#: editor_actions.cc:97
 msgid "Select Range Operations"
 msgstr "Выбор диапазона циклов"
 
-#: editor_actions.cc:97
+#: editor_actions.cc:98
 msgid "Select Regions"
 msgstr "Выбор областей"
 
-#: editor_actions.cc:98
-msgid "Edit Point"
-msgstr "Точка редактирования"
-
-#: editor_actions.cc:99
+#: editor_actions.cc:100
 msgid "Fade"
 msgstr "Фейд"
 
-#: editor_actions.cc:100
+#: editor_actions.cc:101
 msgid "Latch"
 msgstr "Запирание"
 
-#: editor_actions.cc:101 editor_regions.cc:112 region_editor.cc:46
+#: editor_actions.cc:102 editor_regions.cc:115 region_editor.cc:48
 msgid "Region"
 msgstr "Область"
 
-#: editor_actions.cc:102
+#: editor_actions.cc:103
 msgid "Layering"
 msgstr "Слои"
 
-#: editor_actions.cc:103 editor_regions.cc:113 stereo_panner_editor.cc:44
+#: editor_actions.cc:104 editor_regions.cc:116 stereo_panner_editor.cc:46
 msgid "Position"
 msgstr "Положение"
 
-#: editor_actions.cc:105 gain_meter.cc:158 gain_meter.cc:827 panner_ui.cc:176
-#: panner_ui.cc:635 route_time_axis.cc:528
+#: editor_actions.cc:106 gain_meter.cc:158 gain_meter.cc:827 panner_ui.cc:178
+#: panner_ui.cc:637 route_time_axis.cc:529
 msgid "Trim"
 msgstr "Обрезать"
 
-#: editor_actions.cc:106 editor_actions.cc:126 route_group_dialog.cc:46
+#: editor_actions.cc:107 editor_actions.cc:127 route_group_dialog.cc:46
 msgid "Gain"
 msgstr "Усиление"
 
-#: editor_actions.cc:107 editor_actions.cc:572
+#: editor_actions.cc:108 editor_actions.cc:579
 msgid "Ranges"
 msgstr "Выделения"
 
-#: editor_actions.cc:108 editor_actions.cc:1854 session_option_editor.cc:135
+#: editor_actions.cc:109 editor_actions.cc:1861 session_option_editor.cc:135
 #: session_option_editor.cc:144 session_option_editor.cc:151
+#: session_option_editor.cc:158 session_option_editor.cc:165
 msgid "Fades"
 msgstr "Фейды"
 
-#: editor_actions.cc:111
+#: editor_actions.cc:112
 msgid "Link"
 msgstr "Связь"
 
-#: editor_actions.cc:112 editor_actions.cc:145
-msgid "Zoom Focus"
-msgstr "Фокус при масштабировании"
-
-#: editor_actions.cc:113
+#: editor_actions.cc:114
 msgid "Locate to Markers"
 msgstr "Перейти к маркерам"
 
-#: editor_actions.cc:115
+#: editor_actions.cc:116
 msgid "Meter falloff"
 msgstr "Спад индикатора"
 
-#: editor_actions.cc:116
+#: editor_actions.cc:117
 msgid "Meter hold"
 msgstr "Задержка индикатора"
 
-#: editor_actions.cc:117 session_option_editor.cc:321
+#: editor_actions.cc:118 session_option_editor.cc:342
 msgid "MIDI Options"
 msgstr "Параметры MIDI"
 
-#: editor_actions.cc:118
+#: editor_actions.cc:119
 msgid "Misc Options"
 msgstr "Прочие параметры"
 
-#: editor_actions.cc:119 rc_option_editor.cc:2283 route_group_dialog.cc:54
-#: session_option_editor.cc:243 session_option_editor.cc:250
+#: editor_actions.cc:120 rc_option_editor.cc:2261 route_group_dialog.cc:54
+#: session_option_editor.cc:264 session_option_editor.cc:271
 msgid "Monitoring"
 msgstr "Мониторинг"
 
-#: editor_actions.cc:120
+#: editor_actions.cc:121
 msgid "Active Mark"
 msgstr "Активный маркер"
 
-#: editor_actions.cc:123
+#: editor_actions.cc:124
 msgid "Primary Clock"
 msgstr "Основной счётчик"
 
-#: editor_actions.cc:124
+#: editor_actions.cc:125
 msgid "Pullup / Pulldown"
 msgstr "Вверх/вниз"
 
-#: editor_actions.cc:125
+#: editor_actions.cc:126
 msgid "Region operations"
 msgstr "Действия с областями"
 
-#: editor_actions.cc:127 ruler_dialog.cc:28
+#: editor_actions.cc:128 ruler_dialog.cc:28
 msgid "Rulers"
 msgstr "Линейки"
 
-#: editor_actions.cc:128
+#: editor_actions.cc:129
 msgid "Views"
 msgstr "Виды"
 
-#: editor_actions.cc:129
+#: editor_actions.cc:130
 msgid "Scroll"
 msgstr "Прокрутка"
 
-#: editor_actions.cc:130
+#: editor_actions.cc:131
 msgid "Secondary Clock"
 msgstr "Дополнительный счётчик"
 
-#: editor_actions.cc:137
+#: editor_actions.cc:138
 msgid "Subframes"
 msgstr "Подвыборки"
 
-#: editor_actions.cc:140
+#: editor_actions.cc:141
 msgid "Timecode fps"
 msgstr "Скорость (FPS) тайм-кода"
 
-#: editor_actions.cc:141 route_time_axis.cc:586
+#: editor_actions.cc:142 route_time_axis.cc:587
 msgid "Height"
 msgstr "Высота"
 
-#: editor_actions.cc:143
+#: editor_actions.cc:144
 msgid "Tools"
 msgstr "Инструменты"
 
-#: editor_actions.cc:144
+#: editor_actions.cc:145
 msgid "View"
 msgstr "Вид"
 
-#: editor_actions.cc:146
+#: editor_actions.cc:147
 msgid "Zoom"
 msgstr "Масштаб"
 
-#: editor_actions.cc:152
+#: editor_actions.cc:153
 msgid "Break drag or deselect all"
 msgstr "Прервать перетаскивания или отменить все"
 
-#: editor_actions.cc:157
+#: editor_actions.cc:158
 msgid "Session|Lock"
 msgstr "Заблокировать"
 
-#: editor_actions.cc:159
+#: editor_actions.cc:160
 msgid "Show Editor Mixer"
 msgstr "Показывать микшер редактора"
 
-#: editor_actions.cc:160
+#: editor_actions.cc:161
 msgid "Show Editor List"
 msgstr "Показывать список редактирования"
 
-#: editor_actions.cc:162
+#: editor_actions.cc:163
 msgid "Playhead to Next Region Boundary"
 msgstr "К следующей границе области"
 
-#: editor_actions.cc:163
+#: editor_actions.cc:164
 msgid "Playhead to Next Region Boundary (No Track Selection)"
 msgstr "К следующей границе области (без выделения дорожки)"
 
-#: editor_actions.cc:164
+#: editor_actions.cc:165
 msgid "Playhead to Previous Region Boundary"
 msgstr "К предыдущей границе области"
 
-#: editor_actions.cc:165
+#: editor_actions.cc:166
 msgid "Playhead to Previous Region Boundary (No Track Selection)"
 msgstr "К предыдущей границе области (без выделения дорожки)"
 
-#: editor_actions.cc:167
+#: editor_actions.cc:168
 msgid "Playhead to Next Region Start"
 msgstr "К началу следующей области"
 
-#: editor_actions.cc:168
+#: editor_actions.cc:169
 msgid "Playhead to Next Region End"
 msgstr "К концу следующей области"
 
-#: editor_actions.cc:169
+#: editor_actions.cc:170
 msgid "Playhead to Next Region Sync"
 msgstr "К следующему синхронизатору областей"
 
-#: editor_actions.cc:171
+#: editor_actions.cc:172
 msgid "Playhead to Previous Region Start"
 msgstr "К началу предыдущей области"
 
-#: editor_actions.cc:172
+#: editor_actions.cc:173
 msgid "Playhead to Previous Region End"
 msgstr "К концу предыдущей области"
 
-#: editor_actions.cc:173
+#: editor_actions.cc:174
 msgid "Playhead to Previous Region Sync"
 msgstr "К предыдущему синхронизатору областей"
 
-#: editor_actions.cc:175
+#: editor_actions.cc:176
 msgid "To Next Region Boundary"
 msgstr "К следующей границе области"
 
-#: editor_actions.cc:176
+#: editor_actions.cc:177
 msgid "To Next Region Boundary (No Track Selection)"
 msgstr "К следующей границе области (без выделения дорожки)"
 
-#: editor_actions.cc:177
+#: editor_actions.cc:178
 msgid "To Previous Region Boundary"
 msgstr "К предыдущей границе области"
 
-#: editor_actions.cc:178
+#: editor_actions.cc:179
 msgid "To Previous Region Boundary (No Track Selection)"
 msgstr "К предыдущей границе области (без выделения дорожки)"
 
-#: editor_actions.cc:180
+#: editor_actions.cc:181
 msgid "To Next Region Start"
 msgstr "К началу следующей области"
 
-#: editor_actions.cc:181
+#: editor_actions.cc:182
 msgid "To Next Region End"
 msgstr "К концу следующей области"
 
-#: editor_actions.cc:182
+#: editor_actions.cc:183
 msgid "To Next Region Sync"
 msgstr "К следующему синхронизатору области"
 
-#: editor_actions.cc:184
+#: editor_actions.cc:185
 msgid "To Previous Region Start"
 msgstr "К началу предыдущей области"
 
-#: editor_actions.cc:185
+#: editor_actions.cc:186
 msgid "To Previous Region End"
 msgstr "К концу предыдущей области"
 
-#: editor_actions.cc:186
+#: editor_actions.cc:187
 msgid "To Previous Region Sync"
 msgstr "К предыдущему синхронизатору области"
 
-#: editor_actions.cc:188
+#: editor_actions.cc:189
 msgid "To Range Start"
 msgstr "К началу области"
 
-#: editor_actions.cc:189
+#: editor_actions.cc:190
 msgid "To Range End"
 msgstr "К концу области"
 
-#: editor_actions.cc:191
+#: editor_actions.cc:192
 msgid "Playhead to Range Start"
 msgstr "К началу области"
 
-#: editor_actions.cc:192
+#: editor_actions.cc:193
 msgid "Playhead to Range End"
 msgstr "К концу области"
 
-#: editor_actions.cc:195
+#: editor_actions.cc:196
 msgid "Select All Tracks"
 msgstr "Выбрать все дорожки"
 
-#: editor_actions.cc:196 export_timespan_selector.cc:61 processor_box.cc:2535
+#: editor_actions.cc:197 export_timespan_selector.cc:59 processor_box.cc:2841
 msgid "Deselect All"
 msgstr "Снять все выделения"
 
-#: editor_actions.cc:199
-msgid "Set Range in Loop Range"
-msgstr ""
-
-#: editor_actions.cc:208
+#: editor_actions.cc:209
 msgid "Select All Overlapping Edit Range"
 msgstr "Выделить всю пересекающуюся область правки"
 
-#: editor_actions.cc:209
+#: editor_actions.cc:210
 msgid "Select All Inside Edit Range"
 msgstr "Выделить всё внутри области правки"
 
-#: editor_actions.cc:211
+#: editor_actions.cc:212
 msgid "Select Edit Range"
 msgstr "Выделить область правки"
 
-#: editor_actions.cc:213
+#: editor_actions.cc:214
 msgid "Select All in Punch Range"
 msgstr "Выделить все в области врезки"
 
-#: editor_actions.cc:214
+#: editor_actions.cc:215
 msgid "Select All in Loop Range"
 msgstr "Выделить всё в закольцованной области"
 
-#: editor_actions.cc:216
+#: editor_actions.cc:217
 msgid "Select Next Track or Bus"
 msgstr "Выбрать следующую дорожку или шину"
 
-#: editor_actions.cc:217
+#: editor_actions.cc:218
 msgid "Select Previous Track or Bus"
 msgstr "Выбрать предыдущую дорожку или шину"
 
-#: editor_actions.cc:219
+#: editor_actions.cc:220
 msgid "Toggle Record Enable"
 msgstr "Переключить готовность к записи"
 
-#: editor_actions.cc:221
+#: editor_actions.cc:222
 msgid "Toggle Solo"
 msgstr "Переключить соло"
 
-#: editor_actions.cc:223
+#: editor_actions.cc:224
 msgid "Toggle Mute"
 msgstr "Переключить приглушение"
 
-#: editor_actions.cc:225
+#: editor_actions.cc:226
 msgid "Toggle Solo Isolate"
 msgstr "Переключить изолирование солирования"
 
-#: editor_actions.cc:230
+#: editor_actions.cc:231
 msgid "Save View %1"
 msgstr "Сохранить вид %1"
 
-#: editor_actions.cc:236
+#: editor_actions.cc:237
 msgid "Go to View %1"
 msgstr "Перейти к виду %1"
 
-#: editor_actions.cc:242
+#: editor_actions.cc:243
 msgid "Locate to Mark %1"
 msgstr "Перейти к маркеру %1"
 
-#: editor_actions.cc:246 editor_actions.cc:247
+#: editor_actions.cc:247 editor_actions.cc:248
 msgid "Jump to Next Mark"
 msgstr "К следующему маркеру"
 
-#: editor_actions.cc:248 editor_actions.cc:249
+#: editor_actions.cc:249 editor_actions.cc:250
 msgid "Jump to Previous Mark"
 msgstr "К предыдущему маркеру"
 
-#: editor_actions.cc:251
+#: editor_actions.cc:252
 msgid "Set Session Start from Playhead"
 msgstr ""
 
-#: editor_actions.cc:252
+#: editor_actions.cc:253
 msgid "Set Session End from Playhead"
 msgstr ""
 
-#: editor_actions.cc:254 editor_actions.cc:255
+#: editor_actions.cc:255 editor_actions.cc:256
 msgid "Add Mark from Playhead"
 msgstr "Добавить маркер по указателю"
 
-#: editor_actions.cc:257 editor_actions.cc:258
+#: editor_actions.cc:258 editor_actions.cc:259
 msgid "Remove Mark at Playhead"
 msgstr "Удалить маркер воспроизведения"
 
-#: editor_actions.cc:260
+#: editor_actions.cc:261
 msgid "Nudge Next Later"
 msgstr "Сдвиг следующего позже"
 
-#: editor_actions.cc:261
+#: editor_actions.cc:262
 msgid "Nudge Next Earlier"
 msgstr "Сдвиг следующего раньше"
 
-#: editor_actions.cc:263
+#: editor_actions.cc:264
 msgid "Nudge Playhead Forward"
 msgstr "Толкнуть указатель вперёд"
 
-#: editor_actions.cc:264
+#: editor_actions.cc:265
 msgid "Nudge Playhead Backward"
 msgstr "Толкнуть указатель назад"
 
-#: editor_actions.cc:265
-msgid "Playhead To Next Grid"
-msgstr "К следующему делению сетки"
-
 #: editor_actions.cc:266
-msgid "Playhead To Previous Grid"
-msgstr "К предыдущему делению сетки"
+msgid "Playhead to Next Grid"
+msgstr ""
+
+#: editor_actions.cc:267
+msgid "Playhead to Previous Grid"
+msgstr ""
 
-#: editor_actions.cc:271
+#: editor_actions.cc:272
 msgid "Zoom to Selection"
 msgstr "Масштабировать до выделения"
 
-#: editor_actions.cc:272
+#: editor_actions.cc:273
 msgid "Toggle Zoom State"
 msgstr "Переключить состояния масштаба"
 
-#: editor_actions.cc:274
+#: editor_actions.cc:275
 msgid "Expand Track Height"
 msgstr "Увеличить высоту дорожки"
 
-#: editor_actions.cc:275
+#: editor_actions.cc:276
 msgid "Shrink Track Height"
 msgstr "Уменьшить высоту дорожки"
 
-#: editor_actions.cc:277
+#: editor_actions.cc:278
 msgid "Move Selected Tracks Up"
 msgstr "Поднять выбранные дорожки"
 
-#: editor_actions.cc:279
+#: editor_actions.cc:280
 msgid "Move Selected Tracks Down"
 msgstr "Опустить выбранные дорожки"
 
-#: editor_actions.cc:282
+#: editor_actions.cc:283
 msgid "Scroll Tracks Up"
 msgstr "Прокрутить дорожки вверх"
 
-#: editor_actions.cc:284
+#: editor_actions.cc:285
 msgid "Scroll Tracks Down"
 msgstr "Прокрутить дорожки вниз"
 
-#: editor_actions.cc:286
+#: editor_actions.cc:287
 msgid "Step Tracks Up"
 msgstr "Перейти на дорожку выше"
 
-#: editor_actions.cc:288
+#: editor_actions.cc:289
 msgid "Step Tracks Down"
 msgstr "Перейти на дорожку ниже"
 
-#: editor_actions.cc:291
+#: editor_actions.cc:292
 msgid "Scroll Backward"
 msgstr "Прокрутить назад"
 
-#: editor_actions.cc:292
+#: editor_actions.cc:293
 msgid "Scroll Forward"
 msgstr "Прокрутить вперёд"
 
-#: editor_actions.cc:293
+#: editor_actions.cc:294
 msgid "Center Playhead"
 msgstr "Указатель по центру"
 
-#: editor_actions.cc:294
+#: editor_actions.cc:295
 msgid "Center Edit Point"
 msgstr "Центрировать точку редактирования"
 
-#: editor_actions.cc:296
+#: editor_actions.cc:297
 msgid "Playhead Forward"
 msgstr "Указатель вперёд"
 
-#: editor_actions.cc:297
+#: editor_actions.cc:298
 msgid "Playhead Backward"
 msgstr "Указатель назад"
 
-#: editor_actions.cc:299
+#: editor_actions.cc:300
 msgid "Playhead to Active Mark"
 msgstr "Указатель к активному маркеру"
 
-#: editor_actions.cc:300
+#: editor_actions.cc:301
 msgid "Active Mark to Playhead"
 msgstr "Активный маркер к указателю воспроизведения"
 
-#: editor_actions.cc:302
+#: editor_actions.cc:303
 msgid "Use Skip Ranges"
 msgstr "Исп. пропуск диапазонов"
 
-#: editor_actions.cc:309
+#: editor_actions.cc:310
 msgid "Play Selected Regions"
 msgstr "Воспроизвести выбранные области"
 
-#: editor_actions.cc:311
+#: editor_actions.cc:312
 msgid "Play from Edit Point and Return"
 msgstr "Воспроизвести от курсора редактора и вернуться"
 
-#: editor_actions.cc:313
+#: editor_actions.cc:314
 msgid "Play Edit Range"
 msgstr "Воспроизвести изменяемое выделение"
 
-#: editor_actions.cc:315
+#: editor_actions.cc:316
 msgid "Playhead to Mouse"
 msgstr "Указатель к курсору мыши"
 
-#: editor_actions.cc:316
+#: editor_actions.cc:317
 msgid "Active Marker to Mouse"
 msgstr "Активный маркер к указателю мыши"
 
-#: editor_actions.cc:326
+#: editor_actions.cc:327
 msgid "Undo Selection Change"
 msgstr "Отменить смену выделения"
 
-#: editor_actions.cc:327
+#: editor_actions.cc:328
 msgid "Redo Selection Change"
 msgstr "Повторить смену выделения"
 
-#: editor_actions.cc:329
+#: editor_actions.cc:330
 msgid "Export Audio"
 msgstr "Экспортировать звук"
 
-#: editor_actions.cc:330 export_dialog.cc:396
+#: editor_actions.cc:331 export_dialog.cc:394
 msgid "Export Range"
 msgstr "Экспортировать область"
 
-#: editor_actions.cc:335
+#: editor_actions.cc:336
 msgid "Separate Using Punch Range"
 msgstr "Разделить по выделению врезки"
 
-#: editor_actions.cc:338
+#: editor_actions.cc:339
 msgid "Separate Using Loop Range"
 msgstr "Разделить по выделению петли"
 
-#: editor_actions.cc:341 editor_actions.cc:363
+#: editor_actions.cc:342 editor_actions.cc:364
 msgid "Crop"
 msgstr "Обрезать"
 
-#: editor_actions.cc:351
+#: editor_actions.cc:352
 msgid "Fade Range Selection"
 msgstr "Диапазон появления"
 
-#: editor_actions.cc:353
+#: editor_actions.cc:354
 msgid "Set Tempo from Edit Range = Bar"
 msgstr "Установить темп, считая что диапазон редактирования = такт"
 
-#: editor_actions.cc:355
+#: editor_actions.cc:356
 msgid "Log"
 msgstr "Журнал"
 
-#: editor_actions.cc:358 editor_actions.cc:360
+#: editor_actions.cc:359 editor_actions.cc:361
 msgid "Move to Next Transient"
 msgstr "Перейти к следующей переменной"
 
-#: editor_actions.cc:359 editor_actions.cc:361
+#: editor_actions.cc:360 editor_actions.cc:362
 msgid "Move to Previous Transient"
 msgstr "Перейти к предыдущей переменной"
 
-#: editor_actions.cc:365 editor_actions.cc:368
+#: editor_actions.cc:366 editor_actions.cc:375
 msgid "Start Range"
 msgstr "Начать выделение"
 
-#: editor_actions.cc:366 editor_actions.cc:369
+#: editor_actions.cc:367 editor_actions.cc:376
 msgid "Finish Range"
 msgstr "Закончить выделение"
 
-#: editor_actions.cc:401
+#: editor_actions.cc:369
+msgid "Start Punch Range"
+msgstr "Начать врезку"
+
+#: editor_actions.cc:370
+msgid "Finish Punch Range"
+msgstr "Закрыть врезку"
+
+#: editor_actions.cc:372
+msgid "Start Loop Range"
+msgstr "Начать петлю"
+
+#: editor_actions.cc:373
+msgid "Finish Loop Range"
+msgstr "Закрыть петлю"
+
+#: editor_actions.cc:408
 msgid "Follow Playhead"
 msgstr "Следовать за указателем"
 
-#: editor_actions.cc:402
+#: editor_actions.cc:409
 msgid "Remove Last Capture"
 msgstr "Удалить последнюю запись"
 
-#: editor_actions.cc:404
+#: editor_actions.cc:411
 msgid "Stationary Playhead"
 msgstr "Неподвижный указатель"
 
-#: editor_actions.cc:406 insert_remove_time_dialog.cc:32
+#: editor_actions.cc:413 insert_remove_time_dialog.cc:32
 msgid "Insert Time"
 msgstr "Вставить промежуток времени"
 
-#: editor_actions.cc:408 insert_remove_time_dialog.cc:32
+#: editor_actions.cc:415 insert_remove_time_dialog.cc:32
 msgid "Remove Time"
 msgstr ""
 
-#: editor_actions.cc:413
+#: editor_actions.cc:420
 msgid "Toggle Active"
 msgstr "Переключить активность"
 
-#: editor_actions.cc:415 editor_actions.cc:1780 editor_markers.cc:914
-#: editor_markers.cc:979 editor_snapshots.cc:122 mixer_strip.cc:1603
-#: route_time_axis.cc:867
+#: editor_actions.cc:422 editor_actions.cc:1787 editor_markers.cc:921
+#: editor_markers.cc:986 editor_snapshots.cc:134 mixer_strip.cc:1621
+#: route_time_axis.cc:872
 msgid "Remove"
 msgstr "Удалить"
 
-#: editor_actions.cc:420
+#: editor_actions.cc:427
 msgid "Fit Selection (Vertical)"
 msgstr "Уместить выделение по вертикали"
 
-#: editor_actions.cc:422 time_axis_view.cc:1382
+#: editor_actions.cc:429 time_axis_view.cc:1380
 msgid "Largest"
 msgstr "Огромная"
 
-#: editor_actions.cc:425 time_axis_view.cc:1383
+#: editor_actions.cc:432 time_axis_view.cc:1381
 msgid "Larger"
 msgstr "Больше"
 
-#: editor_actions.cc:428 editor_rulers.cc:249 time_axis_view.cc:1384
+#: editor_actions.cc:435 editor_rulers.cc:248 time_axis_view.cc:1382
 msgid "Large"
 msgstr "Большая"
 
-#: editor_actions.cc:434 editor_rulers.cc:253 time_axis_view.cc:1386
+#: editor_actions.cc:441 editor_rulers.cc:252 time_axis_view.cc:1384
 msgid "Small"
 msgstr "Маленькая"
 
-#: editor_actions.cc:438
+#: editor_actions.cc:445
 msgid "Sound Selected MIDI Notes"
 msgstr "Воспроизводить выделяемые MIDI-ноты"
 
-#: editor_actions.cc:443
+#: editor_actions.cc:450
 msgid "Zoom Focus Left"
 msgstr "Влево"
 
-#: editor_actions.cc:444
+#: editor_actions.cc:451
 msgid "Zoom Focus Right"
 msgstr "Вправо"
 
-#: editor_actions.cc:445
+#: editor_actions.cc:452
 msgid "Zoom Focus Center"
 msgstr "По центру"
 
-#: editor_actions.cc:446
+#: editor_actions.cc:453
 msgid "Zoom Focus Playhead"
 msgstr "По указателю"
 
-#: editor_actions.cc:447
+#: editor_actions.cc:454
 msgid "Zoom Focus Mouse"
 msgstr "По курсору мыши"
 
-#: editor_actions.cc:448
+#: editor_actions.cc:455
 msgid "Zoom Focus Edit Point"
 msgstr "По точке редактирования"
 
-#: editor_actions.cc:450
+#: editor_actions.cc:457
 msgid "Next Zoom Focus"
 msgstr "Следующий вариант фокуса"
 
-#: editor_actions.cc:456
+#: editor_actions.cc:463
 msgid "Smart Object Mode"
 msgstr "Универсальный режим"
 
-#: editor_actions.cc:459
+#: editor_actions.cc:466
 msgid "Smart"
 msgstr "Универсальный"
 
-#: editor_actions.cc:462
+#: editor_actions.cc:469
 msgid "Object Tool"
 msgstr "Объект"
 
-#: editor_actions.cc:467
+#: editor_actions.cc:474
 msgid "Range Tool"
 msgstr "Выделение"
 
-#: editor_actions.cc:472
+#: editor_actions.cc:479
 msgid "Note Drawing Tool"
 msgstr "Инструмент рисования нот"
 
-#: editor_actions.cc:477
+#: editor_actions.cc:484
 msgid "Audition Tool"
 msgstr "Инструмент прослушивания"
 
-#: editor_actions.cc:482
+#: editor_actions.cc:489
 msgid "Time FX Tool"
 msgstr "Растяжение во времени"
 
-#: editor_actions.cc:487
+#: editor_actions.cc:494
 msgid "Content Tool"
 msgstr "Правка содержимого"
 
-#: editor_actions.cc:493
+#: editor_actions.cc:500
 msgid "Cut Tool"
 msgstr "Инструмент обрезки"
 
-#: editor_actions.cc:499
+#: editor_actions.cc:506
 msgid "Step Mouse Mode"
 msgstr "Режим шага мыши"
 
-#: editor_actions.cc:506
+#: editor_actions.cc:513
 msgid "Change Edit Point"
 msgstr "Изменить точку редактирования"
 
-#: editor_actions.cc:507
+#: editor_actions.cc:514
 msgid "Change Edit Point Including Marker"
 msgstr "Изменить точку редактирования, включая маркер"
 
-#: editor_actions.cc:512
+#: editor_actions.cc:519
 msgid "EditMode|Lock"
 msgstr "Блок"
 
-#: editor_actions.cc:513
+#: editor_actions.cc:520
 msgid "Cycle Edit Mode"
 msgstr "Циклически менять режим редактирования"
 
-#: editor_actions.cc:515
+#: editor_actions.cc:522
 msgid "Snap to"
 msgstr "Привязка"
 
-#: editor_actions.cc:516
+#: editor_actions.cc:523
 msgid "Snap Mode"
 msgstr "Режим привязки"
 
-#: editor_actions.cc:523
+#: editor_actions.cc:530
 msgid "Next Snap Mode"
 msgstr "Следующий режим привязки"
 
-#: editor_actions.cc:524
+#: editor_actions.cc:531
 msgid "Next Snap Choice"
 msgstr "Следующий выбор привязки"
 
-#: editor_actions.cc:525
+#: editor_actions.cc:532
 msgid "Next Musical Snap Choice"
 msgstr "Следующий вариант привязки (такты, доли)"
 
-#: editor_actions.cc:526
+#: editor_actions.cc:533
 msgid "Previous Snap Choice"
 msgstr "Предыдущий вариант привязки"
 
-#: editor_actions.cc:527
+#: editor_actions.cc:534
 msgid "Previous Musical Snap Choice"
 msgstr "Предыдущий вариант привязки (такты, доли)"
 
-#: editor_actions.cc:532
+#: editor_actions.cc:539
 msgid "Snap to CD Frame"
 msgstr "К выборкам CD"
 
-#: editor_actions.cc:533
+#: editor_actions.cc:540
 msgid "Snap to Timecode Frame"
 msgstr "К кадрам таймкода"
 
-#: editor_actions.cc:534
+#: editor_actions.cc:541
 msgid "Snap to Timecode Seconds"
 msgstr "К секундам таймкода"
 
-#: editor_actions.cc:535
+#: editor_actions.cc:542
 msgid "Snap to Timecode Minutes"
 msgstr "К минутам таймкода"
 
-#: editor_actions.cc:536
+#: editor_actions.cc:543
 msgid "Snap to Seconds"
 msgstr "К секундам"
 
-#: editor_actions.cc:537
+#: editor_actions.cc:544
 msgid "Snap to Minutes"
 msgstr "К минутам"
 
-#: editor_actions.cc:539
+#: editor_actions.cc:546
 msgid "Snap to One Twenty Eighths"
 msgstr "К 1/28"
 
-#: editor_actions.cc:540
+#: editor_actions.cc:547
 msgid "Snap to Sixty Fourths"
 msgstr "К 1/24"
 
-#: editor_actions.cc:541
+#: editor_actions.cc:548
 msgid "Snap to Thirty Seconds"
 msgstr "К 30 секундам"
 
-#: editor_actions.cc:542
+#: editor_actions.cc:549
 msgid "Snap to Twenty Eighths"
 msgstr "К 1/28"
 
-#: editor_actions.cc:543
+#: editor_actions.cc:550
 msgid "Snap to Twenty Fourths"
 msgstr "К 1/24"
 
-#: editor_actions.cc:544
+#: editor_actions.cc:551
 msgid "Snap to Twentieths"
 msgstr "К 1/20"
 
-#: editor_actions.cc:545
+#: editor_actions.cc:552
 msgid "Snap to Sixteenths"
 msgstr "К 1/16"
 
-#: editor_actions.cc:546
+#: editor_actions.cc:553
 msgid "Snap to Fourteenths"
 msgstr "К 1/14"
 
-#: editor_actions.cc:547
+#: editor_actions.cc:554
 msgid "Snap to Twelfths"
 msgstr "К 1/12"
 
-#: editor_actions.cc:548
+#: editor_actions.cc:555
 msgid "Snap to Tenths"
 msgstr "К 1/10"
 
-#: editor_actions.cc:549
+#: editor_actions.cc:556
 msgid "Snap to Eighths"
 msgstr "К 1/8"
 
-#: editor_actions.cc:550
+#: editor_actions.cc:557
 msgid "Snap to Sevenths"
 msgstr "К 1/7"
 
-#: editor_actions.cc:551
+#: editor_actions.cc:558
 msgid "Snap to Sixths"
 msgstr "К 1/6"
 
-#: editor_actions.cc:552
+#: editor_actions.cc:559
 msgid "Snap to Fifths"
 msgstr "К 1/5"
 
-#: editor_actions.cc:553
+#: editor_actions.cc:560
 msgid "Snap to Quarters"
 msgstr "К 1/4"
 
-#: editor_actions.cc:554
+#: editor_actions.cc:561
 msgid "Snap to Thirds"
 msgstr "К 1/3"
 
-#: editor_actions.cc:555
+#: editor_actions.cc:562
 msgid "Snap to Halves"
 msgstr "К 1/2"
 
-#: editor_actions.cc:557
+#: editor_actions.cc:564
 msgid "Snap to Beat"
 msgstr "К долям"
 
-#: editor_actions.cc:558
+#: editor_actions.cc:565
 msgid "Snap to Bar"
 msgstr "К тактам"
 
-#: editor_actions.cc:559
+#: editor_actions.cc:566
 msgid "Snap to Mark"
 msgstr "К маркерам"
 
-#: editor_actions.cc:560
+#: editor_actions.cc:567
 msgid "Snap to Region Start"
 msgstr "К началам областей"
 
-#: editor_actions.cc:561
+#: editor_actions.cc:568
 msgid "Snap to Region End"
 msgstr "К концам областей"
 
-#: editor_actions.cc:562
+#: editor_actions.cc:569
 msgid "Snap to Region Sync"
 msgstr "К синхронизаторам областей"
 
-#: editor_actions.cc:563
+#: editor_actions.cc:570
 msgid "Snap to Region Boundary"
 msgstr "К границам областей"
 
-#: editor_actions.cc:565
+#: editor_actions.cc:572
 msgid "Show Marker Lines"
 msgstr "Показывать линии маркеров"
 
-#: editor_actions.cc:575
+#: editor_actions.cc:582
 msgid "Loop/Punch"
 msgstr "Петли/Врезки"
 
-#: editor_actions.cc:579
+#: editor_actions.cc:586
 msgid "Min:Sec"
 msgstr "Мин:С"
 
-#: editor_actions.cc:581 editor_actions.cc:584 editor_rulers.cc:271
+#: editor_actions.cc:588 editor_actions.cc:591 editor_rulers.cc:270
 msgid "Video Monitor"
 msgstr "Видеомонитор"
 
-#: editor_actions.cc:583 rc_option_editor.cc:2734
+#: editor_actions.cc:590 rc_option_editor.cc:2720
 msgid "Video"
 msgstr "Видео"
 
-#: editor_actions.cc:586
+#: editor_actions.cc:593
 msgid "Always on Top"
 msgstr "Всегда сверху"
 
-#: editor_actions.cc:588
+#: editor_actions.cc:595
 msgid "Frame number"
 msgstr "Номер кадра"
 
-#: editor_actions.cc:589
+#: editor_actions.cc:596
 msgid "Timecode Background"
 msgstr "Фон тайм-кода"
 
-#: editor_actions.cc:590
+#: editor_actions.cc:597
 msgid "Fullscreen"
 msgstr "Во весь экран"
 
-#: editor_actions.cc:591
+#: editor_actions.cc:598
 msgid "Letterbox"
 msgstr "Уместить в окно"
 
-#: editor_actions.cc:592
+#: editor_actions.cc:599
 msgid "Original Size"
 msgstr "Исходный размер"
 
-#: editor_actions.cc:649
+#: editor_actions.cc:656
 msgid "Sort"
 msgstr "Сортировать"
 
-#: editor_actions.cc:660 editor_routes.cc:484 mixer_ui.cc:1212
+#: editor_actions.cc:667 editor_routes.cc:485 mixer_ui.cc:1258
 msgid "Show All"
 msgstr "Показать всё"
 
-#: editor_actions.cc:661
+#: editor_actions.cc:668
 msgid "Show Automatic Regions"
 msgstr "Показать автомат. области"
 
-#: editor_actions.cc:663
+#: editor_actions.cc:670
 msgid "Ascending"
 msgstr "По возрастанию"
 
-#: editor_actions.cc:665
+#: editor_actions.cc:672
 msgid "Descending"
 msgstr "По убыванию"
 
-#: editor_actions.cc:668
+#: editor_actions.cc:675
 msgid "By Region Name"
 msgstr "По имени области"
 
-#: editor_actions.cc:670
+#: editor_actions.cc:677
 msgid "By Region Length"
 msgstr "По длительности области"
 
-#: editor_actions.cc:672
+#: editor_actions.cc:679
 msgid "By Region Position"
 msgstr "По расположению области"
 
-#: editor_actions.cc:674
+#: editor_actions.cc:681
 msgid "By Region Timestamp"
 msgstr "По времени создания области"
 
-#: editor_actions.cc:676
+#: editor_actions.cc:683
 msgid "By Region Start in File"
 msgstr "По началу области в файле"
 
-#: editor_actions.cc:678
+#: editor_actions.cc:685
 msgid "By Region End in File"
 msgstr "По концу области в файле"
 
-#: editor_actions.cc:680
+#: editor_actions.cc:687
 msgid "By Source File Name"
 msgstr "По имени исходного файла"
 
-#: editor_actions.cc:682
+#: editor_actions.cc:689
 msgid "By Source File Length"
 msgstr "По длительности исходного файла"
 
-#: editor_actions.cc:684
+#: editor_actions.cc:691
 msgid "By Source File Creation Date"
 msgstr "По дате создания исходного файла"
 
-#: editor_actions.cc:686
+#: editor_actions.cc:693
 msgid "By Source Filesystem"
 msgstr "По исходной файловой системе"
 
-#: editor_actions.cc:689
+#: editor_actions.cc:696
 msgid "Remove Unused"
 msgstr "Удаление неиспользуемых"
 
-#: editor_actions.cc:691
+#: editor_actions.cc:698
 msgid "Import PT session"
 msgstr "Импортировать сессию PT"
 
-#: editor_actions.cc:696 editor_audio_import.cc:282 editor_pt_import.cc:148
+#: editor_actions.cc:703 editor_audio_import.cc:282 editor_pt_import.cc:148
 #: session_import_dialog.cc:75 session_import_dialog.cc:95
-#: session_metadata_dialog.cc:418 editor_videotimeline.cc:91
+#: session_metadata_dialog.cc:418 sfdb_ui.cc:558 editor_videotimeline.cc:91
 msgid "Import"
 msgstr "Импортировать"
 
-#: editor_actions.cc:699
+#: editor_actions.cc:706
 msgid "Import to Region List..."
 msgstr "Импортировать в список областей…"
 
-#: editor_actions.cc:702 session_import_dialog.cc:44
-msgid "Import From Session"
+#: editor_actions.cc:709 session_import_dialog.cc:44
+#: session_import_dialog.cc:65
+msgid "Import from Session"
 msgstr "Импортировать из сессии"
 
-#: editor_actions.cc:706
+#: editor_actions.cc:713
 msgid "Bring all media into session folder"
 msgstr "Занести все медиа в папку сессии"
 
-#: editor_actions.cc:709
+#: editor_actions.cc:716
 msgid "Show Summary"
 msgstr "Показывать сводку"
 
-#: editor_actions.cc:711
+#: editor_actions.cc:718
 msgid "Show Group Tabs"
 msgstr "Показывать вкладки групп"
 
-#: editor_actions.cc:713
+#: editor_actions.cc:720
 msgid "Show Measure Lines"
 msgstr "Показывать линии тактов и долей"
 
-#: editor_actions.cc:717
+#: editor_actions.cc:724
 msgid "Show Logo"
 msgstr "Показать логотип"
 
-#: editor_actions.cc:721
+#: editor_actions.cc:728
 msgid "Toggle MIDI Input Active for Editor-Selected Tracks/Busses"
 msgstr "Переключить активный вход MIDI для редактора выбранных дорожек/шин"
 
-#: editor_actions.cc:744
+#: editor_actions.cc:751
 msgid "Loaded editor bindings from %1"
 msgstr "Загруженный редактор привязки от %1"
 
-#: editor_actions.cc:746
+#: editor_actions.cc:753
 msgid "Could not find editor.bindings in search path %1"
 msgstr "Не удалось найти редактор привязок в пути поиска %1"
 
-#: editor_actions.cc:1090 editor_actions.cc:1486 editor_actions.cc:1497
-#: editor_actions.cc:1550 editor_actions.cc:1561 editor_actions.cc:1608
-#: editor_actions.cc:1618 editor_regions.cc:1571
+#: editor_actions.cc:1097 editor_actions.cc:1493 editor_actions.cc:1504
+#: editor_actions.cc:1557 editor_actions.cc:1568 editor_actions.cc:1615
+#: editor_actions.cc:1625 editor_regions.cc:1575
 msgid "programming error: %1: %2"
 msgstr "Ошибка в программе: %1: %2"
 
-#: editor_actions.cc:1786
+#: editor_actions.cc:1793
 msgid "Raise"
 msgstr "Поднять"
 
-#: editor_actions.cc:1789
+#: editor_actions.cc:1796
 msgid "Raise to Top"
 msgstr "На самый верх"
 
-#: editor_actions.cc:1792
+#: editor_actions.cc:1799
 msgid "Lower"
 msgstr "Опустить"
 
-#: editor_actions.cc:1795
+#: editor_actions.cc:1802
 msgid "Lower to Bottom"
 msgstr "В самый низ"
 
-#: editor_actions.cc:1798
+#: editor_actions.cc:1805
 msgid "Move to Original Position"
 msgstr "К исходной позиции"
 
-#: editor_actions.cc:1803
+#: editor_actions.cc:1810
 msgid "Lock to Video"
 msgstr "Прикрепить к видео"
 
-#: editor_actions.cc:1808 editor_markers.cc:905
+#: editor_actions.cc:1815 editor_markers.cc:912
 msgid "Glue to Bars and Beats"
 msgstr "Прикрепить к тактам и долям"
 
-#: editor_actions.cc:1813
+#: editor_actions.cc:1820
 msgid "Remove Sync"
 msgstr "Удалить синхронизатор"
 
-#: editor_actions.cc:1816 mixer_strip.cc:2068 monitor_section.cc:278
-#: monitor_section.cc:368 route_time_axis.cc:255 route_time_axis.cc:537
+#: editor_actions.cc:1823 mixer_strip.cc:2088 monitor_section.cc:252
+#: monitor_section.cc:320 route_time_axis.cc:256 route_time_axis.cc:538
 msgid "Mute"
 msgstr "Молча"
 
-#: editor_actions.cc:1819
+#: editor_actions.cc:1826
 msgid "Normalize..."
 msgstr "Нормировать сигнал..."
 
-#: editor_actions.cc:1822
+#: editor_actions.cc:1829
 msgid "Reverse"
 msgstr "Развернуть"
 
-#: editor_actions.cc:1825
+#: editor_actions.cc:1832
 msgid "Make Mono Regions"
 msgstr "Создать моно-области"
 
-#: editor_actions.cc:1828
+#: editor_actions.cc:1835
 msgid "Boost Gain"
 msgstr "Повысить громкость области"
 
-#: editor_actions.cc:1831
+#: editor_actions.cc:1838
 msgid "Cut Gain"
 msgstr "Понизить громкость области"
 
-#: editor_actions.cc:1834
+#: editor_actions.cc:1841
 msgid "Pitch Shift..."
 msgstr "Сменить высоту тона…"
 
-#: editor_actions.cc:1837
-msgid "Transpose..."
-msgstr "Транспозиция…"
-
-#: editor_actions.cc:1840
+#: editor_actions.cc:1847
 msgid "Opaque"
 msgstr "Непрозрачно"
 
-#: editor_actions.cc:1844 editor_regions.cc:117
+#: editor_actions.cc:1851 editor_regions.cc:120
 msgid "Fade In"
 msgstr "Нарастание"
 
-#: editor_actions.cc:1849 editor_regions.cc:118
+#: editor_actions.cc:1856 editor_regions.cc:121
 msgid "Fade Out"
 msgstr "Затухание"
 
-#: editor_actions.cc:1864
+#: editor_actions.cc:1871
 msgid "Multi-Duplicate..."
 msgstr "Продублировать многократно..."
 
-#: editor_actions.cc:1869
+#: editor_actions.cc:1876
 msgid "Fill Track"
 msgstr "Заполнить дорожку"
 
-#: editor_actions.cc:1873 editor_markers.cc:993
+#: editor_actions.cc:1880 editor_markers.cc:1000
 msgid "Set Loop Range"
 msgstr "Установить область петли"
 
-#: editor_actions.cc:1880
+#: editor_actions.cc:1887
 msgid "Set Punch"
 msgstr "Установить врезку"
 
-#: editor_actions.cc:1884
+#: editor_actions.cc:1891
 msgid "Add Single Range Marker"
 msgstr "Добавить маркер текущей области"
 
-#: editor_actions.cc:1889
+#: editor_actions.cc:1896
 msgid "Add Range Marker Per Region"
 msgstr "Добавить по маркеру на каждую область"
 
-#: editor_actions.cc:1893
-msgid "Snap Position To Grid"
-msgstr "Привязать позицию к сетке"
+#: editor_actions.cc:1900
+msgid "Snap Position to Grid"
+msgstr ""
 
-#: editor_actions.cc:1896
+#: editor_actions.cc:1903
 msgid "Close Gaps"
 msgstr "Закрыть интервалы"
 
-#: editor_actions.cc:1899
+#: editor_actions.cc:1906
 msgid "Rhythm Ferret..."
 msgstr "Ритмический хорёк..."
 
-#: editor_actions.cc:1902
+#: editor_actions.cc:1909
 msgid "Export..."
 msgstr "Экспортировать..."
 
-#: editor_actions.cc:1908
+#: editor_actions.cc:1915
 msgid "Separate Under"
 msgstr "Разделить под"
 
-#: editor_actions.cc:1912 editor_actions.cc:1913
+#: editor_actions.cc:1919 editor_actions.cc:1920
 msgid "Set Fade In Length"
 msgstr "Установить длительность нарастания"
 
-#: editor_actions.cc:1914 editor_actions.cc:1915
+#: editor_actions.cc:1921 editor_actions.cc:1922
 msgid "Set Fade Out Length"
 msgstr "Установить длительность затухания"
 
-#: editor_actions.cc:1917
+#: editor_actions.cc:1924
 msgid "Set Tempo from Region = Bar"
 msgstr "Установить темп, считая что область = такт"
 
-#: editor_actions.cc:1922
+#: editor_actions.cc:1929
 msgid "Split at Percussion Onsets"
 msgstr "Разделить по атакам перкуссии"
 
-#: editor_actions.cc:1927
+#: editor_actions.cc:1934
 msgid "List Editor..."
 msgstr "Редактор списка событий"
 
-#: editor_actions.cc:1930
+#: editor_actions.cc:1937
 msgid "Properties..."
 msgstr "Свойства..."
 
-#: editor_actions.cc:1934
+#: editor_actions.cc:1941
 msgid "Bounce (with processing)"
 msgstr "Свести (с обработкой)"
 
-#: editor_actions.cc:1935
+#: editor_actions.cc:1942
 msgid "Bounce (without processing)"
 msgstr "Свести (без обработки)"
 
-#: editor_actions.cc:1936
+#: editor_actions.cc:1943
 msgid "Combine"
 msgstr "Объединить"
 
-#: editor_actions.cc:1937
+#: editor_actions.cc:1944
 msgid "Uncombine"
 msgstr "Снять объединение"
 
-#: editor_actions.cc:1939
+#: editor_actions.cc:1946
 msgid "Spectral Analysis..."
 msgstr "Спектральный анализ..."
 
-#: editor_actions.cc:1941
+#: editor_actions.cc:1948
 msgid "Reset Envelope"
 msgstr "Сбросить огибающую"
 
-#: editor_actions.cc:1943
+#: editor_actions.cc:1950
 msgid "Reset Gain"
 msgstr "Сбросить усиление"
 
-#: editor_actions.cc:1948
+#: editor_actions.cc:1955
 msgid "Envelope Active"
 msgstr "Огибающая активна"
 
-#: editor_actions.cc:1956 editor_actions.cc:1957
+#: editor_actions.cc:1963 editor_actions.cc:1964
 msgid "Insert Patch Change..."
 msgstr "Вставить смену программы..."
 
-#: editor_actions.cc:1958
+#: editor_actions.cc:1965
 msgid "Unlink from other copies"
 msgstr "Отсоединить от других копий"
 
-#: editor_actions.cc:1959
+#: editor_actions.cc:1966
 msgid "Strip Silence..."
 msgstr "Вырезать тишину..."
 
-#: editor_actions.cc:1960
+#: editor_actions.cc:1967
 msgid "Set Range Selection"
 msgstr "Создать выделение из области"
 
-#: editor_actions.cc:1962 editor_actions.cc:1963
+#: editor_actions.cc:1969 editor_actions.cc:1970
 msgid "Nudge Later"
 msgstr "Толкнуть вперёд"
 
-#: editor_actions.cc:1964 editor_actions.cc:1965
+#: editor_actions.cc:1971 editor_actions.cc:1972
 msgid "Nudge Earlier"
 msgstr "Толкнуть назад"
 
-#: editor_actions.cc:1967
+#: editor_actions.cc:1974
 msgid "Sequence Regions"
 msgstr "Выстроить области встык"
 
-#: editor_actions.cc:1972
+#: editor_actions.cc:1979
 msgid "Nudge Later by Capture Offset"
 msgstr "Толкнуть вперёд на смещение захвата"
 
-#: editor_actions.cc:1979
+#: editor_actions.cc:1986
 msgid "Nudge Earlier by Capture Offset"
 msgstr "Толкнуть назад на смещение захвата"
 
-#: editor_actions.cc:1983
+#: editor_actions.cc:1990
 msgid "Trim to Loop"
 msgstr "В петлю"
 
-#: editor_actions.cc:1984
+#: editor_actions.cc:1991
 msgid "Trim to Punch"
 msgstr "Во врезку"
 
-#: editor_actions.cc:1986
+#: editor_actions.cc:1993
 msgid "Trim to Previous"
 msgstr "До предыдущей области"
 
-#: editor_actions.cc:1987
+#: editor_actions.cc:1994
 msgid "Trim to Next"
 msgstr "До следующей области"
 
-#: editor_actions.cc:1994
-msgid "Insert Region From Region List"
-msgstr "Вставить область из списка областей"
+#: editor_actions.cc:2001
+msgid "Insert Region from Region List"
+msgstr ""
 
-#: editor_actions.cc:2000
+#: editor_actions.cc:2007
 msgid "Set Sync Position"
 msgstr "Установить синхронизатор области"
 
-#: editor_actions.cc:2001
+#: editor_actions.cc:2008
 msgid "Place Transient"
 msgstr "Место переходных"
 
-#: editor_actions.cc:2002
+#: editor_actions.cc:2009
 msgid "Split/Separate"
 msgstr "Разбить"
 
-#: editor_actions.cc:2003
+#: editor_actions.cc:2010
 msgid "Trim Start at Edit Point"
 msgstr "Начало по курсору редактора"
 
-#: editor_actions.cc:2004
+#: editor_actions.cc:2011
 msgid "Trim End at Edit Point"
 msgstr "Конец по курсору редактора"
 
-#: editor_actions.cc:2009
+#: editor_actions.cc:2016
 msgid "Align Start"
 msgstr "Выровнять начала областей"
 
-#: editor_actions.cc:2016
+#: editor_actions.cc:2023
 msgid "Align Start Relative"
 msgstr "Выровнять относительно начал областей"
 
-#: editor_actions.cc:2020
+#: editor_actions.cc:2027
 msgid "Align End"
 msgstr "Выровнять концы областей"
 
-#: editor_actions.cc:2025
+#: editor_actions.cc:2032
 msgid "Align End Relative"
 msgstr "Выровнять относительно концов областей"
 
-#: editor_actions.cc:2032
+#: editor_actions.cc:2039
 msgid "Align Sync"
 msgstr "Выровнять по синхронизаторам областей"
 
-#: editor_actions.cc:2039
+#: editor_actions.cc:2046
 msgid "Align Sync Relative"
 msgstr "Выровнять относительно синхронизаторов областей"
 
-#: editor_actions.cc:2043 editor_actions.cc:2046
+#: editor_actions.cc:2050 editor_actions.cc:2053
 msgid "Choose Top..."
 msgstr "Выбрать верхнюю область..."
 
@@ -4861,11 +5020,11 @@ msgstr "Импортировать сессию PT"
 
 #: editor_pt_import.cc:97
 msgid "%1: this is only the directory/folder name, not the filename.\n"
-msgstr ""
+msgstr "%1: это лишь название папки или каталога, а не имя файла.\n"
 
 #: editor_pt_import.cc:131
 msgid "Doesn't seem to be a valid PT session file"
-msgstr ""
+msgstr "Этот файл не похож на корректный файл сеанса PT"
 
 #: editor_pt_import.cc:135
 msgid ""
@@ -4885,214 +5044,226 @@ msgstr ""
 "\n"
 "Продолжить..."
 
-#: editor_canvas_events.cc:1311 editor_drag.cc:1402
+#: editor_canvas_events.cc:1308 editor_drag.cc:1418
 msgid "Could not create new track after region placed in the drop zone"
 msgstr ""
 "Не удалось создать новую дорожку после области, помещённой в рабочую зону"
 
-#: editor_drag.cc:1294
+#: editor_drag.cc:1310
 msgid "fixed time region drag"
 msgstr "Фиксированная временная область перетаскивания"
 
-#: editor_drag.cc:2228
+#: editor_drag.cc:2245
 msgid "Ripple drag"
 msgstr "Перетаскивание ряби"
 
-#: editor_drag.cc:2389 midi_region_view.cc:2850
+#: editor_drag.cc:2307
+msgid "create region"
+msgstr ""
+
+#: editor_drag.cc:2426 midi_region_view.cc:2834
 msgid "resize notes"
 msgstr "Смена размера ноты"
 
-#: editor_drag.cc:2584
+#: editor_drag.cc:2609 editor_drag.cc:2644
+msgid ""
+"One or more Audio Regions\n"
+"are both Locked and\n"
+"Locked to Video.\n"
+"The video cannot me moved."
+msgstr ""
+
+#: editor_drag.cc:2679
 msgid "Video Start:"
 msgstr "Начало видеофайла"
 
-#: editor_drag.cc:2586
+#: editor_drag.cc:2681
 msgid "Diff:"
 msgstr "Разница:"
 
-#: editor_drag.cc:2605
+#: editor_drag.cc:2703
 msgid "Move Video"
 msgstr "Переместить видео"
 
-#: editor_drag.cc:3113
+#: editor_drag.cc:3212
 msgid "copy meter mark"
 msgstr "Скопировать маркер счетчика"
 
-#: editor_drag.cc:3121
+#: editor_drag.cc:3220
 msgid "move meter mark"
 msgstr "Переместить маркер счетчика"
 
-#: editor_drag.cc:3244
-msgid "copy tempo mark"
-msgstr "Скопировать маркер темпа"
-
-#: editor_drag.cc:3252
+#: editor_drag.cc:3308
 msgid "move tempo mark"
 msgstr "Переместить маркер темпа"
 
-#: editor_drag.cc:3504
+#: editor_drag.cc:3345
+msgid "copy tempo mark"
+msgstr "Скопировать маркер темпа"
+
+#: editor_drag.cc:3609
 msgid "change fade in length"
 msgstr "Смена длительности фейда нарастания"
 
-#: editor_drag.cc:3629
+#: editor_drag.cc:3734
 msgid "change fade out length"
 msgstr "Смена длительности фейда затухания"
 
-#: editor_drag.cc:3991
+#: editor_drag.cc:4110
 msgid "move marker"
 msgstr "Смещение маркера"
 
-#: editor_drag.cc:4239 editor_drag.cc:5622
+#: editor_drag.cc:4373 editor_drag.cc:5694
 msgid "automation range move"
 msgstr "Смещение выделения автоматизации"
 
-#: editor_drag.cc:4596
+#: editor_drag.cc:4747
 msgid "An error occurred while executing time stretch operation"
 msgstr "Произошла ошибка при выполнении операции растяжения времени"
 
-#: editor_drag.cc:5057
+#: editor_drag.cc:5208
 msgid "programming_error: %1"
 msgstr "Ошибка в программе: %1"
 
-#: editor_drag.cc:5126 editor_drag.cc:5136
+#: editor_drag.cc:5277 editor_drag.cc:5287
 msgid "new skip marker"
 msgstr "Новый маркер пропуска"
 
-#: editor_drag.cc:5127
+#: editor_drag.cc:5278
 msgid "skip"
 msgstr "Пропустить"
 
-#: editor_drag.cc:5131 location_ui.cc:56
+#: editor_drag.cc:5282 location_ui.cc:58
 msgid "CD"
 msgstr "CD"
 
-#: editor_drag.cc:5132
+#: editor_drag.cc:5283
 msgid "new CD marker"
 msgstr "Новый CD маркер"
 
-#: editor_drag.cc:5137 editor_route_groups.cc:437 mixer_ui.cc:1513
+#: editor_drag.cc:5288 editor_route_groups.cc:438 mixer_ui.cc:1593
 msgid "unnamed"
 msgstr "Безымянный"
 
-#: editor_drag.cc:5443
+#: editor_drag.cc:5601
 msgid "Automation range drag created for invalid region type"
 msgstr ""
 "Перетаскивание области автоматизации предпринято для неправильного типа "
 "области"
 
-#: editor_route_groups.cc:96
+#: editor_route_groups.cc:97
 msgid "Col"
 msgstr "Цвет:"
 
-#: editor_route_groups.cc:96
+#: editor_route_groups.cc:97
 msgid "Group Tab Color"
 msgstr "Цвет вкладки группы"
 
-#: editor_route_groups.cc:97
+#: editor_route_groups.cc:98
 msgid "Name of Group"
 msgstr "Название группы"
 
-#: editor_route_groups.cc:98 editor_routes.cc:208
+#: editor_route_groups.cc:99 editor_routes.cc:209
 msgid "Visible|V"
 msgstr "Ð’"
 
-#: editor_route_groups.cc:98
+#: editor_route_groups.cc:99
 msgid "Group is visible?"
 msgstr "Группа видима"
 
-#: editor_route_groups.cc:99
+#: editor_route_groups.cc:100
 msgid "On"
 msgstr "Вкл"
 
-#: editor_route_groups.cc:99
+#: editor_route_groups.cc:100
 msgid "Group is enabled?"
 msgstr "Группа включена"
 
-#: editor_route_groups.cc:100
+#: editor_route_groups.cc:101
 msgid "Group|G"
 msgstr "Г"
 
-#: editor_route_groups.cc:100
+#: editor_route_groups.cc:101
 msgid "Sharing Gain?"
 msgstr "Разделяется ли усиление"
 
-#: editor_route_groups.cc:101
+#: editor_route_groups.cc:102
 msgid "Relative|Rel"
 msgstr "Отн."
 
-#: editor_route_groups.cc:101
+#: editor_route_groups.cc:102
 msgid "Relative Gain Changes?"
 msgstr "Относительны ли изменения в усилении"
 
-#: editor_route_groups.cc:102 editor_regions.cc:121 editor_routes.cc:212
-#: mixer_strip.cc:2094 meter_strip.cc:367 route_time_axis.cc:2741
-#: time_axis_view.cc:1201
+#: editor_route_groups.cc:103 editor_regions.cc:124 editor_routes.cc:213
+#: mixer_strip.cc:2117 meter_strip.cc:367 route_time_axis.cc:2750
+#: time_axis_view.cc:1199
 msgid "Mute|M"
 msgstr "М"
 
-#: editor_route_groups.cc:102
+#: editor_route_groups.cc:103
 msgid "Sharing Mute?"
 msgstr "Разделяется ли приглушение"
 
-#: editor_route_groups.cc:103 editor_routes.cc:213 mixer_strip.cc:2104
-#: meter_strip.cc:375 route_time_axis.cc:2738
+#: editor_route_groups.cc:104 editor_routes.cc:214 mixer_strip.cc:2130
+#: meter_strip.cc:375 route_time_axis.cc:2747
 msgid "Solo|S"
 msgstr "С"
 
-#: editor_route_groups.cc:103
+#: editor_route_groups.cc:104
 msgid "Sharing Solo?"
 msgstr "Разделяется ли солирование"
 
-#: editor_route_groups.cc:104 midi_time_axis.cc:1623 midi_time_axis.cc:1626
-#: midi_time_axis.cc:1629
+#: editor_route_groups.cc:105 midi_time_axis.cc:1630 midi_time_axis.cc:1633
+#: midi_time_axis.cc:1636
 msgid "Rec"
 msgstr "Зап"
 
-#: editor_route_groups.cc:104
+#: editor_route_groups.cc:105
 msgid "Sharing Record-enable Status?"
 msgstr "Разделяется ли готовность к записи"
 
-#: editor_route_groups.cc:105
+#: editor_route_groups.cc:106
 msgid "Monitoring|Mon"
 msgstr "Мон"
 
-#: editor_route_groups.cc:105
+#: editor_route_groups.cc:106
 msgid "Sharing Monitoring Choice?"
 msgstr "Разделять способ мониторинга"
 
-#: editor_route_groups.cc:106
+#: editor_route_groups.cc:107
 msgid "Selection|Sel"
 msgstr "Выд."
 
-#: editor_route_groups.cc:106
+#: editor_route_groups.cc:107
 msgid "Sharing Selected/Editing Status?"
 msgstr "Разделять статус выделенности"
 
-#: editor_route_groups.cc:107 editor_routes.cc:209
+#: editor_route_groups.cc:108 editor_routes.cc:210
 msgid "Active|A"
 msgstr "А"
 
-#: editor_route_groups.cc:107
+#: editor_route_groups.cc:108
 msgid "Sharing Active Status?"
 msgstr "Разделяется ли активный статус"
 
-#: editor_export_audio.cc:92 editor_markers.cc:733 editor_markers.cc:820
-#: editor_markers.cc:1005 editor_markers.cc:1023 editor_markers.cc:1041
-#: editor_markers.cc:1060 editor_markers.cc:1079 editor_markers.cc:1109
-#: editor_markers.cc:1140 editor_markers.cc:1170 editor_markers.cc:1198
-#: editor_markers.cc:1229 editor_markers.cc:1254 editor_markers.cc:1305
-#: editor_markers.cc:1349 editor_markers.cc:1375 editor_markers.cc:1569
-#: editor_mouse.cc:2140
+#: editor_export_audio.cc:93 editor_markers.cc:733 editor_markers.cc:827
+#: editor_markers.cc:1012 editor_markers.cc:1030 editor_markers.cc:1048
+#: editor_markers.cc:1067 editor_markers.cc:1086 editor_markers.cc:1116
+#: editor_markers.cc:1147 editor_markers.cc:1177 editor_markers.cc:1205
+#: editor_markers.cc:1236 editor_markers.cc:1261 editor_markers.cc:1312
+#: editor_markers.cc:1356 editor_markers.cc:1382 editor_markers.cc:1576
+#: editor_mouse.cc:2248
 msgid "programming error: marker canvas item has no marker object pointer!"
 msgstr "Ошибка в программе: marker canvas item has no marker object pointer!"
 
-#: editor_export_audio.cc:145 editor_export_audio.cc:150
-msgid "File Exists!"
-msgstr "Файл уже существует!"
+#: editor_export_audio.cc:114
+msgid "Confirm MIDI File Overwrite"
+msgstr "Подтвердить перезапись файла MIDI"
 
-#: editor_export_audio.cc:153
-msgid "Overwrite Existing File"
-msgstr "Перезапись существующего файла"
+#: editor_export_audio.cc:115 utils_videotl.cc:73
+msgid "A file with the same name already exists. Do you want to overwrite it?"
+msgstr "Файл с таким именем уже существует. Перезаписать его?"
 
 #: editor_group_tabs.cc:176
 msgid "Fit to Window"
@@ -5110,20 +5281,20 @@ msgstr "Конец"
 msgid "mark"
 msgstr ""
 
-#: editor_markers.cc:650 editor_ops.cc:2100 editor_ops.cc:2122
-#: editor_ops.cc:2238 editor_ops.cc:2275 location_ui.cc:1023
+#: editor_markers.cc:650 editor_ops.cc:2102 editor_ops.cc:2124
+#: editor_ops.cc:2240 editor_ops.cc:2277 location_ui.cc:1025
 msgid "add marker"
 msgstr "Добавка маркера"
 
-#: editor_markers.cc:682 editor_markers.cc:1449
+#: editor_markers.cc:682 editor_markers.cc:1456
 msgid "set loop range"
 msgstr "Создать петлю из области"
 
-#: editor_markers.cc:698 editor_markers.cc:1455
+#: editor_markers.cc:698 editor_markers.cc:1462
 msgid "set punch range"
 msgstr "Создание выделения врезки"
 
-#: editor_markers.cc:715 editor_ops.cc:4169
+#: editor_markers.cc:715 editor_ops.cc:4092
 msgid "range"
 msgstr "диапазон"
 
@@ -5131,106 +5302,106 @@ msgstr "диапазон"
 msgid "new range marker"
 msgstr "Новый маркер диапазона"
 
-#: editor_markers.cc:751 editor_ops.cc:2206 location_ui.cc:859
+#: editor_markers.cc:751 editor_ops.cc:2208 location_ui.cc:861
 msgid "remove marker"
 msgstr "Удаление маркера"
 
-#: editor_markers.cc:887
+#: editor_markers.cc:894
 msgid "Locate to Here"
 msgstr "Переместить сюда указатель"
 
-#: editor_markers.cc:888
+#: editor_markers.cc:895
 msgid "Play from Here"
 msgstr "Воспроизвести отсюда"
 
-#: editor_markers.cc:889
+#: editor_markers.cc:896
 msgid "Move Mark to Playhead"
 msgstr "Маркер к указателю воспроизведения"
 
-#: editor_markers.cc:893
+#: editor_markers.cc:900
 msgid "Create Range to Next Marker"
 msgstr "Создать выделение до след. маркера"
 
-#: editor_markers.cc:934
+#: editor_markers.cc:941
 msgid "Locate to Marker"
 msgstr "Перейти к маркеру"
 
-#: editor_markers.cc:935
+#: editor_markers.cc:942
 msgid "Play from Marker"
 msgstr "Воспроизвести от маркера"
 
-#: editor_markers.cc:938
+#: editor_markers.cc:945
 msgid "Set Marker from Playhead"
 msgstr "Установить маркер по указателю"
 
-#: editor_markers.cc:940
+#: editor_markers.cc:947
 msgid "Set Range from Selection"
 msgstr "Установить диапазон по выделению"
 
-#: editor_markers.cc:950
+#: editor_markers.cc:957
 msgid "Hide Range"
 msgstr "Скрыть выделение"
 
-#: editor_markers.cc:951
+#: editor_markers.cc:958
 msgid "Rename Range..."
 msgstr "Переименовать область…"
 
-#: editor_markers.cc:955
+#: editor_markers.cc:962
 msgid "Remove Range"
 msgstr "Удалить выделение"
 
-#: editor_markers.cc:962
+#: editor_markers.cc:969
 msgid "Separate Regions in Range"
 msgstr "Разделить области в выделении"
 
-#: editor_markers.cc:965
+#: editor_markers.cc:972
 msgid "Select Range"
 msgstr "Выбрать выделение"
 
-#: editor_markers.cc:994
+#: editor_markers.cc:1001
 msgid "Set Punch Range"
 msgstr "Установить область врезки"
 
-#: editor_markers.cc:1400 editor_ops.cc:2055
+#: editor_markers.cc:1407 editor_ops.cc:2057
 msgid "New Name:"
 msgstr "Новое название:"
 
-#: editor_markers.cc:1403
+#: editor_markers.cc:1410
 msgid "Rename Mark"
 msgstr "Переименовать маркер"
 
-#: editor_markers.cc:1405
+#: editor_markers.cc:1412
 msgid "Rename Range"
 msgstr "Переименовать выделение"
 
-#: editor_markers.cc:1412 editor_mouse.cc:2157 processor_box.cc:2060
-#: processor_box.cc:2531 route_time_axis.cc:1107 route_ui.cc:1574
+#: editor_markers.cc:1419 editor_mouse.cc:2265 processor_box.cc:2370
+#: processor_box.cc:2837 route_time_axis.cc:1112 route_ui.cc:1616
 msgid "Rename"
 msgstr "Переименовать"
 
-#: editor_markers.cc:1425
+#: editor_markers.cc:1432
 msgid "rename marker"
 msgstr "Переименование маркера"
 
-#: editor_mixer.cc:90
+#: editor_mixer.cc:91
 msgid "This screen is not tall enough to display the editor mixer"
 msgstr "Экран недостаточно высок, чтобы показать окно редактора"
 
-#: editor_mouse.cc:1235 editor_mouse.cc:1253 editor_tempodisplay.cc:270
+#: editor_mouse.cc:1343 editor_mouse.cc:1361 editor_tempodisplay.cc:270
 msgid ""
 "programming error: tempo marker canvas item has no marker object pointer!"
 msgstr ""
 "Ошибка в программе: tempo marker canvas item has no marker object pointer!"
 
-#: editor_mouse.cc:1240 editor_tempodisplay.cc:275
+#: editor_mouse.cc:1348 editor_tempodisplay.cc:275
 msgid "programming error: marker for tempo is not a tempo marker!"
 msgstr "Ошибка в программе: marker for tempo is not a tempo marker!"
 
-#: editor_mouse.cc:1258 editor_tempodisplay.cc:375
+#: editor_mouse.cc:1366 editor_tempodisplay.cc:375
 msgid "programming error: marker for meter is not a meter marker!"
 msgstr "Ошибка в программе: маркер размера таковым не является!"
 
-#: editor_mouse.cc:1905 editor_mouse.cc:1930 editor_mouse.cc:1943
+#: editor_mouse.cc:2013 editor_mouse.cc:2038 editor_mouse.cc:2051
 msgid ""
 "programming error: control point canvas item has no control point object "
 "pointer!"
@@ -5238,179 +5409,179 @@ msgstr ""
 "ошибка в программе: у контр. точки пункта события нет управления точкой "
 "объектауказатель!"
 
-#: editor_mouse.cc:2078
+#: editor_mouse.cc:2186
 msgid "start point trim"
 msgstr "Обрезка начальной точки"
 
-#: editor_mouse.cc:2103
-msgid "End point trim"
-msgstr "Конечная точка отделки"
+#: editor_mouse.cc:2211
+msgid "end point trim"
+msgstr ""
 
-#: editor_mouse.cc:2155
+#: editor_mouse.cc:2263
 msgid "Name for region:"
 msgstr "Название области: "
 
-#: editor_ops.cc:165
+#: editor_ops.cc:167
 msgid "split"
 msgstr "Разделение"
 
-#: editor_ops.cc:339
+#: editor_ops.cc:341
 msgid "alter selection"
 msgstr "Изменение выделения"
 
-#: editor_ops.cc:381
+#: editor_ops.cc:383
 msgid "nudge regions forward"
 msgstr "Толчок областей вперед"
 
-#: editor_ops.cc:435 editor_ops.cc:526
+#: editor_ops.cc:437 editor_ops.cc:528
 msgid "nudge location forward"
 msgstr "Толчок позиции вперед"
 
-#: editor_ops.cc:466
+#: editor_ops.cc:468
 msgid "nudge regions backward"
 msgstr "Толчок областей назад"
 
-#: editor_ops.cc:558
+#: editor_ops.cc:560
 msgid "nudge forward"
 msgstr "Толчок вперед"
 
-#: editor_ops.cc:582
+#: editor_ops.cc:584
 msgid "nudge backward"
 msgstr "Толчок назад"
 
-#: editor_ops.cc:647
+#: editor_ops.cc:649
 msgid "sequence regions"
 msgstr "выстраивание областей встык"
 
-#: editor_ops.cc:709
+#: editor_ops.cc:711
 msgid "build_region_boundary_cache called with snap_type = %1"
 msgstr "Функция build_region_boundary_cache вызвана с snap_type = %1"
 
-#: editor_ops.cc:2057
+#: editor_ops.cc:2059
 msgid "New Location Marker"
 msgstr "Новый маркер позиции"
 
-#: editor_ops.cc:2148 editor_ops.cc:2172
+#: editor_ops.cc:2150 editor_ops.cc:2174
 msgid "Set session start"
 msgstr ""
 
-#: editor_ops.cc:2238
+#: editor_ops.cc:2240
 msgid "add markers"
 msgstr "Добавка маркера"
 
-#: editor_ops.cc:2334
+#: editor_ops.cc:2336
 msgid "clear markers"
 msgstr "Очистка маркеров"
 
-#: editor_ops.cc:2349
+#: editor_ops.cc:2351
 msgid "clear ranges"
 msgstr "Очистка диапазонов"
 
-#: editor_ops.cc:2365
+#: editor_ops.cc:2367
 msgid "clear locations"
 msgstr "Очистка позиций"
 
-#: editor_ops.cc:2428
+#: editor_ops.cc:2430
 msgid "insert region"
 msgstr "Вставка области"
 
-#: editor_ops.cc:2619
+#: editor_ops.cc:2621
 msgid "raise regions"
 msgstr "Поднятие областей"
 
-#: editor_ops.cc:2621
+#: editor_ops.cc:2623
 msgid "raise region"
 msgstr "Поднятие области"
 
-#: editor_ops.cc:2627
+#: editor_ops.cc:2629
 msgid "raise regions to top"
 msgstr "Поднятие областей наверх"
 
-#: editor_ops.cc:2629
+#: editor_ops.cc:2631
 msgid "raise region to top"
 msgstr "Поднятие области наверх"
 
-#: editor_ops.cc:2635
+#: editor_ops.cc:2637
 msgid "lower regions"
 msgstr "Опускание областей"
 
-#: editor_ops.cc:2637 editor_ops.cc:2645
+#: editor_ops.cc:2639 editor_ops.cc:2647
 msgid "lower region"
 msgstr "Опускание области"
 
-#: editor_ops.cc:2643
+#: editor_ops.cc:2645
 msgid "lower regions to bottom"
 msgstr "Опускание областей вниз"
 
-#: editor_ops.cc:2728
+#: editor_ops.cc:2730
 msgid "Rename Region"
 msgstr "Переименовать область..."
 
-#: editor_ops.cc:2730 processor_box.cc:2058 route_ui.cc:1572
+#: editor_ops.cc:2732 processor_box.cc:2368 route_ui.cc:1614
 msgid "New name:"
 msgstr "Новое название:"
 
-#: editor_ops.cc:3047
+#: editor_ops.cc:3030
 msgid "separate"
 msgstr "разделение"
 
-#: editor_ops.cc:3159
+#: editor_ops.cc:3142
 msgid "separate region under"
 msgstr "разделение области под курсором"
 
-#: editor_ops.cc:3305
+#: editor_ops.cc:3294
 msgid "trim to selection"
 msgstr "Обрезание по выделению"
 
-#: editor_ops.cc:3454
+#: editor_ops.cc:3376
 msgid "set sync point"
 msgstr "Установка точки синхронизации"
 
-#: editor_ops.cc:3478
+#: editor_ops.cc:3400
 msgid "remove region sync"
 msgstr "Удаление синхронизатора области"
 
-#: editor_ops.cc:3500
+#: editor_ops.cc:3422
 msgid "move regions to original position"
 msgstr "Перемещение областей в исходную позицию"
 
-#: editor_ops.cc:3502
+#: editor_ops.cc:3424
 msgid "move region to original position"
 msgstr "Перемещение области в исходную позицию"
 
-#: editor_ops.cc:3523
+#: editor_ops.cc:3445
 msgid "align selection"
 msgstr "Выравнивание выделения"
 
-#: editor_ops.cc:3597
+#: editor_ops.cc:3519
 msgid "align selection (relative)"
 msgstr "Выравнивание выделения (относительное)"
 
-#: editor_ops.cc:3631
+#: editor_ops.cc:3553
 msgid "align region"
 msgstr "Выравнивание области"
 
-#: editor_ops.cc:3682
+#: editor_ops.cc:3604
 msgid "trim front"
 msgstr "Обрезка впереди"
 
-#: editor_ops.cc:3682
+#: editor_ops.cc:3604
 msgid "trim back"
 msgstr "Обрезка сзади"
 
-#: editor_ops.cc:3712
+#: editor_ops.cc:3634
 msgid "trim to loop"
 msgstr "Обрезка в петлю"
 
-#: editor_ops.cc:3722
+#: editor_ops.cc:3644
 msgid "trim to punch"
 msgstr "Обрезка во врезку"
 
-#: editor_ops.cc:3844
+#: editor_ops.cc:3766
 msgid "trim to region"
 msgstr "Обрезка в область"
 
-#: editor_ops.cc:3903
+#: editor_ops.cc:3825
 msgid ""
 "This track/bus cannot be frozen because the signal adds or loses channels "
 "before reaching the outputs.\n"
@@ -5422,11 +5593,11 @@ msgstr ""
 "Это, как правило, вызвано плагинами, которые генерируют выходной "
 "стереосигнал из моновхода или наоборот."
 
-#: editor_ops.cc:3906
+#: editor_ops.cc:3828
 msgid "Cannot freeze"
 msgstr "Невозможно заморозить"
 
-#: editor_ops.cc:3912
+#: editor_ops.cc:3834
 msgid ""
 "<b>%1</b>\n"
 "\n"
@@ -5442,23 +5613,23 @@ msgstr ""
 "Замораживание будет только обрабатывать сигнал как первый посыл/вставку/"
 "возврат."
 
-#: editor_ops.cc:3916
+#: editor_ops.cc:3838
 msgid "Freeze anyway"
 msgstr "Всё равно заморозить"
 
-#: editor_ops.cc:3917
+#: editor_ops.cc:3839
 msgid "Don't freeze"
 msgstr "Не замораживать"
 
-#: editor_ops.cc:3918
+#: editor_ops.cc:3840
 msgid "Freeze Limits"
 msgstr "Пределы заморозки"
 
-#: editor_ops.cc:3933
+#: editor_ops.cc:3855
 msgid "Cancel Freeze"
 msgstr "Отменить замораживание"
 
-#: editor_ops.cc:3963
+#: editor_ops.cc:3885
 msgid ""
 "You can't perform this operation because the processing of the signal will "
 "cause one or more of the tracks to end up with a region with more channels "
@@ -5472,47 +5643,47 @@ msgstr ""
 "\n"
 "Вы можете сделать это без обработки, и это уже другая операция."
 
-#: editor_ops.cc:3967
+#: editor_ops.cc:3889
 msgid "Cannot bounce"
 msgstr "Невозможно выполнить сведение"
 
-#: editor_ops.cc:4018
+#: editor_ops.cc:3940
 msgid "bounce range"
 msgstr "Сведение области"
 
-#: editor_ops.cc:4085
+#: editor_ops.cc:4007
 msgid "delete"
 msgstr "Удаление"
 
-#: editor_ops.cc:4088
+#: editor_ops.cc:4010
 msgid "cut"
 msgstr "Вырезать"
 
-#: editor_ops.cc:4091
+#: editor_ops.cc:4013
 msgid "copy"
 msgstr "Копировать"
 
-#: editor_ops.cc:4094
+#: editor_ops.cc:4016
 msgid "clear"
 msgstr "Очистить"
 
-#: editor_ops.cc:4142
+#: editor_ops.cc:4065
 msgid "objects"
 msgstr "объекты"
 
-#: editor_ops.cc:4352 editor_ops.cc:4437
+#: editor_ops.cc:4275 editor_ops.cc:4360
 msgid "remove region"
 msgstr "Удаление области"
 
-#: editor_ops.cc:4862
+#: editor_ops.cc:4787
 msgid "duplicate selection"
 msgstr "Дублирование выделения"
 
-#: editor_ops.cc:4948
+#: editor_ops.cc:4873
 msgid "nudge track"
 msgstr "Смещение дорожки"
 
-#: editor_ops.cc:4975
+#: editor_ops.cc:4900
 msgid ""
 "Do you really want to destroy the last capture?\n"
 "(This is destructive and cannot be undone)"
@@ -5520,140 +5691,156 @@ msgstr ""
 "Последнюю запись будет удалена. Вы уверены?\n"
 "(отмена операции невозможна)"
 
-#: editor_ops.cc:4978 editor_ops.cc:7078 editor_regions.cc:462
-#: editor_snapshots.cc:159
+#: editor_ops.cc:4903 editor_ops.cc:7127 editor_regions.cc:466
+#: editor_snapshots.cc:171
 msgid "No, do nothing."
 msgstr "Нет"
 
-#: editor_ops.cc:4979
+#: editor_ops.cc:4904
 msgid "Yes, destroy it."
 msgstr "Да"
 
-#: editor_ops.cc:4981
+#: editor_ops.cc:4906
 msgid "Destroy last capture"
 msgstr "Уничтожение последней записи"
 
-#: editor_ops.cc:5057
+#: editor_ops.cc:4982
 msgid "normalize"
 msgstr "Нормализация"
 
-#: editor_ops.cc:5155
+#: editor_ops.cc:5080
 msgid "reverse regions"
 msgstr "Разворот областей"
 
-#: editor_ops.cc:5189
+#: editor_ops.cc:5116
 msgid "strip silence"
 msgstr "Удаление тишины"
 
-#: editor_ops.cc:5270
+#: editor_ops.cc:5197
 msgid "Fork Region(s)"
 msgstr "Ответвление областей"
 
-#: editor_ops.cc:5277
+#: editor_ops.cc:5204
 msgid "Could not unlink %1"
 msgstr "Не удалось отсоединить %1"
 
-#: editor_ops.cc:5517
+#: editor_ops.cc:5465
 msgid "reset region gain"
 msgstr "Сброс усиления области"
 
-#: editor_ops.cc:5575
+#: editor_ops.cc:5523
 msgid "region gain envelope active"
 msgstr "Огибающая области активна"
 
-#: editor_ops.cc:5600
+#: editor_ops.cc:5548
 msgid "toggle region lock"
 msgstr "Переключение блокировки области"
 
-#: editor_ops.cc:5624
+#: editor_ops.cc:5572
 msgid "Toggle Video Lock"
 msgstr "Переключить видеоблокировку"
 
-#: editor_ops.cc:5648
+#: editor_ops.cc:5596
 msgid "region lock style"
 msgstr "Способ блокировки области"
 
-#: editor_ops.cc:5673
+#: editor_ops.cc:5621
 msgid "change region opacity"
 msgstr "Смена прозрачности области"
 
-#: editor_ops.cc:5766
+#: editor_ops.cc:5714
 msgid "fade range"
 msgstr "Диапазон фейда"
 
-#: editor_ops.cc:5804
+#: editor_ops.cc:5752
 msgid "set fade in length"
 msgstr "Установка длины фейда нарастания"
 
-#: editor_ops.cc:5811
+#: editor_ops.cc:5759
 msgid "set fade out length"
 msgstr "Установка длины фейда затухания"
 
-#: editor_ops.cc:5876
+#: editor_ops.cc:5824
 msgid "set fade in shape"
 msgstr "Установка формы фейда нарастания"
 
-#: editor_ops.cc:5911
+#: editor_ops.cc:5859
 msgid "set fade out shape"
 msgstr "Установка формы фейда затухания"
 
-#: editor_ops.cc:5947
+#: editor_ops.cc:5895
 msgid "set fade in active"
 msgstr "Установка активности фейда нарастания"
 
-#: editor_ops.cc:5981
+#: editor_ops.cc:5929
 msgid "set fade out active"
 msgstr "Установка активности фейда затухания"
 
-#: editor_ops.cc:6041
+#: editor_ops.cc:5989
 msgid "toggle fade active"
 msgstr ""
 
-#: editor_ops.cc:6227
+#: editor_ops.cc:6179
 msgid "set loop range from selection"
 msgstr "Установка петли из выделения"
 
-#: editor_ops.cc:6241
+#: editor_ops.cc:6193
 msgid "set loop range from region"
 msgstr "Установка петли из области"
 
-#: editor_ops.cc:6260
+#: editor_ops.cc:6212
 msgid "set punch range from selection"
 msgstr "Установка врезки из выделения"
 
-#: editor_ops.cc:6284
+#: editor_ops.cc:6236
 msgid "set session start/end from selection"
 msgstr "Установка начала/конца сессии из выделения"
 
-#: editor_ops.cc:6299
+#: editor_ops.cc:6272
+msgid "set punch start from EP"
+msgstr ""
+
+#: editor_ops.cc:6300
+msgid "set punch end from EP"
+msgstr ""
+
+#: editor_ops.cc:6333
+msgid "set loop start from EP"
+msgstr ""
+
+#: editor_ops.cc:6361
+msgid "set loop end from EP"
+msgstr ""
+
+#: editor_ops.cc:6372
 msgid "set punch range from region"
 msgstr "Установка врезки из области"
 
-#: editor_ops.cc:6408
+#: editor_ops.cc:6457
 msgid "Add new marker"
 msgstr "Создать маркер"
 
-#: editor_ops.cc:6409
+#: editor_ops.cc:6458
 msgid "Set global tempo"
 msgstr "Установить общий темп"
 
-#: editor_ops.cc:6412
+#: editor_ops.cc:6461
 msgid "Define one bar"
 msgstr "Определение такта"
 
-#: editor_ops.cc:6413
+#: editor_ops.cc:6462
 msgid "Do you want to set the global tempo or add a new tempo marker?"
 msgstr "Вы хотите установить общий темп или добавить новый маркер темпа?"
 
-#: editor_ops.cc:6439
+#: editor_ops.cc:6488
 msgid "set tempo from region"
 msgstr "Установка темпа из области"
 
-#: editor_ops.cc:6469
+#: editor_ops.cc:6518
 msgid "split regions"
 msgstr "Разделение выделений"
 
-#: editor_ops.cc:6511
+#: editor_ops.cc:6560
 msgid ""
 "You are about to split\n"
 "%1\n"
@@ -5665,11 +5852,11 @@ msgstr ""
 "на %2 частей.\n"
 "Это может занять много времени."
 
-#: editor_ops.cc:6518
+#: editor_ops.cc:6567
 msgid "Call for the Ferret!"
 msgstr "(?)Призвать Ферре!"
 
-#: editor_ops.cc:6519
+#: editor_ops.cc:6568
 msgid ""
 "Press OK to continue with this split operation\n"
 "or ask the Ferret dialog to tune the analysis"
@@ -5677,52 +5864,52 @@ msgstr ""
 "Нажмите OK для выполнения разделения\n"
 "или попросите Хорька скорректировать анализ."
 
-#: editor_ops.cc:6521
+#: editor_ops.cc:6570
 msgid "Press OK to continue with this split operation"
 msgstr "Нажмите OK для выполнения разделения"
 
-#: editor_ops.cc:6524
+#: editor_ops.cc:6573
 msgid "Excessive split?"
 msgstr "Массовое разделение?"
 
-#: editor_ops.cc:6676
+#: editor_ops.cc:6725
 msgid "place transient"
 msgstr "Разместить переходные"
 
-#: editor_ops.cc:6711
+#: editor_ops.cc:6760
 msgid "snap regions to grid"
 msgstr "привязка областей к сетке"
 
-#: editor_ops.cc:6750
+#: editor_ops.cc:6799
 msgid "Close Region Gaps"
 msgstr "Закрытие интервалов между областями"
 
-#: editor_ops.cc:6755
+#: editor_ops.cc:6804
 msgid "Crossfade length"
 msgstr "Длительность кроссфейда"
 
-#: editor_ops.cc:6764 editor_ops.cc:6775 rhythm_ferret.cc:119
+#: editor_ops.cc:6813 editor_ops.cc:6824 rhythm_ferret.cc:119
 #: session_option_editor.cc:141
 msgid "ms"
 msgstr "мс"
 
-#: editor_ops.cc:6766
+#: editor_ops.cc:6815
 msgid "Pull-back length"
 msgstr "Растяжка длины назад"
 
-#: editor_ops.cc:6779
+#: editor_ops.cc:6828
 msgid "Ok"
 msgstr "ОК"
 
-#: editor_ops.cc:6794
+#: editor_ops.cc:6843
 msgid "close region gaps"
 msgstr "устранение пробелов области"
 
-#: editor_ops.cc:7036
+#: editor_ops.cc:7085
 msgid "That would be bad news ...."
 msgstr "Это было бы плохой новостью..."
 
-#: editor_ops.cc:7041
+#: editor_ops.cc:7090
 msgid ""
 "Removing the master or monitor bus is such a bad idea\n"
 "that %1 is not going to allow it.\n"
@@ -5738,21 +5925,21 @@ msgstr ""
 "подобные вещи, в файле ardour.rc измените значение параметра\n"
 "\"allow-special-bus-removal\" на \"yes\""
 
-#: editor_ops.cc:7057 route_ui.cc:1938
+#: editor_ops.cc:7106 route_ui.cc:2009
 msgid "track"
 msgid_plural "tracks"
 msgstr[0] "дорожка"
 msgstr[1] "дорожки"
 msgstr[2] "дорожек"
 
-#: editor_ops.cc:7058 route_ui.cc:1938
+#: editor_ops.cc:7107 route_ui.cc:2009
 msgid "bus"
 msgid_plural "busses"
 msgstr[0] "шина"
 msgstr[1] "шины"
 msgstr[2] "шин"
 
-#: editor_ops.cc:7062
+#: editor_ops.cc:7111
 msgid ""
 "Do you really want to remove %1 %2 and %3 %4?\n"
 "(You may also lose the playlists associated with the %2)\n"
@@ -5764,7 +5951,7 @@ msgstr ""
 "\n"
 "Это действие невозможно отменить, файл сессии будет перезаписан."
 
-#: editor_ops.cc:7067
+#: editor_ops.cc:7116
 msgid ""
 "Do you really want to remove %1 %2?\n"
 "(You may also lose the playlists associated with the %2)\n"
@@ -5776,7 +5963,7 @@ msgstr ""
 "\n"
 "Это действие невозможно отменить, файл сессии будет перезаписан."
 
-#: editor_ops.cc:7073
+#: editor_ops.cc:7122
 msgid ""
 "Do you really want to remove %1 %2?\n"
 "\n"
@@ -5786,144 +5973,144 @@ msgstr ""
 "\n"
 "Это действие не может быть отменено и файл сессии будут перезаписан"
 
-#: editor_ops.cc:7080
+#: editor_ops.cc:7129
 msgid "Yes, remove them."
 msgstr "Да, удалить их."
 
-#: editor_ops.cc:7082 editor_snapshots.cc:160
+#: editor_ops.cc:7131 editor_snapshots.cc:172
 msgid "Yes, remove it."
 msgstr "Да, удалить"
 
-#: editor_ops.cc:7087 editor_ops.cc:7089
+#: editor_ops.cc:7136 editor_ops.cc:7138
 msgid "Remove %1"
 msgstr "Удалить %1"
 
-#: editor_ops.cc:7191 editor_ops.cc:7205 editor_ops.cc:7245 editor_ops.cc:7255
+#: editor_ops.cc:7240 editor_ops.cc:7254 editor_ops.cc:7294 editor_ops.cc:7304
 msgid "insert time"
 msgstr "Вставка времени"
 
-#: editor_ops.cc:7308
+#: editor_ops.cc:7357
 msgid "Cannot insert or delete time when in Lock edit."
 msgstr ""
 
-#: editor_ops.cc:7328 editor_ops.cc:7340 editor_ops.cc:7413
+#: editor_ops.cc:7377 editor_ops.cc:7389 editor_ops.cc:7462
 msgid "cut time"
 msgstr ""
 
-#: editor_ops.cc:7426
+#: editor_ops.cc:7475
 msgid "remove time"
 msgstr ""
 
-#: editor_ops.cc:7500
+#: editor_ops.cc:7549
 msgid "There are too many tracks to fit in the current window"
 msgstr "Такое количество дорожек в окне не поместится"
 
-#: editor_ops.cc:7561
+#: editor_ops.cc:7610
 msgid "Sel"
 msgstr "Выб."
 
-#: editor_ops.cc:7600
+#: editor_ops.cc:7649
 #, c-format
 msgid "Saved view %u"
 msgstr "Сохраненный вид %u"
 
-#: editor_ops.cc:7625
+#: editor_ops.cc:7674
 msgid "mute regions"
 msgstr "Приглушение областей"
 
-#: editor_ops.cc:7627
+#: editor_ops.cc:7676
 msgid "mute region"
 msgstr "Приглушение области"
 
-#: editor_ops.cc:7664
+#: editor_ops.cc:7713
 msgid "combine regions"
 msgstr "Объединение областей"
 
-#: editor_ops.cc:7702
+#: editor_ops.cc:7751
 msgid "uncombine regions"
 msgstr "Разъединение областей"
 
-#: editor_ops.cc:7739
+#: editor_ops.cc:7788
 msgid "%1: Locked"
 msgstr "%1: заблокировано"
 
-#: editor_ops.cc:7746
+#: editor_ops.cc:7795
 msgid "Click to unlock"
 msgstr "Снять замок"
 
-#: editor_ops.cc:7793
+#: editor_ops.cc:7844
 msgid "Moving embedded files into session folder"
 msgstr "Перемещение встроенных файлов в папке сессии"
 
-#: editor_regions.cc:112
+#: editor_regions.cc:115
 msgid "Region name, with number of channels in []'s"
 msgstr "Название региона с числом каналов в []'с"
 
-#: editor_regions.cc:113
+#: editor_regions.cc:116
 msgid "Position of start of region"
 msgstr "Положение начала области"
 
-#: editor_regions.cc:114 editor_regions.cc:859 time_info_box.cc:101
+#: editor_regions.cc:117 editor_regions.cc:863 time_info_box.cc:101
 msgid "End"
 msgstr "Конец"
 
-#: editor_regions.cc:114
+#: editor_regions.cc:117
 msgid "Position of end of region"
 msgstr "Положение конца области"
 
-#: editor_regions.cc:115
+#: editor_regions.cc:118
 msgid "Length of the region"
 msgstr "Длительность области"
 
-#: editor_regions.cc:116
+#: editor_regions.cc:119
 msgid "Position of region sync point, relative to start of the region"
 msgstr "Положение точки области синхронизации относительно начала региона"
 
-#: editor_regions.cc:117
+#: editor_regions.cc:120
 msgid "Length of region fade-in (units: secondary clock), () if disabled"
 msgstr "Длина области нарастания (единицы: второй счётчик), (), если отключен"
 
-#: editor_regions.cc:118
+#: editor_regions.cc:121
 msgid "Length of region fade-out (units: secondary clock), () if disabled"
 msgstr "Длина области затухания (единицы: второй счётчик), (), если отключены"
 
-#: editor_regions.cc:119
+#: editor_regions.cc:122
 msgid "Lock|L"
 msgstr "Б"
 
-#: editor_regions.cc:119
+#: editor_regions.cc:122
 msgid "Region position locked?"
 msgstr "Позиция области заблокирована?"
 
-#: editor_regions.cc:120
+#: editor_regions.cc:123
 msgid "Gain|G"
 msgstr "У"
 
-#: editor_regions.cc:120
+#: editor_regions.cc:123
 msgid "Region position glued to Bars|Beats time?"
 msgstr "Приклеить позицию региона к времени Бар|Бит?"
 
-#: editor_regions.cc:121
+#: editor_regions.cc:124
 msgid "Region muted?"
 msgstr "Область приглушена?"
 
-#: editor_regions.cc:122
+#: editor_regions.cc:125
 msgid "Opaque|O"
 msgstr "Н"
 
-#: editor_regions.cc:122
+#: editor_regions.cc:125
 msgid "Region opaque (blocks regions below it from being heard)?"
 msgstr "Непрозрачность региона (блоки регионов под ним слышимы)?"
 
-#: editor_regions.cc:311 editor_regions.cc:316 editor_regions.cc:318
+#: editor_regions.cc:315 editor_regions.cc:320 editor_regions.cc:322
 msgid "Hidden"
 msgstr "Скрытый"
 
-#: editor_regions.cc:391
+#: editor_regions.cc:395
 msgid "(MISSING) "
 msgstr "(ОТСУТСТВУЕТ) "
 
-#: editor_regions.cc:459
+#: editor_regions.cc:463
 msgid ""
 "Do you really want to remove unused regions?\n"
 "(This is destructive and cannot be undone)"
@@ -5931,143 +6118,143 @@ msgstr ""
 "Вы действительно хотите удалить неиспользуемые области?\n"
 "Отменить это действие будет невозможно."
 
-#: editor_regions.cc:463
+#: editor_regions.cc:467
 msgid "Yes, remove."
 msgstr "Да, удалить"
 
-#: editor_regions.cc:465
+#: editor_regions.cc:469
 msgid "Remove unused regions"
 msgstr "Удалить неиспользуемые области"
 
-#: editor_regions.cc:694
+#: editor_regions.cc:698
 msgid "EditorRegions::format_position: negative timecode position: %1"
 msgstr ""
 
-#: editor_regions.cc:824 editor_regions.cc:840 editor_regions.cc:854
+#: editor_regions.cc:828 editor_regions.cc:844 editor_regions.cc:858
 msgid "Mult."
 msgstr "Неск."
 
-#: editor_regions.cc:857 midi_list_editor.cc:104 time_info_box.cc:94
+#: editor_regions.cc:861 midi_list_editor.cc:104 time_info_box.cc:94
 msgid "Start"
 msgstr "Начало"
 
-#: editor_regions.cc:875 editor_regions.cc:891
+#: editor_regions.cc:879 editor_regions.cc:895
 msgid "Multiple"
 msgstr "Несколько"
 
-#: editor_regions.cc:960
+#: editor_regions.cc:964
 msgid "MISSING "
 msgstr "(ОТСУТСТВУЕТ) "
 
-#: editor_routes.cc:183
+#: editor_routes.cc:184
 msgid "SS"
 msgstr "СС"
 
-#: editor_routes.cc:207
+#: editor_routes.cc:208
 msgid "Track/Bus Name"
 msgstr "Название дорожи/шины"
 
-#: editor_routes.cc:208
+#: editor_routes.cc:209
 msgid "Track/Bus visible ?"
 msgstr "Дорожка или шина видима?"
 
-#: editor_routes.cc:209
+#: editor_routes.cc:210
 msgid "Track/Bus active ?"
 msgstr "Дорожка или шина активна?"
 
-#: editor_routes.cc:210
+#: editor_routes.cc:211
 msgid "MidiInput|I"
 msgstr "Ð’Ñ…"
 
-#: editor_routes.cc:210
+#: editor_routes.cc:211
 msgid "MIDI input enabled"
 msgstr "Вход MIDI включен"
 
-#: editor_routes.cc:211
+#: editor_routes.cc:212
 msgid "Rec|R"
 msgstr "З"
 
-#: editor_routes.cc:211
+#: editor_routes.cc:212
 msgid "Record enabled"
 msgstr "Готовность к записи"
 
-#: editor_routes.cc:212
+#: editor_routes.cc:213
 msgid "Muted"
 msgstr "Пригл."
 
-#: editor_routes.cc:213
+#: editor_routes.cc:214
 msgid "Soloed"
 msgstr "Солир."
 
-#: editor_routes.cc:214
+#: editor_routes.cc:215
 msgid "SoloIso|SI"
 msgstr "ИС"
 
-#: editor_routes.cc:214
+#: editor_routes.cc:215
 msgid "Solo Isolated"
 msgstr "Изолирование соло"
 
-#: editor_routes.cc:215
+#: editor_routes.cc:216
 msgid "SoloLock|SS"
 msgstr "БС"
 
-#: editor_routes.cc:215
+#: editor_routes.cc:216
 msgid "Solo Safe (Locked)"
 msgstr "Сохр. соло (закрыт)"
 
-#: editor_routes.cc:485 mixer_ui.cc:1213
+#: editor_routes.cc:486 mixer_ui.cc:1259
 msgid "Hide All"
 msgstr "Скрыть всё"
 
-#: editor_routes.cc:486 mixer_ui.cc:1214
+#: editor_routes.cc:487 mixer_ui.cc:1260
 msgid "Show All Audio Tracks"
 msgstr "Показать все звуковые дорожки"
 
-#: editor_routes.cc:487 mixer_ui.cc:1215
+#: editor_routes.cc:488 mixer_ui.cc:1261
 msgid "Hide All Audio Tracks"
 msgstr "Скрыть все звуковые дорожки"
 
-#: editor_routes.cc:488 mixer_ui.cc:1216
+#: editor_routes.cc:489 mixer_ui.cc:1262
 msgid "Show All Audio Busses"
 msgstr "Показать все звуковые шины"
 
-#: editor_routes.cc:489 mixer_ui.cc:1217
+#: editor_routes.cc:490 mixer_ui.cc:1263
 msgid "Hide All Audio Busses"
 msgstr "Скрыть все звуковые шины"
 
-#: editor_routes.cc:490 mixer_ui.cc:1218
+#: editor_routes.cc:491 mixer_ui.cc:1264
 msgid "Show All Midi Tracks"
 msgstr "Показать все MIDI-дорожки"
 
-#: editor_routes.cc:491 mixer_ui.cc:1219
+#: editor_routes.cc:492 mixer_ui.cc:1265
 msgid "Hide All Midi Tracks"
 msgstr "Скрыть все MIDI-дорожки"
 
-#: editor_routes.cc:492
-msgid "Show Tracks With Regions Under Playhead"
-msgstr "Показывать дорожки с областями под указателем воспроизведения"
+#: editor_routes.cc:493
+msgid "Only Show Tracks with Regions Under Playhead"
+msgstr ""
 
-#: editor_rulers.cc:211
+#: editor_rulers.cc:212
 msgid "New location marker"
 msgstr "Создать маркер позиции"
 
-#: editor_rulers.cc:212
+#: editor_rulers.cc:213
 msgid "Clear all locations"
 msgstr "Стереть все маркеры позиций"
 
-#: editor_rulers.cc:213
+#: editor_rulers.cc:214
 msgid "Unhide locations"
 msgstr "Раскрыть позиции"
 
-#: editor_rulers.cc:217
+#: editor_rulers.cc:218
 msgid "New range"
 msgstr "Создать маркеры диапазона"
 
-#: editor_rulers.cc:218
+#: editor_rulers.cc:219
 msgid "Clear all ranges"
 msgstr "Стереть все маркеры выделения"
 
-#: editor_rulers.cc:219
+#: editor_rulers.cc:220
 msgid "Unhide ranges"
 msgstr "Раскрыть маркеры выделения"
 
@@ -6083,23 +6270,23 @@ msgstr "Создать новую врезку"
 msgid "New CD track marker"
 msgstr "Создать маркер дорожки CD"
 
-#: editor_rulers.cc:235 tempo_dialog.cc:38
+#: editor_rulers.cc:234 tempo_dialog.cc:38
 msgid "New Tempo"
 msgstr "Вставить новый темп"
 
-#: editor_rulers.cc:239 tempo_dialog.cc:315
+#: editor_rulers.cc:238 tempo_dialog.cc:315
 msgid "New Meter"
 msgstr "Вставить новый размер"
 
-#: editor_snapshots.cc:137
+#: editor_snapshots.cc:149
 msgid "Rename Snapshot"
 msgstr "Переименовать снимок"
 
-#: editor_snapshots.cc:139
+#: editor_snapshots.cc:151
 msgid "New name of snapshot"
 msgstr "Новое название снимка"
 
-#: editor_snapshots.cc:157
+#: editor_snapshots.cc:169
 msgid ""
 "Do you really want to remove snapshot \"%1\" ?\n"
 "(which cannot be undone)"
@@ -6107,7 +6294,7 @@ msgstr ""
 "Вы действительно хотите удалить снимок «%1»?\n"
 "Это действие невозможно отменить."
 
-#: editor_snapshots.cc:162
+#: editor_snapshots.cc:174
 msgid "Remove snapshot"
 msgstr "Удалить снимок"
 
@@ -6153,19 +6340,19 @@ msgstr "Смена высоты тона"
 msgid "timefx cannot be started - thread creation error"
 msgstr "Timefx не может быть запущен, ошибка при создании потока"
 
-#: engine_dialog.cc:87
+#: engine_dialog.cc:86
 msgid "Device Control Panel"
 msgstr "Панель управления устройством"
 
-#: engine_dialog.cc:88
+#: engine_dialog.cc:87
 msgid "Midi Device Setup"
 msgstr "Настройка MIDI-устройства"
 
 #: engine_dialog.cc:89
-msgid "Stop (Reconfigure)"
-msgstr "Остановить (для настройки)"
+msgid "Refresh Devices"
+msgstr "Обновить список устройств"
 
-#: engine_dialog.cc:90 engine_dialog.cc:2693
+#: engine_dialog.cc:90 engine_dialog.cc:2923
 msgid "Measure"
 msgstr "Измерить"
 
@@ -6185,7 +6372,7 @@ msgstr "Калибровка аудио"
 msgid "Back to settings"
 msgstr "Возврат к настройкам"
 
-#: engine_dialog.cc:117
+#: engine_dialog.cc:118
 msgid ""
 "No audio/MIDI backends detected. %1 cannot run\n"
 "\n"
@@ -6195,11 +6382,11 @@ msgstr ""
 "\n"
 "(Это ошибка сборки/упаковки/системы, она никогда не должна происходить.)"
 
-#: engine_dialog.cc:142
+#: engine_dialog.cc:143
 msgid "Latency Measurement Tool"
 msgstr "Тестирование задержки отклика"
 
-#: engine_dialog.cc:154
+#: engine_dialog.cc:155
 msgid ""
 "<span weight=\"bold\">Turn down the volume on your audio equipment to a very "
 "low level.</span>"
@@ -6207,94 +6394,98 @@ msgstr ""
 "<span weight=\"bold\">Уберите громкость выхода вашей звуковой карты до "
 "минимума </span>"
 
-#: engine_dialog.cc:163
+#: engine_dialog.cc:164
 msgid "Select two channels below and connect them using a cable."
 msgstr "Выберите два канала ниже и соединить их с помощью кабеля"
 
-#: engine_dialog.cc:168
+#: engine_dialog.cc:169
 msgid "Output channel"
 msgstr "Канал выхода"
 
-#: engine_dialog.cc:176
+#: engine_dialog.cc:177
 msgid "Input channel"
 msgstr "Канал входа"
 
-#: engine_dialog.cc:209
+#: engine_dialog.cc:211
 msgid "Once the channels are connected, click the \"Measure\" button."
 msgstr "Соединив каналы, нажмите кнопку «Измерить»."
 
-#: engine_dialog.cc:216
+#: engine_dialog.cc:218
 msgid "When satisfied with the results, click the \"Use results\" button."
 msgstr ""
 "Если результат вас устраивает, нажмите кнопку «Использовать результаты»."
 
-#: engine_dialog.cc:231 engine_dialog.cc:2813 engine_dialog.cc:2823
+#: engine_dialog.cc:233 engine_dialog.cc:3058 engine_dialog.cc:3068
 msgid "No measurement results yet"
 msgstr "Пока нет результатов измерения"
 
-#: engine_dialog.cc:241 route_params_ui.cc:106
+#: engine_dialog.cc:243 route_params_ui.cc:106
 msgid "Latency"
 msgstr "Задержка отклика"
 
-#: engine_dialog.cc:465
+#: engine_dialog.cc:497
 msgid "Audio System:"
 msgstr "Звуковая подсистема:"
 
-#: engine_dialog.cc:507
+#: engine_dialog.cc:540
 msgid "Driver:"
 msgstr "Драйвер:"
 
-#: engine_dialog.cc:514
+#: engine_dialog.cc:547
 msgid "Input Device:"
 msgstr "Устройство записи:"
 
-#: engine_dialog.cc:518
+#: engine_dialog.cc:551
 msgid "Output Device:"
 msgstr "Устройство вывода:"
 
-#: engine_dialog.cc:525
+#: engine_dialog.cc:558
 msgid "Device:"
 msgstr "Устройство:"
 
-#: engine_dialog.cc:534 engine_dialog.cc:639 sfdb_ui.cc:152 sfdb_ui.cc:347
-#: sfdb_ui.cc:352
+#: engine_dialog.cc:567 engine_dialog.cc:681 sfdb_ui.cc:153 sfdb_ui.cc:348
+#: sfdb_ui.cc:353
 msgid "Sample rate:"
 msgstr "Частота сэмплирования:"
 
-#: engine_dialog.cc:540 engine_dialog.cc:646
+#: engine_dialog.cc:573 engine_dialog.cc:688
 msgid "Buffer size:"
 msgstr "Размер буфера:"
 
-#: engine_dialog.cc:558
+#: engine_dialog.cc:582
+msgid "Periods:"
+msgstr "Периодов:"
+
+#: engine_dialog.cc:600
 msgid "Input Channels:"
 msgstr "Каналов входа:"
 
-#: engine_dialog.cc:571
+#: engine_dialog.cc:613
 msgid "Output Channels:"
 msgstr "Каналов выхода:"
 
-#: engine_dialog.cc:583
+#: engine_dialog.cc:625
 msgid "Hardware input latency:"
 msgstr "Задержка аппаратных входов:"
 
-#: engine_dialog.cc:586 engine_dialog.cc:599
+#: engine_dialog.cc:628 engine_dialog.cc:641
 msgid "samples"
 msgstr "сэмплов"
 
-#: engine_dialog.cc:596
+#: engine_dialog.cc:638
 msgid "Hardware output latency:"
 msgstr "Задержка аппаратных выходов:"
 
-#: engine_dialog.cc:607
+#: engine_dialog.cc:649
 msgid "MIDI System:"
 msgstr "Подсистема MIDI:"
 
-#: engine_dialog.cc:631
+#: engine_dialog.cc:673
 msgid ""
 "%1 is already running. %2 will connect to it and use the existing settings."
 msgstr ""
 
-#: engine_dialog.cc:684
+#: engine_dialog.cc:726
 msgid ""
 "Failed to start or connect to audio-engine.\n"
 "\n"
@@ -6304,7 +6495,7 @@ msgstr ""
 "\n"
 "Калибровка задержки требует рабочий аудиоинтерфейс."
 
-#: engine_dialog.cc:690
+#: engine_dialog.cc:732
 msgid ""
 "Your selected audio configuration is playback- or capture-only.\n"
 "\n"
@@ -6314,144 +6505,152 @@ msgstr ""
 "\n"
 "Калибровка задержки требует воспроизведение и захват"
 
-#: engine_dialog.cc:870
+#: engine_dialog.cc:938
 msgid "MIDI Devices"
 msgstr "MIDI устройства"
 
-#: engine_dialog.cc:876
+#: engine_dialog.cc:944
 msgid "Device"
 msgstr "Устройство"
 
-#: engine_dialog.cc:878
+#: engine_dialog.cc:946
 msgid "Hardware Latencies"
 msgstr "Аппаратные задержки"
 
-#: engine_dialog.cc:919
+#: engine_dialog.cc:987
 msgid "Calibrate"
 msgstr "Калибровка"
 
-#: engine_dialog.cc:1008
+#: engine_dialog.cc:1090
 msgid "all available channels"
 msgstr "Все доступные каналы"
 
-#: engine_dialog.cc:1441 latency_gui.cc:39
+#: engine_dialog.cc:1576 latency_gui.cc:39
 msgid "sample"
 msgid_plural "samples"
 msgstr[0] "сэмпл"
 msgstr[1] "сэмпла"
 msgstr[2] "сэмплов"
 
-#: engine_dialog.cc:1494
+#: engine_dialog.cc:1640
 #, c-format
 msgid "(%.1f ms)"
 msgstr "(%.1f мс)"
 
-#: engine_dialog.cc:2161
+#: engine_dialog.cc:2371
 msgid "Could not start backend engine %1"
 msgstr "Не удалось запустить движок бекенда %1"
 
-#: engine_dialog.cc:2212
+#: engine_dialog.cc:2403
 msgid "Cannot set driver to %1"
 msgstr "Невозможно использовать %1 в качестве драйвера."
 
-#: engine_dialog.cc:2217
+#: engine_dialog.cc:2408
 msgid "Cannot set input device name to %1"
 msgstr ""
 
-#: engine_dialog.cc:2221
+#: engine_dialog.cc:2412
 msgid "Cannot set output device name to %1"
 msgstr ""
 
-#: engine_dialog.cc:2226
+#: engine_dialog.cc:2417
 msgid "Cannot set device name to %1"
 msgstr "Невозможно %1 в имени устройства."
 
-#: engine_dialog.cc:2231
+#: engine_dialog.cc:2422
 msgid "Cannot set sample rate to %1"
 msgstr "Невозможно использовать %1 в частоты сэмплирования."
 
-#: engine_dialog.cc:2235
+#: engine_dialog.cc:2426
 msgid "Cannot set buffer size to %1"
 msgstr "Невозможно использовать %1 в размера буфера."
 
-#: engine_dialog.cc:2241
+#: engine_dialog.cc:2430
+msgid "Cannot set periods to %1"
+msgstr ""
+
+#: engine_dialog.cc:2436
 msgid "Cannot set input channels to %1"
 msgstr "Не удается установить входные каналы в %1"
 
-#: engine_dialog.cc:2245
+#: engine_dialog.cc:2440
 msgid "Cannot set output channels to %1"
 msgstr "Не удается установить выходные каналы в %1"
 
-#: engine_dialog.cc:2251
+#: engine_dialog.cc:2446
 msgid "Cannot set input latency to %1"
 msgstr "Не удается установить задержку входа в %1"
 
-#: engine_dialog.cc:2255
+#: engine_dialog.cc:2450
 msgid "Cannot set output latency to %1"
 msgstr "Не удается установить задержку выхода в %1"
 
-#: engine_dialog.cc:2551 engine_dialog.cc:2610
+#: engine_dialog.cc:2781 engine_dialog.cc:2840
 msgid "No signal detected "
 msgstr "Сигнал не обнаружен"
 
-#: engine_dialog.cc:2564 engine_dialog.cc:2618 port_insert_ui.cc:70
+#: engine_dialog.cc:2794 engine_dialog.cc:2848 port_insert_ui.cc:70
 #: port_insert_ui.cc:98
 msgid "Disconnected from audio engine"
 msgstr "Выполнено отсоединение от звукового движка"
 
-#: engine_dialog.cc:2573 engine_dialog.cc:2626
+#: engine_dialog.cc:2803 engine_dialog.cc:2856
 msgid "Detected roundtrip latency: "
 msgstr "Определены следующие задержки:"
 
-#: engine_dialog.cc:2575 engine_dialog.cc:2628
+#: engine_dialog.cc:2805 engine_dialog.cc:2858
 msgid "Systemic latency: "
 msgstr "Системная задержка:"
 
-#: engine_dialog.cc:2582
+#: engine_dialog.cc:2812
 msgid "(signal detection error)"
 msgstr "(ошибка обнаружения сигнала)"
 
-#: engine_dialog.cc:2588
+#: engine_dialog.cc:2818
 msgid "(inverted - bad wiring)"
 msgstr "(инвертировано - плохая проводка)"
 
-#: engine_dialog.cc:2635
+#: engine_dialog.cc:2865
 msgid "(averaging)"
 msgstr "(усреднение)"
 
-#: engine_dialog.cc:2641
+#: engine_dialog.cc:2871
 msgid "(too large jitter)"
 msgstr "(слишком большое дрожание)"
 
-#: engine_dialog.cc:2645
+#: engine_dialog.cc:2875
 msgid "(large jitter)"
 msgstr "(большое дрожание)"
 
-#: engine_dialog.cc:2657
+#: engine_dialog.cc:2887
 msgid "Timeout - large MIDI jitter."
 msgstr "Тайм-аут - большой MIDI джиттер."
 
-#: engine_dialog.cc:2673 port_insert_ui.cc:134
+#: engine_dialog.cc:2903 port_insert_ui.cc:134
 msgid "Detecting ..."
 msgstr "Выполняется определение..."
 
-#: engine_dialog.cc:2764
+#: engine_dialog.cc:3004
 msgid "Disconnect from %1"
 msgstr "Отсоединить от %1"
 
-#: engine_dialog.cc:2769
+#: engine_dialog.cc:3009
 msgid "Running"
 msgstr ""
 
-#: engine_dialog.cc:2771
+#: engine_dialog.cc:3011
 msgid "Connected"
 msgstr ""
 
-#: engine_dialog.cc:2782
+#: engine_dialog.cc:3022
 msgid "Connect to %1"
 msgstr "Соединить с %1"
 
-#: export_channel_selector.cc:51 sfdb_ui.cc:150
+#: engine_dialog.cc:3026 shuttle_control.cc:614
+msgid "Stopped"
+msgstr "Остановлено"
+
+#: export_channel_selector.cc:51 sfdb_ui.cc:151
 msgid "Channels:"
 msgstr "Каналов:"
 
@@ -6507,20 +6706,20 @@ msgstr ""
 msgid "List files"
 msgstr "Список файлов"
 
-#: export_dialog.cc:158 export_format_dialog.cc:59
+#: export_dialog.cc:156 export_format_dialog.cc:59
 msgid "File format"
 msgstr "Формат"
 
-#: export_dialog.cc:159 export_timespan_selector.cc:374
-#: export_timespan_selector.cc:436
+#: export_dialog.cc:157 export_timespan_selector.cc:371
+#: export_timespan_selector.cc:433
 msgid "Time Span"
 msgstr "Отрезок времени"
 
-#: export_dialog.cc:160
+#: export_dialog.cc:158
 msgid "Channels"
 msgstr "Каналы"
 
-#: export_dialog.cc:182
+#: export_dialog.cc:180
 msgid ""
 "Export has been aborted due to an error!\n"
 "See the Log for details."
@@ -6528,39 +6727,39 @@ msgstr ""
 "Экспорт был прерван из-за ошибки!\n"
 "См. вывод для деталей."
 
-#: export_dialog.cc:251
+#: export_dialog.cc:249
 msgid "Files that will be overwritten"
 msgstr "Файлы будут перезаписаны"
 
-#: export_dialog.cc:296
+#: export_dialog.cc:294
 msgid "Export initialization failed: %1"
 msgstr "Сбой инициализации экспорта: %1"
 
-#: export_dialog.cc:306
+#: export_dialog.cc:304
 msgid "Stop Export"
 msgstr "Остановить экспорт"
 
-#: export_dialog.cc:327
+#: export_dialog.cc:325
 msgid "export"
 msgstr "Экспорт"
 
-#: export_dialog.cc:346
+#: export_dialog.cc:344
 msgid "Normalizing '%3' (timespan %1 of %2)"
 msgstr "Выполняется нормировка '%3' (временной отрезок %1 из %2)"
 
-#: export_dialog.cc:350
+#: export_dialog.cc:348
 msgid "Exporting '%3' (timespan %1 of %2)"
 msgstr "Экспортируется '%3' (отрезок времени %1 из %2)"
 
-#: export_dialog.cc:373 export_dialog.cc:375
+#: export_dialog.cc:371 export_dialog.cc:373
 msgid "<span color=\"#ffa755\">Error: "
 msgstr "<span color=\"#ffa755\">Ошибка: "
 
-#: export_dialog.cc:385
+#: export_dialog.cc:383
 msgid "<span color=\"#ffa755\">Warning: "
 msgstr "<span color=\"#ffa755\">Предупреждение: "
 
-#: export_dialog.cc:387
+#: export_dialog.cc:385
 msgid ""
 "\n"
 "<span color=\"#ffa755\">Warning: "
@@ -6568,19 +6767,19 @@ msgstr ""
 "\n"
 "<span color=\"#ffa755\">Предупреждение: "
 
-#: export_dialog.cc:411
+#: export_dialog.cc:409
 msgid "Export Selection"
 msgstr "Экспортировать выделение"
 
-#: export_dialog.cc:425
+#: export_dialog.cc:423
 msgid "Export Region"
 msgstr "Экспортировать область"
 
-#: export_dialog.cc:434
+#: export_dialog.cc:432
 msgid "Source"
 msgstr "Источник"
 
-#: export_dialog.cc:450
+#: export_dialog.cc:448
 msgid "Stem Export"
 msgstr "Экспортировать каждую дорожку в свой файл"
 
@@ -6612,7 +6811,7 @@ msgstr "Формат %1: %2"
 msgid "Label:"
 msgstr "Метка:"
 
-#: export_filename_selector.cc:33
+#: export_filename_selector.cc:33 session_dialog.cc:310
 msgid "Session Name"
 msgstr "Название сессии"
 
@@ -6635,17 +6834,17 @@ msgstr "Указать"
 msgid "<i>Build filename(s) from these components:</i>"
 msgstr "<i>Сформировать имена файлов из следующих компонентов:</i>"
 
-#: export_filename_selector.cc:212
+#: export_filename_selector.cc:208
 msgid ""
 "<small><i>Sorry, no example filename can be shown at the moment</i></small>"
 msgstr ""
 "<small><i>Извините, показать пример имени файла сейчас невозможно</i></small>"
 
-#: export_filename_selector.cc:214
+#: export_filename_selector.cc:210
 msgid "<small><i>Current (approximate) filename: \"%1\"</i></small>"
 msgstr "<small><i>Текущее предполагаемое имя файла: \"%1\"</i></small>"
 
-#: export_filename_selector.cc:250 export_filename_selector.cc:336
+#: export_filename_selector.cc:246 export_filename_selector.cc:332
 msgid ""
 "%1: this is only the directory/folder name, not the filename.\n"
 "The filename will be chosen from the information just above the folder "
@@ -6654,7 +6853,7 @@ msgstr ""
 "%1: это только имя каталога/папки, но не имя файла. \n"
 "Имя файла будет выбрано из информации чуть выше папки Селектор."
 
-#: export_filename_selector.cc:322
+#: export_filename_selector.cc:318
 msgid "Choose export folder"
 msgstr "Выберите папку для экспорта данных"
 
@@ -6762,7 +6961,7 @@ msgstr "Параметры FLAC"
 msgid "Broadcast Wave options"
 msgstr "Параметры Broadcast Wave"
 
-#: export_format_selector.cc:136
+#: export_format_selector.cc:131
 msgid "Do you really want to remove the format?"
 msgstr "Вы действительно хотите удалить этот формат?"
 
@@ -6770,7 +6969,7 @@ msgstr "Вы действительно хотите удалить этот ф
 msgid "Preset"
 msgstr "Профиль"
 
-#: export_preset_selector.cc:104
+#: export_preset_selector.cc:99
 msgid ""
 "The selected preset did not load successfully!\n"
 "Perhaps it references a format that has been removed?"
@@ -6778,23 +6977,23 @@ msgstr ""
 "Выбранная предустановка загружена не успешно!\n"
 "Может быть, она ссылается на формат, который был удален?"
 
-#: export_preset_selector.cc:156
+#: export_preset_selector.cc:151
 msgid "Do you really want to remove this preset?"
 msgstr "Вы действительно хотите удалить этот профиль?"
 
-#: export_timespan_selector.cc:46
+#: export_timespan_selector.cc:44
 msgid "Show Times as:"
 msgstr "Показать время как:"
 
-#: export_timespan_selector.cc:53 processor_box.cc:2533
+#: export_timespan_selector.cc:51 processor_box.cc:2839
 msgid "Select All"
 msgstr "Выделить всё"
 
-#: export_timespan_selector.cc:223 transform_dialog.cc:93
+#: export_timespan_selector.cc:220 transform_dialog.cc:93
 msgid " to "
 msgstr " до "
 
-#: export_timespan_selector.cc:367 export_timespan_selector.cc:426
+#: export_timespan_selector.cc:364 export_timespan_selector.cc:423
 msgid "Range"
 msgstr "Диапазон"
 
@@ -6810,7 +7009,7 @@ msgstr "getSoundResourceFile: Нет правильного корня в фай
 msgid "getSoundResourceFile: root = %1, != response"
 msgstr "getSoundResourceFile: корень = %1, != ответ"
 
-#: sfdb_freesound_mootcher.cc:410 rc_option_editor.cc:2298
+#: sfdb_freesound_mootcher.cc:410 rc_option_editor.cc:2276
 msgid "%1"
 msgstr "%1"
 
@@ -6826,7 +7025,7 @@ msgstr "Режим автоматизации фейдера"
 msgid "Fader automation type"
 msgstr "Тип автоматизации фейдера"
 
-#: gain_meter.cc:159 gain_meter.cc:831 panner_ui.cc:177 panner_ui.cc:639
+#: gain_meter.cc:159 gain_meter.cc:831 panner_ui.cc:179 panner_ui.cc:641
 msgid "Abs"
 msgstr "Абс"
 
@@ -6846,48 +7045,48 @@ msgstr "К"
 msgid "W"
 msgstr "З"
 
-#: generic_pluginui.cc:83
+#: generic_pluginui.cc:85
 msgid "<span size=\"large\">Presets</span>"
 msgstr "<span size=\"large\">Профили</span>"
 
-#: generic_pluginui.cc:98
+#: generic_pluginui.cc:100
 msgid "Manual"
 msgstr "Вручную"
 
-#: generic_pluginui.cc:107
+#: generic_pluginui.cc:109
 msgid "All Automation"
 msgstr "Вся автоматизация"
 
-#: generic_pluginui.cc:251
+#: generic_pluginui.cc:253
 msgid "Switches"
 msgstr "Переключатели"
 
-#: generic_pluginui.cc:261 generic_pluginui.cc:437 processor_box.cc:2507
+#: generic_pluginui.cc:263 generic_pluginui.cc:439 processor_box.cc:2817
 msgid "Controls"
 msgstr "Управление"
 
-#: generic_pluginui.cc:294
+#: generic_pluginui.cc:296
 msgid "Plugin Editor: could not build control element for port %1"
 msgstr "Редактор плагинов: невозможно создать управляющий элемент для порта %1"
 
-#: generic_pluginui.cc:319
+#: generic_pluginui.cc:321
 msgid "Plugin Editor: no control for property %1"
 msgstr "Редактор плагинов: нет регулятора для свойства %1"
 
-#: generic_pluginui.cc:325
+#: generic_pluginui.cc:327
 msgid "Plugin Editor: could not build control element for property %1"
 msgstr ""
 "Редаткор плагина: не удалось создать контрольный элемент для свойства %1"
 
-#: generic_pluginui.cc:469
+#: generic_pluginui.cc:471
 msgid "Meters"
 msgstr "Индикаторы уровня"
 
-#: generic_pluginui.cc:491
+#: generic_pluginui.cc:493
 msgid "Automation control"
 msgstr "Контроль автоматизации"
 
-#: generic_pluginui.cc:498
+#: generic_pluginui.cc:500
 msgid "Mgnual"
 msgstr "Mgnual"
 
@@ -6899,8 +7098,8 @@ msgstr "Управление звуковыми соединениями"
 msgid "MIDI Connection Manager"
 msgstr "Управление MIDI-соединениями"
 
-#: global_port_matrix.cc:201 io_selector.cc:211 mixer_strip.cc:826
-#: mixer_strip.cc:927 monitor_section.cc:1279 monitor_selector.cc:189
+#: global_port_matrix.cc:201 io_selector.cc:211 mixer_strip.cc:840
+#: mixer_strip.cc:941 monitor_section.cc:1341 monitor_selector.cc:189
 msgid "Disconnect"
 msgstr "Отсоединить"
 
@@ -6920,47 +7119,47 @@ msgstr "Готовых к записи..."
 msgid "Soloed..."
 msgstr "Солирующих..."
 
-#: group_tabs.cc:320
+#: group_tabs.cc:321
 msgid "Create New Group ..."
 msgstr "Создать группу..."
 
-#: group_tabs.cc:321
+#: group_tabs.cc:324
 msgid "Create New Group From"
 msgstr "Создать группу из"
 
-#: group_tabs.cc:324
+#: group_tabs.cc:327
 msgid "Edit Group..."
 msgstr "Изменить группу..."
 
-#: group_tabs.cc:325
+#: group_tabs.cc:328
 msgid "Collect Group"
 msgstr "Собрать группу"
 
-#: group_tabs.cc:326
+#: group_tabs.cc:329
 msgid "Remove Group"
 msgstr "Удалить группу"
 
-#: group_tabs.cc:329
+#: group_tabs.cc:332
 msgid "Remove Subgroup Bus"
 msgstr "Удалить шину подгруппы"
 
-#: group_tabs.cc:331
+#: group_tabs.cc:334
 msgid "Add New Subgroup Bus"
 msgstr "Добавить новую шину подгруппы"
 
-#: group_tabs.cc:333
+#: group_tabs.cc:336
 msgid "Add New Aux Bus (pre-fader)"
 msgstr "Добавить новую внешнюю шину (до фейдера)"
 
-#: group_tabs.cc:334
+#: group_tabs.cc:337
 msgid "Add New Aux Bus (post-fader)"
 msgstr "Добавить новую внешнюю шину (после фейдера)"
 
-#: group_tabs.cc:340
+#: group_tabs.cc:343
 msgid "Enable All Groups"
 msgstr "Включить все группы"
 
-#: group_tabs.cc:341
+#: group_tabs.cc:344
 msgid "Disable All Groups"
 msgstr "Отключить все группы"
 
@@ -6990,7 +7189,7 @@ msgstr "Разделиться"
 
 #: insert_remove_time_dialog.cc:73
 msgid "Apply to all the track's playlists"
-msgstr ""
+msgstr "Применить ко всем спискам воспроизведения дорожки"
 
 #: insert_remove_time_dialog.cc:76
 msgid "Move glued regions"
@@ -7028,7 +7227,7 @@ msgstr "Вставить"
 msgid "-none-"
 msgstr "-нет-"
 
-#: interthread_progress_window.cc:103
+#: interthread_progress_window.cc:104
 msgid "Importing file: %1 of %2"
 msgstr "Импортируется  файл: %1 из %2"
 
@@ -7044,16 +7243,16 @@ msgstr "%1 вход"
 msgid "%1 output"
 msgstr "%1 выход"
 
-#: keyboard.cc:78
+#: keyboard.cc:82
 msgid "your own"
 msgstr "Ваш собс."
 
-#: keyboard.cc:141 keyboard.cc:165
+#: keyboard.cc:145 keyboard.cc:169
 msgid "Default keybindings not found - %1 will be hard to use!"
 msgstr ""
 "Конфигурация комбинаций клавиш недоступна - работать с %1 будет непросто!"
 
-#: keyboard.cc:144
+#: keyboard.cc:148
 msgid "Key bindings file \"%1\" not found. Default bindings used instead"
 msgstr "Файл привязки клавиш \"%1\" не найден. Исп. привязки по умолчанию"
 
@@ -7112,103 +7311,103 @@ msgstr[0] "%1 сэмпл"
 msgstr[1] "%1 сэмпла"
 msgstr[2] "%1 сэмплов"
 
-#: latency_gui.cc:72 panner_ui.cc:409 plugin_ui.cc:421
+#: latency_gui.cc:72 panner_ui.cc:411 plugin_ui.cc:421
 msgid "Reset"
 msgstr "Сбросить"
 
-#: latency_gui.cc:149 rhythm_ferret.cc:273 sfdb_ui.cc:1911
+#: latency_gui.cc:149 rhythm_ferret.cc:273 sfdb_ui.cc:1909
 msgid "programming error: %1 (%2)"
 msgstr "Ошибка в программе: %1 (%2)"
 
-#: location_ui.cc:52 location_ui.cc:54
+#: location_ui.cc:54 location_ui.cc:56
 msgid "Use PH"
 msgstr "По указателю"
 
-#: location_ui.cc:59
+#: location_ui.cc:61
 msgid "Glue"
 msgstr "Приклеить"
 
-#: location_ui.cc:87
+#: location_ui.cc:89
 msgid "Performer:"
 msgstr "Исполнитель:"
 
-#: location_ui.cc:88
+#: location_ui.cc:90
 msgid "Composer:"
 msgstr "Композитор:"
 
-#: location_ui.cc:90
+#: location_ui.cc:92
 msgid "Pre-Emphasis"
 msgstr "Пред. акцент"
 
-#: location_ui.cc:317
+#: location_ui.cc:319
 msgid "Remove this range"
 msgstr "Удалить эту область"
 
-#: location_ui.cc:318
+#: location_ui.cc:320
 msgid "Start time - middle click to locate here"
 msgstr "Время начала - средний клик, чтобы разместить здесь"
 
-#: location_ui.cc:319
+#: location_ui.cc:321
 msgid "End time - middle click to locate here"
 msgstr "Время окончания - средний клик, чтобы разместить здесь"
 
-#: location_ui.cc:322
+#: location_ui.cc:324
 msgid "Set range start from playhead location"
 msgstr "Установить начало диапазона по указателю воспроизведения"
 
-#: location_ui.cc:323
+#: location_ui.cc:325
 msgid "Set range end from playhead location"
 msgstr "Установить конец диапазона по указателю воспроизведения"
 
-#: location_ui.cc:327
+#: location_ui.cc:329
 msgid "Remove this marker"
 msgstr "Удалить этот маркер"
 
-#: location_ui.cc:328
+#: location_ui.cc:330
 msgid "Position - middle click to locate here"
 msgstr "Позиция - средний клик, чтобы разместить здесь"
 
-#: location_ui.cc:330
+#: location_ui.cc:332
 msgid "Set marker time from playhead location"
 msgstr "Установить маркер времени по месту воспроизведения"
 
-#: location_ui.cc:499
+#: location_ui.cc:501
 msgid "You cannot put a CD marker at the start of the session"
 msgstr "Размещение маркера CD в начале сессии невозможно"
 
-#: location_ui.cc:725
+#: location_ui.cc:727
 msgid "New Marker"
 msgstr "Создать маркер"
 
-#: location_ui.cc:726
+#: location_ui.cc:728
 msgid "New Range"
 msgstr "Создать диапазон"
 
-#: location_ui.cc:739
+#: location_ui.cc:741
 msgid "<b>Loop/Punch Ranges</b>"
 msgstr "<b>Диапазоны петель/врезок</b>"
 
-#: location_ui.cc:764
+#: location_ui.cc:766
 msgid "<b>Markers (Including CD Index)</b>"
 msgstr "<b>Маркеры (включая индекс CD)</b>"
 
-#: location_ui.cc:799
+#: location_ui.cc:801
 msgid "<b>Ranges (Including CD Track Ranges)</b>"
 msgstr "<b>Диапазоны (включая диапазоны дорожек CD)</b>"
 
-#: location_ui.cc:1042
+#: location_ui.cc:1044
 msgid "add range marker"
 msgstr "Добавка маркера выделения"
 
-#: main.cc:82
+#: main.cc:86
 msgid "%1 could not connect to the audio backend."
 msgstr "%1 не удалось соединиться со звуковой подсистемой."
 
-#: main.cc:129 main.cc:145
+#: main.cc:133 main.cc:149
 msgid "The audio backend (%1) has failed, or terminated"
 msgstr "Ошибка аудиодвижка (%1), либо он был остановлен"
 
-#: main.cc:132
+#: main.cc:136
 msgid ""
 "%2 exited unexpectedly, and without notifying %1.\n"
 "\n"
@@ -7223,11 +7422,11 @@ msgstr ""
 "\n"
 "Нажмите OK, чтобы выйти из %1."
 
-#: main.cc:146
+#: main.cc:150
 msgid "%2 exited unexpectedly, and without notifying %1."
 msgstr "%2 вышел неожиданно и без уведомления %1."
 
-#: main.cc:241
+#: main.cc:245
 msgid ""
 "\n"
 "   %1 could not understand your command line      "
@@ -7235,23 +7434,23 @@ msgstr ""
 "\n"
 "   %1 не удалось разобрать переданные вами аргументы командной строки      "
 
-#: main.cc:243
+#: main.cc:247
 msgid "An error was encountered while launching %1"
 msgstr "Произошла ошибка при запуске %1"
 
-#: main.cc:332
+#: main.cc:340
 msgid " (built using "
 msgstr " (собран, используя "
 
-#: main.cc:335
+#: main.cc:343
 msgid " and GCC version "
 msgstr ", при помощи GCC версии "
 
-#: main.cc:345
+#: main.cc:353
 msgid "Copyright (C) 1999-2015 Paul Davis"
 msgstr "Авторские права (C) 1999-2015 Paul Davis"
 
-#: main.cc:346
+#: main.cc:354
 msgid ""
 "Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
 "Baker, Robin Gareus"
@@ -7259,65 +7458,65 @@ msgstr ""
 "Частичные авторские права © Steve Harris, Ari Johnson, Brett Viren, Joel "
 "Baker, Robin Gareus"
 
-#: main.cc:348
+#: main.cc:356
 msgid "%1 comes with ABSOLUTELY NO WARRANTY"
 msgstr "%1 распространяется БЕЗО ВСЯКИХ ГАРАНТИЙ"
 
-#: main.cc:349
+#: main.cc:357
 msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 msgstr "Даже не для КОММЕРЦИИ или ПРИГОДНОСТИ К КОНКРЕТНЫМ ЦЕЛЯМ."
 
-#: main.cc:350
+#: main.cc:358
 msgid "This is free software, and you are welcome to redistribute it "
 msgstr "Это свободное программное обеспечение, Вы можете распространять его"
 
-#: main.cc:351
+#: main.cc:359
 msgid "under certain conditions; see the source for copying conditions."
 msgstr "На определённых условиях; подробнее об этом читайте в файле COPYING."
 
-#: main.cc:356
+#: main.cc:364
 msgid "could not initialize %1."
 msgstr "Не удалось инициализировать %1."
 
-#: main.cc:366
+#: main.cc:374
 msgid "Cannot xinstall SIGPIPE error handler"
 msgstr "Сбой установки обработчика ошибок SIGPIPE"
 
-#: main.cc:373
+#: main.cc:379
 msgid "Could not complete pre-GUI initialization"
 msgstr ""
 
-#: main.cc:380
+#: main.cc:386
 msgid "could not create %1 GUI"
 msgstr "Не удалось создать графический интерфейс для %1"
 
-#: main_clock.cc:50
+#: main_clock.cc:51
 msgid "Display delta to edit cursor"
 msgstr "Показывать разницу с курсором редактора"
 
-#: main_clock.cc:65 tempo_dialog.cc:54
+#: main_clock.cc:66 tempo_dialog.cc:54
 msgid "Edit Tempo"
 msgstr "Изменить темп"
 
-#: main_clock.cc:66 tempo_dialog.cc:326
+#: main_clock.cc:67 tempo_dialog.cc:326
 msgid "Edit Meter"
 msgstr "Изменить размер"
 
-#: main_clock.cc:67
+#: main_clock.cc:68
 msgid "Insert Tempo Change"
 msgstr "Вставить новый темп"
 
-#: main_clock.cc:68
+#: main_clock.cc:69
 msgid "Insert Meter Change"
 msgstr "Вставить новый размер"
 
-#: marker.cc:276
+#: marker.cc:280
 msgid "MarkerText"
 msgstr ""
 
 #: midi_channel_selector.cc:161 midi_channel_selector.cc:400
-#: midi_channel_selector.cc:436 rc_option_editor.cc:2044
-#: rc_option_editor.cc:2677 sfdb_ui.cc:664
+#: midi_channel_selector.cc:436 rc_option_editor.cc:2017
+#: rc_option_editor.cc:2663 sfdb_ui.cc:670
 msgid "None"
 msgstr "Нет"
 
@@ -7398,11 +7597,11 @@ msgstr "Нажмите, чтобы переключить воспроизвед
 msgid "Click to force all MIDI channel messages to channel %1"
 msgstr "Нажмите для принуд. вывода сообщений MIDI канала на канал %1"
 
-#: midi_channel_selector.cc:718
+#: midi_channel_selector.cc:720
 msgid "Click to toggle recording of channel %1"
 msgstr "Нажмите, чтобы переключить запись на канал %1"
 
-#: midi_channel_selector.cc:726
+#: midi_channel_selector.cc:728
 msgid "Click to force all recorded channels to %1"
 msgstr "Нажмите для принуд. записи всех каналов в %1"
 
@@ -7506,200 +7705,200 @@ msgstr "Название порта:"
 msgid "MidiPortDialog"
 msgstr "MidiPortDialog"
 
-#: midi_region_view.cc:863
+#: midi_region_view.cc:849
 msgid "channel edit"
 msgstr "Правка канала"
 
-#: midi_region_view.cc:899
+#: midi_region_view.cc:885
 msgid "velocity edit"
 msgstr "Правка силы нажатия"
 
-#: midi_region_view.cc:958
+#: midi_region_view.cc:944
 msgid "add note"
 msgstr "Добавка ноты"
 
-#: midi_region_view.cc:1890
+#: midi_region_view.cc:1872
 msgid "step add"
 msgstr "Добавить шаг"
 
-#: midi_region_view.cc:1984 midi_region_view.cc:2007
+#: midi_region_view.cc:1966 midi_region_view.cc:1989
 msgid "alter patch change"
 msgstr "Смена изменения патча"
 
-#: midi_region_view.cc:2043
+#: midi_region_view.cc:2025
 msgid "add patch change"
 msgstr "Добавка смены программы"
 
-#: midi_region_view.cc:2065 midi_region_view.cc:2066
+#: midi_region_view.cc:2047 midi_region_view.cc:2048
 msgid "move patch change"
 msgstr "Перемещение смены программы"
 
-#: midi_region_view.cc:2078 midi_region_view.cc:2079
+#: midi_region_view.cc:2060 midi_region_view.cc:2061
 msgid "delete patch change"
 msgstr "Удаление смены программы"
 
-#: midi_region_view.cc:2117
+#: midi_region_view.cc:2099
 msgid "delete selection"
 msgstr "Удаление выделения"
 
-#: midi_region_view.cc:2133
+#: midi_region_view.cc:2116
 msgid "delete note"
 msgstr "Удаление ноты"
 
-#: midi_region_view.cc:2592
+#: midi_region_view.cc:2575
 msgid "move notes"
 msgstr "Перемещение ноты"
 
-#: midi_region_view.cc:3123
+#: midi_region_view.cc:3110
 msgid "change velocities"
 msgstr "Смена силы нажатия"
 
-#: midi_region_view.cc:3189
+#: midi_region_view.cc:3176
 msgid "transpose"
 msgstr "Транспозиция"
 
-#: midi_region_view.cc:3217
+#: midi_region_view.cc:3204
 msgid "change note lengths"
 msgstr "Смена длительности нот"
 
-#: midi_region_view.cc:3293
+#: midi_region_view.cc:3280
 msgid "nudge"
 msgstr "Толчок"
 
-#: midi_region_view.cc:3308
+#: midi_region_view.cc:3295
 msgid "change channel"
 msgstr "Смена канала"
 
-#: midi_region_view.cc:3348
+#: midi_region_view.cc:3333
 msgid "Bank "
 msgstr "Банк"
 
-#: midi_region_view.cc:3349
+#: midi_region_view.cc:3334
 msgid "Program "
 msgstr "Программа"
 
-#: midi_region_view.cc:3350
+#: midi_region_view.cc:3335
 msgid "Channel "
 msgstr "Канал"
 
-#: midi_region_view.cc:3537
+#: midi_region_view.cc:3522
 msgid "paste"
 msgstr "Вставка"
 
-#: midi_streamview.cc:185
+#: midi_streamview.cc:184
 msgid "attempt to display MIDI region with no source"
 msgstr "пытаться показать MIDI-область без источника"
 
-#: midi_streamview.cc:195
+#: midi_streamview.cc:194
 msgid "attempt to display MIDI region with no model"
 msgstr "пытаться показать MIDI-область без модели"
 
-#: midi_streamview.cc:506
+#: midi_streamview.cc:505
 msgid "failed to create MIDI region"
 msgstr "Не удалось создать MIDI-область"
 
-#: midi_time_axis.cc:309
+#: midi_time_axis.cc:316
 msgid "External MIDI Device"
 msgstr "Внешнее MIDI-устройство"
 
-#: midi_time_axis.cc:310
+#: midi_time_axis.cc:317
 msgid "External Device Mode"
 msgstr "Режим внешнего устройства"
 
-#: midi_time_axis.cc:318
+#: midi_time_axis.cc:325
 msgid "Chns"
 msgstr "Кнл"
 
-#: midi_time_axis.cc:320
+#: midi_time_axis.cc:327
 msgid "Click to edit channel settings"
 msgstr "Щёлкните для изменения параметров каналов"
 
-#: midi_time_axis.cc:519
+#: midi_time_axis.cc:526
 msgid "Show Full Range"
 msgstr "Показать все октавы"
 
-#: midi_time_axis.cc:524
+#: midi_time_axis.cc:531
 msgid "Fit Contents"
 msgstr "Уместить содержимое"
 
-#: midi_time_axis.cc:528
+#: midi_time_axis.cc:535
 msgid "Note Range"
 msgstr "Нотный диапазон"
 
-#: midi_time_axis.cc:529
+#: midi_time_axis.cc:536
 msgid "Note Mode"
 msgstr "Режим представления нот"
 
-#: midi_time_axis.cc:530
+#: midi_time_axis.cc:537
 msgid "Channel Selector"
 msgstr "Выбор каналов"
 
-#: midi_time_axis.cc:535
+#: midi_time_axis.cc:542
 msgid "Color Mode"
 msgstr "Режим раскрашивания"
 
-#: midi_time_axis.cc:594
+#: midi_time_axis.cc:601
 msgid "Bender"
 msgstr "Высота тона"
 
-#: midi_time_axis.cc:598
+#: midi_time_axis.cc:605
 msgid "Pressure"
 msgstr "Сила нажатия"
 
-#: midi_time_axis.cc:610
+#: midi_time_axis.cc:617
 msgid "Controllers"
 msgstr "Контроллеры"
 
-#: midi_time_axis.cc:615
+#: midi_time_axis.cc:622
 msgid "No MIDI Channels selected"
 msgstr "Нет выбранных каналов MIDI"
 
-#: midi_time_axis.cc:672 midi_time_axis.cc:801
+#: midi_time_axis.cc:679 midi_time_axis.cc:808
 msgid "Hide all channels"
 msgstr "Скрыть все каналы"
 
-#: midi_time_axis.cc:676 midi_time_axis.cc:805
+#: midi_time_axis.cc:683 midi_time_axis.cc:812
 msgid "Show all channels"
 msgstr "Показать все каналы"
 
-#: midi_time_axis.cc:687 midi_time_axis.cc:816
+#: midi_time_axis.cc:694 midi_time_axis.cc:823
 msgid "Channel %1"
 msgstr "Канал %1"
 
-#: midi_time_axis.cc:942 midi_time_axis.cc:974
+#: midi_time_axis.cc:949 midi_time_axis.cc:981
 msgid "Controllers %1-%2"
 msgstr "Контроллеры %1-%2"
 
-#: midi_time_axis.cc:965 midi_time_axis.cc:968
+#: midi_time_axis.cc:972 midi_time_axis.cc:975
 msgid "Controller %1"
 msgstr "Контроллер %1"
 
-#: midi_time_axis.cc:991
+#: midi_time_axis.cc:998
 msgid "Sustained"
 msgstr "Хроматические"
 
-#: midi_time_axis.cc:998
+#: midi_time_axis.cc:1005
 msgid "Percussive"
 msgstr "Перкуссия"
 
-#: midi_time_axis.cc:1018
+#: midi_time_axis.cc:1025
 msgid "Meter Colors"
 msgstr "Цвета силы нажатия"
 
-#: midi_time_axis.cc:1025
+#: midi_time_axis.cc:1032
 msgid "Channel Colors"
 msgstr "Цвета канала"
 
-#: midi_time_axis.cc:1032
+#: midi_time_axis.cc:1039
 msgid "Track Color"
 msgstr "Цвет дорожки"
 
-#: midi_time_axis.cc:1607 midi_time_axis.cc:1613 midi_time_axis.cc:1623
-#: midi_time_axis.cc:1629
+#: midi_time_axis.cc:1614 midi_time_axis.cc:1620 midi_time_axis.cc:1630
+#: midi_time_axis.cc:1636
 msgid "all"
 msgstr "Все"
 
-#: midi_time_axis.cc:1610 midi_time_axis.cc:1626
+#: midi_time_axis.cc:1617 midi_time_axis.cc:1633
 msgid "some"
 msgstr "Не все"
 
@@ -7715,7 +7914,7 @@ msgstr "Автопрокрутка"
 msgid "Decimal"
 msgstr "Десятичный"
 
-#: midi_tracer.cc:57 rc_option_editor.cc:1191
+#: midi_tracer.cc:57 rc_option_editor.cc:1355
 msgid "Enabled"
 msgstr "Включено"
 
@@ -7731,35 +7930,35 @@ msgstr "Порт:"
 msgid "New velocity"
 msgstr "Новая сила нажатия"
 
-#: missing_file_dialog.cc:35
+#: missing_file_dialog.cc:36
 msgid "Missing File"
 msgstr "Отсутствует файл"
 
-#: missing_file_dialog.cc:37
+#: missing_file_dialog.cc:38
 msgid "Select a folder to search"
 msgstr "Выберите папку для поиска"
 
-#: missing_file_dialog.cc:38
+#: missing_file_dialog.cc:39
 msgid "Add chosen folder to search path, and try again"
 msgstr "Добавить выбранную папку в путь поиска и попробовать снова"
 
-#: missing_file_dialog.cc:40
+#: missing_file_dialog.cc:41
 msgid "Stop loading this session"
 msgstr "Прекратить загрузку этой сессии"
 
-#: missing_file_dialog.cc:41
+#: missing_file_dialog.cc:42
 msgid "Skip all missing files"
 msgstr "Пропустить все отсутствующие файлы"
 
-#: missing_file_dialog.cc:42
+#: missing_file_dialog.cc:43
 msgid "Skip this file"
 msgstr "Пропустить этот файл"
 
-#: missing_file_dialog.cc:53
+#: missing_file_dialog.cc:57
 msgid "audio"
 msgstr "Звуковой"
 
-#: missing_file_dialog.cc:70
+#: missing_file_dialog.cc:74
 msgid ""
 "%1 cannot find the %2 file\n"
 "\n"
@@ -7779,7 +7978,7 @@ msgstr ""
 "<tt>%3</tt>\n"
 "\n"
 
-#: missing_file_dialog.cc:104
+#: missing_file_dialog.cc:108
 msgid "Click to choose an additional folder"
 msgstr "Выберите дополнительную папку:"
 
@@ -7787,7 +7986,7 @@ msgstr "Выберите дополнительную папку:"
 msgid "Missing Plugins"
 msgstr "Отсутствующие плагины"
 
-#: missing_plugin_dialog.cc:33 transcode_video_dialog.cc:60
+#: missing_plugin_dialog.cc:36 transcode_video_dialog.cc:60
 msgid "OK"
 msgstr "ОК"
 
@@ -7863,20 +8062,20 @@ msgstr "Загруженные привязки микшера от %1"
 msgid "Could not find mixer.bindings in search path %1"
 msgstr "Не удалось найти привязки микшера в пути поиска %1"
 
-#: mixer_strip.cc:97 mixer_strip.cc:127
+#: mixer_strip.cc:98 mixer_strip.cc:129
 msgid "pre"
 msgstr "До"
 
-#: mixer_strip.cc:99 mixer_strip.cc:129 mixer_strip.cc:384 mixer_strip.cc:1456
-#: rc_option_editor.cc:2833
+#: mixer_strip.cc:101 mixer_strip.cc:132 mixer_strip.cc:387 mixer_strip.cc:1470
+#: rc_option_editor.cc:2949
 msgid "Comments"
 msgstr "Комментарии"
 
-#: mixer_strip.cc:152
+#: mixer_strip.cc:155
 msgid "Click to toggle the width of this mixer strip."
 msgstr "Щёлкните для переключения ширины полоски микшера"
 
-#: mixer_strip.cc:154
+#: mixer_strip.cc:157
 msgid ""
 "\n"
 "%1-%2-click to toggle the width of all strips."
@@ -7884,257 +8083,305 @@ msgstr ""
 "\n"
 "%1-%2-щелчок для изменения ширины всех полос."
 
-#: mixer_strip.cc:161
+#: mixer_strip.cc:164
 msgid "Hide this mixer strip"
 msgstr "Скрыть полоску микшера"
 
-#: mixer_strip.cc:172
+#: mixer_strip.cc:175
 msgid "Click to select metering point"
 msgstr "Щёлкните для выбора точки замера"
 
-#: mixer_strip.cc:188
+#: mixer_strip.cc:191
 msgid "Isolate Solo"
 msgstr "Изолировать соло"
 
-#: mixer_strip.cc:196
+#: mixer_strip.cc:199
 msgid "Lock Solo Status"
 msgstr "Статус блокировки солирования"
 
-#: mixer_strip.cc:198 mixer_strip.cc:2090
+#: mixer_strip.cc:201 mixer_strip.cc:2113
 msgid "SoloLock|Lock"
 msgstr "Блок"
 
-#: mixer_strip.cc:199 mixer_strip.cc:2089
+#: mixer_strip.cc:202 mixer_strip.cc:2112
 msgid "Iso"
 msgstr "Изо."
 
-#: mixer_strip.cc:253
+#: mixer_strip.cc:256
 msgid "Mix group"
 msgstr "Группа микса"
 
-#: mixer_strip.cc:263
+#: mixer_strip.cc:266
 msgid "Trim: "
 msgstr "Усиление: "
 
-#: mixer_strip.cc:380 rc_option_editor.cc:2829
+#: mixer_strip.cc:383 rc_option_editor.cc:2945
 msgid "Phase Invert"
 msgstr "Инверсия фазы"
 
-#: mixer_strip.cc:381 rc_option_editor.cc:2830
+#: mixer_strip.cc:384 rc_option_editor.cc:2946
 msgid "Record & Monitor"
 msgstr "Запись и монитор"
 
-#: mixer_strip.cc:382 rc_option_editor.cc:2831
+#: mixer_strip.cc:385 rc_option_editor.cc:2947
 msgid "Solo Iso / Lock"
 msgstr "Соло Iso / Блок"
 
-#: mixer_strip.cc:546
+#: mixer_strip.cc:507
+msgid "Show/Hide Monitoring Section"
+msgstr "Показать или скрыть панель мониторинга"
+
+#: mixer_strip.cc:559
 msgid "Enable/Disable MIDI input"
 msgstr "Включить или выключить MIDI-вход"
 
-#: mixer_strip.cc:712
+#: mixer_strip.cc:726
 msgid "Aux"
 msgstr "Ð’Ñ‹Ñ…"
 
-#: mixer_strip.cc:738
+#: mixer_strip.cc:752
 msgid "Snd"
 msgstr "Псл"
 
-#: mixer_strip.cc:809 mixer_strip.cc:912 processor_box.cc:2449
+#: mixer_strip.cc:823 mixer_strip.cc:926 processor_box.cc:2759
 msgid "Not connected to audio engine - no I/O changes are possible"
 msgstr ""
 "Нет соединения со звуковой подсистемой, любые изменения входа-выхода "
 "невозможны."
 
-#: mixer_strip.cc:866 mixer_strip.cc:968
+#: mixer_strip.cc:880 mixer_strip.cc:982
 msgid "Add %1 port"
 msgstr "Добавить %1-порт"
 
-#: mixer_strip.cc:873 mixer_strip.cc:975 monitor_section.cc:1315
+#: mixer_strip.cc:887 mixer_strip.cc:989 monitor_section.cc:1377
 msgid "Routing Grid"
 msgstr "Матрица маршрутизации"
 
-#: mixer_strip.cc:1204
+#: mixer_strip.cc:1218
 msgid "MIDI "
 msgstr "MIDI "
 
-#: mixer_strip.cc:1209
+#: mixer_strip.cc:1223
 msgid "<b>INPUT</b> to %1"
 msgstr "<b>ВХОД</b> в %1"
 
-#: mixer_strip.cc:1212 monitor_section.cc:1366
+#: mixer_strip.cc:1226 monitor_section.cc:1422
 msgid "<b>OUTPUT</b> from %1"
 msgstr "<b>ВЫХОД</b> из %1"
 
-#: mixer_strip.cc:1330 monitor_section.cc:1453
+#: mixer_strip.cc:1344 monitor_section.cc:1509
 msgid "Disconnected"
 msgstr "Нет соединения"
 
-#: mixer_strip.cc:1459
+#: mixer_strip.cc:1473
 msgid "*Comments*"
 msgstr "*Кмт*"
 
-#: mixer_strip.cc:1466
+#: mixer_strip.cc:1480
 msgid "Cmt"
 msgstr "Кмт"
 
-#: mixer_strip.cc:1469
+#: mixer_strip.cc:1483
 msgid "*Cmt*"
 msgstr "*Кмт*"
 
-#: mixer_strip.cc:1475
-msgid "Click to Add/Edit Comments"
-msgstr "Нажмите для добавления/правки комментариев"
+#: mixer_strip.cc:1489
+msgid "Click to add/edit comments"
+msgstr "Щёлкните, чтобы добавить или изменить комментарий"
 
-#: mixer_strip.cc:1519
+#: mixer_strip.cc:1533
 msgid "Grp"
 msgstr "Грп"
 
-#: mixer_strip.cc:1522
+#: mixer_strip.cc:1536
 msgid "~G"
 msgstr "нГр"
 
-#: mixer_strip.cc:1551 route_time_axis.cc:572
+#: mixer_strip.cc:1565 route_time_axis.cc:573
 msgid "Color..."
 msgstr "Цвет..."
 
-#: mixer_strip.cc:1553 route_time_axis.cc:574
+#: mixer_strip.cc:1567 route_time_axis.cc:575
 msgid "Comments..."
 msgstr "Комментарии..."
 
-#: mixer_strip.cc:1555 route_time_axis.cc:576
+#: mixer_strip.cc:1569 route_time_axis.cc:577
 msgid "Inputs..."
 msgstr "Входы..."
 
-#: mixer_strip.cc:1557 route_time_axis.cc:578
+#: mixer_strip.cc:1571 route_time_axis.cc:579
 msgid "Outputs..."
 msgstr "Выходы..."
 
-#: mixer_strip.cc:1562
+#: mixer_strip.cc:1576
 msgid "Save As Template..."
 msgstr "Сохранить как шаблон..."
 
-#: mixer_strip.cc:1568 route_group_dialog.cc:45 route_time_axis.cc:852
+#: mixer_strip.cc:1582 route_group_dialog.cc:45 route_time_axis.cc:853
 msgid "Active"
 msgstr "Активно"
 
-#: mixer_strip.cc:1576
+#: mixer_strip.cc:1590
 msgid "Adjust Latency..."
 msgstr "Скорректировать задержку..."
 
-#: mixer_strip.cc:1579
+#: mixer_strip.cc:1593
 msgid "Protect Against Denormals"
 msgstr "Защищать от отклонений"
 
-#: mixer_strip.cc:1585 route_time_axis.cc:591
+#: mixer_strip.cc:1599 route_time_axis.cc:592
 msgid "Remote Control ID..."
 msgstr "ID для удалённого управления..."
 
-#: mixer_strip.cc:1885
+#: mixer_strip.cc:1617 route_time_axis.cc:869
+msgid "Duplicate..."
+msgstr "Продублировать..."
+
+#: mixer_strip.cc:1905
 msgid "Pre"
 msgstr "До"
 
-#: mixer_strip.cc:1889
+#: mixer_strip.cc:1909
 msgid "Post"
 msgstr "После"
 
-#: mixer_strip.cc:1905
+#: mixer_strip.cc:1925
 msgid "Meter|In"
 msgstr "Ð’Ñ…"
 
-#: mixer_strip.cc:1909
+#: mixer_strip.cc:1929
 msgid "Meter|Pr"
 msgstr "Прд"
 
-#: mixer_strip.cc:1913
+#: mixer_strip.cc:1933
 msgid "Meter|Po"
 msgstr "Псл"
 
-#: mixer_strip.cc:1917
+#: mixer_strip.cc:1937
 msgid "Meter|O"
 msgstr "Ð’Ñ‹Ñ…"
 
-#: mixer_strip.cc:1922
+#: mixer_strip.cc:1942
 msgid "Meter|C"
 msgstr "З"
 
-#: mixer_strip.cc:2070 route_ui.cc:170
+#: mixer_strip.cc:2090 route_ui.cc:181
 msgid "Disk"
 msgstr "Диск"
 
-#: mixer_strip.cc:2082 monitor_section.cc:76
+#: mixer_strip.cc:2092
+msgid "Mon"
+msgstr ""
+
+#: mixer_strip.cc:2105 monitor_section.cc:81
 msgid "AFL"
 msgstr "AFL"
 
-#: mixer_strip.cc:2085 monitor_section.cc:77
+#: mixer_strip.cc:2108 monitor_section.cc:82
 msgid "PFL"
 msgstr "PFL"
 
-#: mixer_strip.cc:2095 meter_strip.cc:387
+#: mixer_strip.cc:2118 meter_strip.cc:387
 msgid "MonitorInput|I"
 msgstr "Ð’Ñ…"
 
-#: mixer_strip.cc:2096 meter_strip.cc:388
+#: mixer_strip.cc:2119 meter_strip.cc:388
 msgid "MonitorDisk|D"
 msgstr "Д"
 
-#: mixer_strip.cc:2108 meter_strip.cc:379 route_time_axis.cc:2729
+#: mixer_strip.cc:2121
+msgid "Mon|O"
+msgstr ""
+
+#: mixer_strip.cc:2134 meter_strip.cc:379 route_time_axis.cc:2738
 msgid "AfterFader|A"
 msgstr "П"
 
-#: mixer_strip.cc:2111
+#: mixer_strip.cc:2137
 msgid "Prefader|P"
 msgstr "Д"
 
-#: mixer_strip.cc:2116
+#: mixer_strip.cc:2142
 msgid "SoloIso|I"
 msgstr "И"
 
-#: mixer_strip.cc:2117
+#: mixer_strip.cc:2143
 msgid "SoloLock|L"
 msgstr "Б"
 
-#: mixer_strip.cc:2303
+#: mixer_strip.cc:2348
 msgid "Pre Fader"
 msgstr "Предфейдер"
 
-#: mixer_strip.cc:2304
+#: mixer_strip.cc:2349
 msgid "Post Fader"
 msgstr "Послефейдер"
 
-#: mixer_strip.cc:2349 meter_strip.cc:860
+#: mixer_strip.cc:2394 meter_strip.cc:860
 msgid "Change all in Group to %1"
 msgstr "Поменять все в группе на %1"
 
-#: mixer_strip.cc:2351 meter_strip.cc:862
+#: mixer_strip.cc:2396 meter_strip.cc:862
 msgid "Change all to %1"
 msgstr "Поменять все на %1"
 
-#: mixer_strip.cc:2353 meter_strip.cc:864
+#: mixer_strip.cc:2398 meter_strip.cc:864
 msgid "Change same track-type to %1"
 msgstr "Поменять дорожки одного типа на %1"
 
-#: mixer_ui.cc:130 route_time_axis.cc:829
+#: mixer_ui.cc:134 route_time_axis.cc:830
 msgid "Group"
 msgstr "Группа"
 
-#: mixer_ui.cc:1242
+#: mixer_ui.cc:199
+msgid "Favorite Plugins"
+msgstr "Избранные плагины"
+
+#: mixer_ui.cc:1288
 msgid "track display list item for renamed strip not found!"
 msgstr "Элемент списка для переименованного канала микшера не найден!"
 
-#: mixer_ui.cc:1336
+#: mixer_ui.cc:1382
 msgid "-all-"
 msgstr "-все-"
 
-#: mixer_ui.cc:1873
+#: mixer_ui.cc:2039
 msgid "Strips"
 msgstr "Каналы"
 
+#: mixer_ui.cc:2346
+msgid "No Track/Bus is selected."
+msgstr ""
+
+#: mixer_ui.cc:2348
+msgid "Add at the top"
+msgstr "Добавить в начало"
+
+#: mixer_ui.cc:2350
+msgid "Add Pre-Fader"
+msgstr "Добавить перед фейдером"
+
+#: mixer_ui.cc:2352
+msgid "Add Post-Fader"
+msgstr "Добавить после фейдера"
+
+#: mixer_ui.cc:2354
+msgid "Add at the end"
+msgstr "Добавить в конец"
+
+#: mixer_ui.cc:2360
+msgid "Remove from favorites"
+msgstr "Удалить из избранных"
+
+#: mixer_ui.cc:2364
+msgid "Delete Preset"
+msgstr "Удалить предустановку"
+
 #: meter_strip.cc:161
 msgid "Reset Peak"
 msgstr "Сброс пик"
 
-#: meter_strip.cc:382 route_time_axis.cc:2733
+#: meter_strip.cc:382 route_time_axis.cc:2742
 msgid "PreFader|P"
 msgstr "Д"
 
@@ -8158,67 +8405,67 @@ msgstr "Grande"
 msgid "Venti"
 msgstr "Venti"
 
-#: meter_patterns.cc:82
+#: meter_patterns.cc:84
 msgid "Peak (+6dBFS)"
-msgstr ""
+msgstr "Пик (+6dBFS)"
 
-#: meter_patterns.cc:85
+#: meter_patterns.cc:87
 msgid "Peak (0dBFS)"
-msgstr ""
+msgstr "Пик (0dBFS)"
 
-#: meter_patterns.cc:88
+#: meter_patterns.cc:90
 msgid "RMS + Peak"
 msgstr "Среднеквадратичное + пиковое значение"
 
-#: meter_patterns.cc:91
+#: meter_patterns.cc:93
 msgid "IEC1/DIN"
 msgstr "IEC1/DIN"
 
-#: meter_patterns.cc:94
+#: meter_patterns.cc:96
 msgid "IEC1/Nordic"
 msgstr "IEC1/Nordic"
 
-#: meter_patterns.cc:97
+#: meter_patterns.cc:99
 msgid "IEC2/BBC"
 msgstr "IEC2/BBC"
 
-#: meter_patterns.cc:100
+#: meter_patterns.cc:102
 msgid "IEC2/EBU"
 msgstr "IEC2/EBU"
 
-#: meter_patterns.cc:103
+#: meter_patterns.cc:105
 msgid "K20/RMS"
 msgstr "K20/RMS"
 
-#: meter_patterns.cc:106
+#: meter_patterns.cc:108
 msgid "K14/RMS"
 msgstr "K14/RMS"
 
-#: meter_patterns.cc:109
+#: meter_patterns.cc:111
 msgid "K12/RMS"
 msgstr "K12/RMS"
 
-#: meter_patterns.cc:112
+#: meter_patterns.cc:114
 msgid "VU"
 msgstr "VU"
 
-#: monitor_section.cc:75
+#: monitor_section.cc:80
 msgid "SiP"
 msgstr "SiP"
 
-#: monitor_section.cc:102 route_group_dialog.cc:49
+#: monitor_section.cc:111 route_group_dialog.cc:49
 msgid "Soloing"
 msgstr "Солирование"
 
-#: monitor_section.cc:106
+#: monitor_section.cc:115
 msgid "Isolated"
 msgstr "Изолировано"
 
-#: monitor_section.cc:110
+#: monitor_section.cc:119
 msgid "Auditioning"
 msgstr "Прослушивание"
 
-#: monitor_section.cc:120
+#: monitor_section.cc:130
 msgid ""
 "When active, something is solo-isolated.\n"
 "Click to de-isolate everything"
@@ -8226,7 +8473,7 @@ msgstr ""
 "Если активно, то что-то будет соло-изолировано.\n"
 "Нажмите, чтобы де-изолировать все"
 
-#: monitor_section.cc:123
+#: monitor_section.cc:133
 msgid ""
 "When active, auditioning is active.\n"
 "Click to stop the audition"
@@ -8234,44 +8481,72 @@ msgstr ""
 "Если включено, выполняется прослушивание.\n"
 "Щёлкните, чтобы прекратить его."
 
-#: monitor_section.cc:140
+#: monitor_section.cc:150
 msgid "Solo controls affect solo-in-place"
 msgstr "Управление солированием затрагивает солирование на месте"
 
-#: monitor_section.cc:146
+#: monitor_section.cc:156
 msgid "Solo controls toggle after-fader-listen"
 msgstr "Управление солированием переключает послефейдерное прослушивание"
 
-#: monitor_section.cc:152
+#: monitor_section.cc:162
 msgid "Solo controls toggle pre-fader-listen"
 msgstr "Управление солированием переключает предфейдерное прослушивание"
 
-#: monitor_section.cc:162
+#: monitor_section.cc:168
+msgid "Excl. Solo"
+msgstr "Экскл. соло"
+
+#: monitor_section.cc:170
+msgid "Exclusive solo means that only 1 solo is active at a time"
+msgstr "Одновременно может быть активным только одно соло"
+
+#: monitor_section.cc:177
+msgid "Solo » Mute"
+msgstr "Соло » Выкл"
+
+#: monitor_section.cc:179
+msgid ""
+"If enabled, solo will override mute\n"
+"(a soloed & muted track or bus will be audible)"
+msgstr ""
+"Если включено, то соло заменит приглушение\n"
+"(соло и приглушенная дорожка/шина будут слышны)"
+
+#: monitor_section.cc:187
+msgid "Processors"
+msgstr "Обработчики"
+
+#: monitor_section.cc:189
+msgid "Allow to add monitor effect processors"
+msgstr ""
+
+#: monitor_section.cc:205
 msgid "Gain increase for soloed signals (0dB is normal)"
 msgstr "Усиление солируемого сигнала (0dB является нормой)"
 
-#: monitor_section.cc:167 monitor_section.cc:196 monitor_section.cc:222
-#: monitor_section.cc:322
+#: monitor_section.cc:209 monitor_section.cc:226 monitor_section.cc:243
+#: monitor_section.cc:288
 msgid "0 dB"
 msgstr "0 Дб"
 
-#: monitor_section.cc:168
+#: monitor_section.cc:210
 msgid "3 dB"
 msgstr "3 Дб"
 
-#: monitor_section.cc:169
+#: monitor_section.cc:211
 msgid "6 dB"
 msgstr "6 Дб"
 
-#: monitor_section.cc:170
+#: monitor_section.cc:212
 msgid "10 dB"
 msgstr "10 Дб"
 
-#: monitor_section.cc:176
+#: monitor_section.cc:214
 msgid "Solo Boost"
 msgstr "Усиление соло"
 
-#: monitor_section.cc:191
+#: monitor_section.cc:221
 msgid ""
 "Gain reduction non-soloed signals\n"
 "A value above -inf dB causes \"solo-in-front\""
@@ -8279,119 +8554,99 @@ msgstr ""
 "Снижение усиления не-солированных сигналов \n"
 "Значение выше -инф дБ вызывает \"solo-in-front\""
 
-#: monitor_section.cc:197 monitor_section.cc:224 monitor_section.cc:324
+#: monitor_section.cc:227 monitor_section.cc:245 monitor_section.cc:290
 msgid "-6 dB"
 msgstr "-6 Дб"
 
-#: monitor_section.cc:198 monitor_section.cc:225 monitor_section.cc:325
+#: monitor_section.cc:228 monitor_section.cc:246 monitor_section.cc:291
 msgid "-12 dB"
 msgstr "-12 Дб"
 
-#: monitor_section.cc:199 monitor_section.cc:226 monitor_section.cc:326
+#: monitor_section.cc:229 monitor_section.cc:247 monitor_section.cc:292
 msgid "-20 dB"
 msgstr "-20 Дб"
 
-#: monitor_section.cc:200
+#: monitor_section.cc:230
 msgid "OFF"
 msgstr "ВЫКЛ"
 
-#: monitor_section.cc:202
+#: monitor_section.cc:232
 msgid "SiP Cut"
 msgstr "SiP Обр."
 
-#: monitor_section.cc:217
+#: monitor_section.cc:239
 msgid "Gain reduction to use when dimming monitor outputs"
 msgstr "Снижение усиленеия для исп. при затемнении мониторов выходов"
 
-#: monitor_section.cc:223 monitor_section.cc:323
+#: monitor_section.cc:244 monitor_section.cc:289
 msgid "-3 dB"
 msgstr "-3 Дб"
 
-#: monitor_section.cc:231 monitor_section.cc:289 monitor_section.cc:372
+#: monitor_section.cc:249 monitor_section.cc:263 monitor_section.cc:324
 msgid "Dim"
 msgstr "Тише"
 
-#: monitor_section.cc:241
-msgid "Excl. Solo"
-msgstr "Экскл. соло"
-
-#: monitor_section.cc:243
-msgid "Exclusive solo means that only 1 solo is active at a time"
-msgstr "Одновременно может быть активным только одно соло"
-
-#: monitor_section.cc:250
-msgid "Solo » Mute"
-msgstr "Соло » Выкл"
-
-#: monitor_section.cc:252
-msgid ""
-"If enabled, solo will override mute\n"
-"(a soloed & muted track or bus will be audible)"
-msgstr ""
-"Если включено, то соло заменит приглушение\n"
-"(соло и приглушенная дорожка/шина будут слышны)"
-
-#: monitor_section.cc:327
+#: monitor_section.cc:293
 msgid "-30 dB"
 msgstr "-30 Дб"
 
-#: monitor_section.cc:341
-msgid "Monitor"
-msgstr "Монитор"
-
-#: monitor_section.cc:380
+#: monitor_section.cc:332
 msgid "Inv"
 msgstr "Инв."
 
-#: monitor_section.cc:784
+#: monitor_section.cc:398
+msgid "Monitor"
+msgstr "Монитор"
+
+#: monitor_section.cc:862
 msgid "Switch monitor to mono"
 msgstr "Переключить мониторинг в монофонический режим"
 
-#: monitor_section.cc:787
+#: monitor_section.cc:865
 msgid "Cut monitor"
 msgstr "Выключить мониторинг"
 
-#: monitor_section.cc:790
+#: monitor_section.cc:868
 msgid "Dim monitor"
 msgstr "Приглушить мониторинг"
 
-#: monitor_section.cc:793
+#: monitor_section.cc:871
 msgid "Toggle exclusive solo mode"
 msgstr "Переключить эксклюзивное солирование"
 
-#: monitor_section.cc:799
+#: monitor_section.cc:877
 msgid "Toggle mute overrides solo mode"
 msgstr "Переключение глушения перекрывает соло-режим"
 
-#: monitor_section.cc:811
+#: monitor_section.cc:887
 msgid "Cut monitor channel %1"
 msgstr "Вырезать канал %1 мониторинга"
 
-#: monitor_section.cc:816
+#: monitor_section.cc:892
 msgid "Dim monitor channel %1"
 msgstr "Приглушить канал %1 мониторинга"
 
-#: monitor_section.cc:821
+#: monitor_section.cc:897
 msgid "Solo monitor channel %1"
 msgstr "Солировать каналом %1 мониторинга"
 
-#: monitor_section.cc:826
+#: monitor_section.cc:902
 msgid "Invert monitor channel %1"
 msgstr "Инвертировать канал %1 мониторинга"
 
-#: monitor_section.cc:836
+#: monitor_section.cc:912
 msgid "In-place solo"
 msgstr "На месте соло"
 
-#: monitor_section.cc:838
+#: monitor_section.cc:914
 msgid "After Fade Listen (AFL) solo"
 msgstr "Прослушивание солирования после фейдера (AFL)"
 
-#: monitor_section.cc:840
+#: monitor_section.cc:916
 msgid "Pre Fade Listen (PFL) solo"
 msgstr "Прослушивание солирования до фейдера (PFL)"
 
-#: monitor_section.cc:1262
+#: monitor_section.cc:1324
 msgid "No session - no I/O changes are possible"
 msgstr ""
 
@@ -8399,31 +8654,29 @@ msgstr ""
 msgid "Monitor output selector"
 msgstr ""
 
-#: mono_panner.cc:104 stereo_panner.cc:114
+#: mono_panner.cc:105 stereo_panner.cc:115
 msgid "bypassed"
 msgstr "Обойдено"
 
-#: mono_panner.cc:118
+#: mono_panner.cc:119
 #, c-format
 msgid "L:%3d R:%3d"
 msgstr "Левый: %3d, Правый: %3d"
 
-#: mono_panner.cc:202 panner2d.cc:277 stereo_panner.cc:251
-#: stereo_panner.cc:274
+#: mono_panner.cc:203 panner2d.cc:276 stereo_panner.cc:252 stereo_panner.cc:275
 msgid "Panner|L"
 msgstr "Л"
 
-#: mono_panner.cc:219 panner2d.cc:278 stereo_panner.cc:249
-#: stereo_panner.cc:276
+#: mono_panner.cc:220 panner2d.cc:277 stereo_panner.cc:250 stereo_panner.cc:277
 msgid "Panner|R"
 msgstr "П"
 
-#: mono_panner_editor.cc:33
+#: mono_panner_editor.cc:35
 msgid "Mono Panner"
 msgstr "Монопанорама"
 
-#: mono_panner_editor.cc:44 mono_panner_editor.cc:49
-#: stereo_panner_editor.cc:46 stereo_panner_editor.cc:51
+#: mono_panner_editor.cc:46 mono_panner_editor.cc:51 stereo_panner_editor.cc:48
+#: stereo_panner_editor.cc:53
 msgid "%"
 msgstr "%"
 
@@ -8500,10 +8753,6 @@ msgstr ""
 "\n"
 "Спасибо за использование Ardour!"
 
-#: new_plugin_preset_dialog.cc:29
-msgid "New Preset"
-msgstr "Создать профиль"
-
 #: new_plugin_preset_dialog.cc:30
 msgid "Replace existing preset with this name"
 msgstr "Заменить существующий профиль с таким именем"
@@ -8512,6 +8761,10 @@ msgstr "Заменить существующий профиль с таким 
 msgid "Name of new preset"
 msgstr "Название нового профиля"
 
+#: new_plugin_preset_dialog.cc:44
+msgid "New Favorite Only"
+msgstr ""
+
 #: normalize_dialog.cc:34
 msgid "Normalize regions"
 msgstr "Нормировка областей"
@@ -8520,7 +8773,7 @@ msgstr "Нормировка областей"
 msgid "Normalize region"
 msgstr "Нормировка области"
 
-#: normalize_dialog.cc:49 strip_silence_dialog.cc:66
+#: normalize_dialog.cc:49 strip_silence_dialog.cc:67
 msgid "dbFS"
 msgstr "dbFS"
 
@@ -8540,35 +8793,40 @@ msgstr "Нормировать"
 msgid "Select Note"
 msgstr "Выбрать ноту"
 
-#: opts.cc:57
+#: opts.cc:61
 msgid "Usage: "
 msgstr "Использование: "
 
-#: opts.cc:58
+#: opts.cc:62
 msgid "  [SESSION_NAME]              Name of session to load\n"
 msgstr ""
 "  [имя_сессии]                     Загрузить сессию с указанным названием\n"
 
-#: opts.cc:59
+#: opts.cc:63
 msgid "  -v, --version               Show version information\n"
 msgstr "  -v, --version                    Информация о версии программы\n"
 
-#: opts.cc:60
+#: opts.cc:64
 msgid "  -h, --help                  Print this message\n"
 msgstr "  -h, --help                       Показать это сообщение\n"
 
-#: opts.cc:61
+#: opts.cc:65
 msgid ""
 "  -a, --no-announcements      Do not contact website for announcements\n"
 msgstr "  -a, --no-announcements      Не обращайтесь на сайт для объявлений\n"
 
-#: opts.cc:62
+#: opts.cc:66
 msgid ""
 "  -b, --bindings              Print all possible keyboard binding names\n"
 msgstr ""
 "  -b, --bindings                   Показать все доступные комбинации клавиш\n"
 
-#: opts.cc:63
+#: opts.cc:67
+msgid ""
+"  -B, --bypass-plugins        Bypass all plugins in an existing session\n"
+msgstr "  -B, --bypass-plugins        Выключить все плагины в текущем сеансе\n"
+
+#: opts.cc:68
 msgid ""
 "  -c, --name <name>           Use a specific backend client name, default is "
 "ardour\n"
@@ -8576,14 +8834,14 @@ msgstr ""
 "  -c, --name  <имя>      Использовать другое имя клиента звуковой "
 "подсистемы, по умолчанию -- ardour\n"
 
-#: opts.cc:64
+#: opts.cc:69
 msgid ""
 "  -d, --disable-plugins       Disable all plugins in an existing session\n"
 msgstr ""
 "  -d, --disable-plugins            Отключить все плагины в существующей "
 "сессии\n"
 
-#: opts.cc:65
+#: opts.cc:70
 msgid ""
 "  -D, --debug <options>       Set debug flags. Use \"-D list\" to see "
 "available options\n"
@@ -8591,43 +8849,43 @@ msgstr ""
 " -D, --debug <options>       Уст. отладочные флаги. Используйте \"-D list\", "
 "чтобы увидеть доступные опции\n"
 
-#: opts.cc:66
+#: opts.cc:71
 msgid "  -n, --no-splash             Do not show splash screen\n"
 msgstr ""
 "  -n, --no-splash                  Не показывать заставку при запуске "
 "программы\n"
 
-#: opts.cc:67
+#: opts.cc:72
 msgid "  -m, --menus file            Use \"file\" to define menus\n"
 msgstr ""
 "  -m, --menus файл                 Использовать свой файл для меню Ardour\n"
 
-#: opts.cc:68
+#: opts.cc:73
 msgid ""
 "  -N, --new session-name      Create a new session from the command line\n"
 msgstr ""
 "  -N, --new имя_сессии             Создать новую сессию из командной строки\n"
 
-#: opts.cc:69
+#: opts.cc:74
 msgid "  -O, --no-hw-optimizations   Disable h/w specific optimizations\n"
 msgstr ""
 "  -O, --no-hw-optimizations        Отключить аппаратно-специфичные "
 "оптимизации\n"
 
-#: opts.cc:70
+#: opts.cc:75
 msgid "  -P, --no-connect-ports      Do not connect any ports at startup\n"
 msgstr "  -P, --no-connect-ports      Не подключайте порты при запуске\n"
 
-#: opts.cc:71
+#: opts.cc:76
 msgid "  -S, --sync                  Draw the gui synchronously \n"
 msgstr ""
 "  -S, --sync\t                   Синхронно рисовать графический интерфейс\n"
 
-#: opts.cc:73
+#: opts.cc:78
 msgid "  -V, --novst                 Do not use VST support\n"
 msgstr "  -V, --novst                      Не использовать поддержку VST\n"
 
-#: opts.cc:75
+#: opts.cc:80
 msgid ""
 "  -E, --save <file>           Load the specified session, save it to <file> "
 "and then quit\n"
@@ -8635,47 +8893,48 @@ msgstr ""
 "  -E, --save <file>           Загрузите указанную сессию, сохраните её в "
 "<file> и затем выйдите\n"
 
-#: opts.cc:76
+#: opts.cc:81
 msgid "  -C, --curvetest filename    Curve algorithm debugger\n"
 msgstr "  -C, --curvetest имя_файла        Отладчик алгоритма кривых\n"
 
-#: opts.cc:77
+#: opts.cc:82
 msgid "  -k, --keybindings filename  Name of key bindings to load\n"
 msgstr ""
+"  -k, --keybindings имя_файла  Какой файл клавиатурных комбинаций загрузить\n"
 
-#: panner2d.cc:897
+#: panner2d.cc:896
 msgid "Panner (2D)"
 msgstr "Панорамирование (2D)"
 
-#: panner2d.cc:899 panner_ui.cc:400 plugin_ui.cc:458
+#: panner2d.cc:898 panner_ui.cc:402 plugin_ui.cc:458
 msgid "Bypass"
 msgstr "Обход"
 
-#: panner2d.cc:905
+#: panner2d.cc:904
 msgid "Panner"
 msgstr "Панорамирование"
 
-#: panner_ui.cc:70
+#: panner_ui.cc:72
 msgid "Pan automation mode"
 msgstr "Режим автоматизации панорамы"
 
-#: panner_ui.cc:71
+#: panner_ui.cc:73
 msgid "Pan automation type"
 msgstr "Тип автоматизации панорамы"
 
-#: panner_ui.cc:603
+#: panner_ui.cc:605
 msgid "Manual|M"
 msgstr "Р"
 
-#: panner_ui.cc:606
+#: panner_ui.cc:608
 msgid "Play|P"
 msgstr "П"
 
-#: panner_ui.cc:609
+#: panner_ui.cc:611
 msgid "Touch|T"
 msgstr "К"
 
-#: panner_ui.cc:612
+#: panner_ui.cc:614
 msgid "Write|W"
 msgstr "З"
 
@@ -8703,104 +8962,140 @@ msgstr "Не назначен"
 msgid "Imported"
 msgstr "Импортировано"
 
-#: plugin_eq_gui.cc:85 plugin_eq_gui.cc:109
+#: plugin_eq_gui.cc:83 plugin_eq_gui.cc:107
 msgid "dB scale"
 msgstr "Масштаб в  Дб"
 
-#: plugin_eq_gui.cc:116
+#: plugin_eq_gui.cc:114
 msgid "Show phase"
 msgstr "Показывать фазу"
 
-#: plugin_selector.cc:53 plugin_selector.cc:225
+#: plugin_selector.cc:54 plugin_selector.cc:311
 msgid "Name contains"
 msgstr "Название содержит"
 
-#: plugin_selector.cc:54 plugin_selector.cc:229
+#: plugin_selector.cc:55 plugin_selector.cc:315
 msgid "Type contains"
 msgstr "Тип содержит"
 
-#: plugin_selector.cc:55 plugin_selector.cc:227
+#: plugin_selector.cc:56 plugin_selector.cc:313
 msgid "Category contains"
 msgstr "Название категории содержит"
 
-#: plugin_selector.cc:56 plugin_selector.cc:249
+#: plugin_selector.cc:57 plugin_selector.cc:335
 msgid "Author contains"
 msgstr "Имя автора содержит"
 
-#: plugin_selector.cc:57 plugin_selector.cc:251
+#: plugin_selector.cc:58 plugin_selector.cc:337
 msgid "Library contains"
 msgstr "Библиотека содержит"
 
-#: plugin_selector.cc:58 plugin_selector.cc:215 plugin_selector.cc:527
+#: plugin_selector.cc:59 plugin_selector.cc:267 plugin_selector.cc:613
 msgid "Favorites only"
 msgstr "Только любимые"
 
-#: plugin_selector.cc:59 plugin_selector.cc:219 plugin_selector.cc:527
+#: plugin_selector.cc:60 plugin_selector.cc:271 plugin_selector.cc:613
 msgid "Hidden only"
 msgstr "Только скрытые"
 
-#: plugin_selector.cc:64
+#: plugin_selector.cc:65
 msgid "Plugin Manager"
 msgstr "Управление плагинами"
 
-#: plugin_selector.cc:85
+#: plugin_selector.cc:96
 msgid "Fav"
 msgstr "Избранный"
 
-#: plugin_selector.cc:87
+#: plugin_selector.cc:98
 msgid "Available Plugins"
 msgstr "Доступные плагины"
 
-#: plugin_selector.cc:88
+#: plugin_selector.cc:99
 msgid "Type"
 msgstr "Тип"
 
-#: plugin_selector.cc:89
+#: plugin_selector.cc:100
 msgid "Category"
 msgstr "Категория"
 
-#: plugin_selector.cc:90
+#: plugin_selector.cc:101
 msgid "Creator"
 msgstr "Создатель"
 
-#: plugin_selector.cc:91
+#: plugin_selector.cc:102
 msgid "# Audio In"
 msgstr "# Звук. вх."
 
-#: plugin_selector.cc:92
+#: plugin_selector.cc:103
 msgid "# Audio Out"
 msgstr "# Звук. вых."
 
-#: plugin_selector.cc:93
+#: plugin_selector.cc:104
 msgid "# MIDI In"
 msgstr "# MIDI-вх."
 
-#: plugin_selector.cc:94
+#: plugin_selector.cc:105
 msgid "# MIDI Out"
 msgstr "# MIDI-вых."
 
-#: plugin_selector.cc:116
+#: plugin_selector.cc:132
 msgid "Plugins to be connected"
 msgstr "Подключаемые плагины"
 
-#: plugin_selector.cc:129
+#: plugin_selector.cc:145
 msgid "Add a plugin to the effect list"
 msgstr "Добавить плагин в список эффектов"
 
-#: plugin_selector.cc:133
+#: plugin_selector.cc:149
 msgid "Remove a plugin from the effect list"
 msgstr "Удалить плагин из списка эффектов"
 
-#: plugin_selector.cc:169
+#: plugin_selector.cc:161
+msgid "Show Hidden"
+msgstr "Показывать скрытые"
+
+#: plugin_selector.cc:163
+msgid "Include hidden plugins in list."
+msgstr "Включить в список скрытые плагины"
+
+#: plugin_selector.cc:166
+msgid "Instruments"
+msgstr "Инструменты"
+
+#: plugin_selector.cc:168
+msgid "Cycle display of instrument plugins (if any)."
+msgstr ""
+
+#: plugin_selector.cc:171
+msgid "Analyzers"
+msgstr "Анализаторы"
+
+#: plugin_selector.cc:173
+msgid "Cycle display of analysis plugins (if any)."
+msgstr ""
+
+#: plugin_selector.cc:176
+msgid "Utils"
+msgstr "Общие"
+
+#: plugin_selector.cc:178
+msgid "Cycle display of utility plugins (if any)."
+msgstr ""
+
+#: plugin_selector.cc:208
+msgid "Filter"
+msgstr "Фильтр"
+
+#: plugin_selector.cc:221
 msgid "Insert Plugin(s)"
 msgstr "Вставить плагины"
 
-#: plugin_selector.cc:333 plugin_selector.cc:334 plugin_selector.cc:335
-#: plugin_selector.cc:336
+#: plugin_selector.cc:419 plugin_selector.cc:420 plugin_selector.cc:421
+#: plugin_selector.cc:422
 msgid "variable"
 msgstr "Переменная"
 
-#: plugin_selector.cc:486
+#: plugin_selector.cc:572
 msgid ""
 "The plugin \"%1\" could not be loaded\n"
 "\n"
@@ -8810,19 +9105,19 @@ msgstr ""
 "\n"
 "Смотреть окно отчёта для большей информации (возможно)"
 
-#: plugin_selector.cc:634
+#: plugin_selector.cc:730
 msgid "Favorites"
 msgstr "Избранные"
 
-#: plugin_selector.cc:636
+#: plugin_selector.cc:732
 msgid "Plugin Manager..."
 msgstr "Управление плагинами..."
 
-#: plugin_selector.cc:640
+#: plugin_selector.cc:736
 msgid "By Creator"
 msgstr "По создателю"
 
-#: plugin_selector.cc:643
+#: plugin_selector.cc:739
 msgid "By Category"
 msgstr "По категории"
 
@@ -8937,6 +9232,10 @@ msgstr ""
 "В этой сборке нет поддержки предустановок плагинов. См. подробнее в окне "
 "журнала."
 
+#: plugin_ui.cc:592
+msgid "New Preset"
+msgstr "Создать профиль"
+
 #: plugin_ui.cc:692
 msgid "Click to allow normal use of %1 keyboard shortcuts"
 msgstr ""
@@ -8946,77 +9245,85 @@ msgstr ""
 msgid "(none)"
 msgstr "(нет)"
 
-#: port_group.cc:337
+#: port_group.cc:338
 msgid "%1 Busses"
 msgstr "Шины %1"
 
-#: port_group.cc:338
+#: port_group.cc:339
 msgid "%1 Tracks"
 msgstr "Дорожки %1"
 
-#: port_group.cc:339
+#: port_group.cc:340
 msgid "Hardware"
 msgstr "Аппаратное обеспечение"
 
-#: port_group.cc:340
+#: port_group.cc:341
 msgid "%1 Misc"
 msgstr "Прочее"
 
-#: port_group.cc:341
+#: port_group.cc:342
 msgid "Other"
 msgstr "Прочее"
 
-#: port_group.cc:432 port_group.cc:433
+#: port_group.cc:434 port_group.cc:435
 msgid "LTC Out"
 msgstr "LTC Out"
 
-#: port_group.cc:436 port_group.cc:437
+#: port_group.cc:438 port_group.cc:439
 msgid "LTC In"
 msgstr "LTC In"
 
-#: port_group.cc:463
+#: port_group.cc:473
 msgid "MTC in"
 msgstr "MTC in"
 
-#: port_group.cc:466
+#: port_group.cc:476
 msgid "MIDI control in"
 msgstr "MIDI control in"
 
-#: port_group.cc:469
+#: port_group.cc:479
 msgid "MIDI clock in"
 msgstr "MIDI clock in"
 
-#: port_group.cc:472
+#: port_group.cc:482
 msgid "MMC in"
 msgstr "MMC in"
 
-#: port_group.cc:476
+#: port_group.cc:486
 msgid "MTC out"
 msgstr "MTC out"
 
-#: port_group.cc:479
+#: port_group.cc:489
 msgid "MIDI control out"
 msgstr "MIDI control out"
 
-#: port_group.cc:482
+#: port_group.cc:492
 msgid "MIDI clock out"
 msgstr "MIDI clock out"
 
-#: port_group.cc:485
+#: port_group.cc:495
 msgid "MMC out"
 msgstr "MMC out"
 
-#: port_group.cc:532
+#: port_group.cc:543
 msgid ":monitor"
 msgstr ": монитор"
 
-#: port_group.cc:544
+#: port_group.cc:559
 msgid "system:"
 msgstr "Система:"
 
-#: port_group.cc:545
-msgid "alsa_pcm"
-msgstr "аlsa_pcm"
+#: port_group.cc:560
+msgid "alsa_pcm:"
+msgstr "alsa_pcm:"
+
+#: port_group.cc:561
+msgid "alsa_midi:"
+msgstr "alsa_midi:"
+
+#: port_group.cc:566
+msgid "Scene "
+msgstr "Сцена"
 
 #: port_insert_ui.cc:39
 msgid "Measure Latency"
@@ -9038,46 +9345,46 @@ msgstr "Не обнаружен сигнал"
 msgid "Port Insert "
 msgstr "Вставка порта"
 
-#: port_matrix.cc:340 port_matrix.cc:366
+#: port_matrix.cc:341 port_matrix.cc:367
 msgid "<b>Sources</b>"
 msgstr "<b>Источники</b>"
 
-#: port_matrix.cc:341 port_matrix.cc:367
+#: port_matrix.cc:342 port_matrix.cc:368
 msgid "<b>Destinations</b>"
 msgstr "<b>Назначения</b>"
 
-#: port_matrix.cc:449 port_matrix.cc:457
+#: port_matrix.cc:450 port_matrix.cc:458
 #, c-format
 msgid "Add %s %s"
 msgstr "Добавить %s-%s"
 
-#: port_matrix.cc:465
+#: port_matrix.cc:466
 #, c-format
 msgid "Rename '%s'..."
 msgstr "Переименовать '%s'..."
 
-#: port_matrix.cc:481
+#: port_matrix.cc:482
 msgid "Remove all"
 msgstr "Удалить все"
 
-#: port_matrix.cc:501 port_matrix.cc:513
+#: port_matrix.cc:502 port_matrix.cc:514
 #, c-format
 msgid "%s all"
 msgstr "%s все"
 
-#: port_matrix.cc:536
+#: port_matrix.cc:537
 msgid "Rescan"
 msgstr "Просканировать заново"
 
-#: port_matrix.cc:538
+#: port_matrix.cc:539
 msgid "Show individual ports"
 msgstr "Показывать порты раздельно"
 
-#: port_matrix.cc:544
+#: port_matrix.cc:545
 msgid "Flip"
 msgstr "Повернуть матрицу"
 
-#: port_matrix.cc:731
+#: port_matrix.cc:732
 msgid ""
 "It is not possible to add a port here, as the first processor in the track "
 "or buss cannot support the new configuration."
@@ -9085,15 +9392,15 @@ msgstr ""
 "Невозможно добавить сюда порт, поскольку первый обработчик дорожки или шины "
 "не может поддерживать новую конфигурацию."
 
-#: port_matrix.cc:734
+#: port_matrix.cc:735
 msgid "Cannot add port"
 msgstr "Невозможно добавить порт"
 
-#: port_matrix.cc:756
+#: port_matrix.cc:757
 msgid "Port removal not allowed"
 msgstr "Удаление портов не разрешено"
 
-#: port_matrix.cc:757
+#: port_matrix.cc:758
 msgid ""
 "This port cannot be removed.\n"
 "Either the first plugin in the track or buss cannot accept\n"
@@ -9103,17 +9410,17 @@ msgstr ""
 "Либо первый плагин в дорожке или шине не может принять новое\n"
 "количество входов, либо у последнего плагина больше выходов."
 
-#: port_matrix.cc:974
+#: port_matrix.cc:975
 #, c-format
 msgid "Remove '%s'"
 msgstr "Удалить '%s'"
 
-#: port_matrix.cc:989
+#: port_matrix.cc:990
 #, c-format
 msgid "%s all from '%s'"
 msgstr "%s все из '%s'"
 
-#: port_matrix.cc:1055 transform_dialog.cc:62
+#: port_matrix.cc:1056 transform_dialog.cc:62
 msgid "channel"
 msgstr "Канал"
 
@@ -9125,15 +9432,19 @@ msgstr "Нет доступных портов."
 msgid "There are no %1 ports to connect."
 msgstr "Нет соединяемых портов %1."
 
-#: processor_box.cc:150
+#: processor_box.cc:169
 msgid "Send"
 msgstr "Послать"
 
-#: processor_box.cc:152
+#: processor_box.cc:171
 msgid "Return"
 msgstr "Возврат"
 
-#: processor_box.cc:310
+#: processor_box.cc:239
+msgid "New Favorite Preset for \"%1\""
+msgstr "Новая избранная предустановка для \"%1\""
+
+#: processor_box.cc:414
 msgid ""
 "\n"
 "This mono plugin has been replicated %1 times."
@@ -9141,17 +9452,17 @@ msgstr ""
 "\n"
 "Этот моноплагин был копирован %1 раз."
 
-#: processor_box.cc:314
+#: processor_box.cc:418
 msgid ""
 "<b>%1</b>\n"
 "Double-click to show GUI.\n"
-"Alt+double-click to show generic GUI.%2"
+"%2+double-click to show generic GUI.%3"
 msgstr ""
 "<b>%1</b>\n"
-"Двойной щелчок, чтобы показать общий GUI.\n"
-"Alt+двойной щелчок, чтобы показать общий GUI.%2"
+"Двойной щелчок открывает интерфейс плагина.\n"
+"%2+двойной щелчок открывает рисуемый хостом интерфейс.%3"
 
-#: processor_box.cc:317
+#: processor_box.cc:421
 msgid ""
 "<b>%1</b>\n"
 "Double-click to show generic GUI.%2"
@@ -9159,32 +9470,42 @@ msgstr ""
 "<b>%1</b>\n"
 "Двойной щелчок, чтобы показать общий GUI.%2"
 
-#: processor_box.cc:361
+#: processor_box.cc:427
+msgid ""
+"<b>%1</b>\n"
+"The Plugin is not available on this system\n"
+"and has been replaced by a stub."
+msgstr ""
+"<b>%1</b>\n"
+"Этот плагин недоступен в \n"
+"системе и заменён на заглушку."
+
+#: processor_box.cc:470
 #, c-format
 msgid "(%1x1) "
 msgstr "(%1x1) "
 
-#: processor_box.cc:437
+#: processor_box.cc:546
 msgid "Show All Controls"
 msgstr "Показать все регуляторы"
 
-#: processor_box.cc:441
+#: processor_box.cc:550
 msgid "Hide All Controls"
 msgstr "Скрыть все регуляторы"
 
-#: processor_box.cc:475
+#: processor_box.cc:584
 msgid "Link panner controls"
 msgstr "Связать регуляторы панорамирования"
 
-#: processor_box.cc:573
+#: processor_box.cc:691
 msgid "on"
 msgstr "Вкл"
 
-#: processor_box.cc:573 rc_option_editor.cc:2862 rc_option_editor.cc:2876
+#: processor_box.cc:691 rc_option_editor.cc:2978 rc_option_editor.cc:2992
 msgid "off"
 msgstr "Выкл"
 
-#: processor_box.cc:1021
+#: processor_box.cc:1177
 msgid ""
 "Right-click to add/remove/edit\n"
 "plugins,inserts,sends and more"
@@ -9192,15 +9513,22 @@ msgstr ""
 "Щелчком правой клавишей мыши можно добавлять, \n"
 "изменять и удалять плагины, посылы, возвраты и пр."
 
-#: processor_box.cc:1495 processor_box.cc:1870
+#: processor_box.cc:1326
+msgid ""
+"Processor Drag/Drop failed. Probably because\n"
+"the I/O configuration of the plugins could\n"
+"not match the configuration of this track."
+msgstr ""
+
+#: processor_box.cc:1769 processor_box.cc:2164
 msgid "Plugin Incompatibility"
 msgstr "Несовместимость плагинов"
 
-#: processor_box.cc:1498
+#: processor_box.cc:1772
 msgid "You attempted to add the plugin \"%1\" in slot %2.\n"
 msgstr "Вы пытались добавить плагин \"%1\" в слот %2.\n"
 
-#: processor_box.cc:1504
+#: processor_box.cc:1778
 msgid ""
 "\n"
 "This plugin has:\n"
@@ -9208,21 +9536,21 @@ msgstr ""
 "\n"
 "У этого плагина:\n"
 
-#: processor_box.cc:1507
+#: processor_box.cc:1781
 msgid "\t%1 MIDI input\n"
 msgid_plural "\t%1 MIDI inputs\n"
 msgstr[0] "\t%1 MIDI-вход\n"
 msgstr[1] "\t%1 MIDI-входа\n"
 msgstr[2] "\t%1 MIDI-входов\n"
 
-#: processor_box.cc:1511
+#: processor_box.cc:1785
 msgid "\t%1 audio input\n"
 msgid_plural "\t%1 audio inputs\n"
 msgstr[0] "\t%1 звуковой вход\n"
 msgstr[1] "\t%1 звуковых входа\n"
 msgstr[2] "\t%1 звуковых входов\n"
 
-#: processor_box.cc:1514
+#: processor_box.cc:1788
 msgid ""
 "\n"
 "but at the insertion point, there are:\n"
@@ -9230,21 +9558,21 @@ msgstr ""
 "\n"
 "но в точке вставки сейчас:\n"
 
-#: processor_box.cc:1517
+#: processor_box.cc:1791
 msgid "\t%1 MIDI channel\n"
 msgid_plural "\t%1 MIDI channels\n"
 msgstr[0] "\t%1 MIDI-канал\n"
 msgstr[1] "\t%1 MIDI-канала\n"
 msgstr[2] "\t%1 MIDI-каналов\n"
 
-#: processor_box.cc:1521
+#: processor_box.cc:1795
 msgid "\t%1 audio channel\n"
 msgid_plural "\t%1 audio channels\n"
 msgstr[0] "\t%1 звуковой канал\n"
 msgstr[1] "\t%1 звуковых канала\n"
 msgstr[2] "\t%1 звуковых каналов\n"
 
-#: processor_box.cc:1524
+#: processor_box.cc:1798
 msgid ""
 "\n"
 "%1 is unable to insert this plugin here.\n"
@@ -9252,11 +9580,11 @@ msgstr ""
 "\n"
 "%1 не может вставить сюда этот плагин.\n"
 
-#: processor_box.cc:1561
+#: processor_box.cc:1835
 msgid "Cannot set up new send: %1"
 msgstr "Невозможно настроить новый посыл: %1"
 
-#: processor_box.cc:1873
+#: processor_box.cc:2167
 msgid ""
 "You cannot reorder these plugins/sends/inserts\n"
 "in that way because the inputs and\n"
@@ -9266,20 +9594,20 @@ msgstr ""
 "посылы и возвраты подобным образом, поскольку \n"
 "входы и выходы перестанут корректно работать."
 
-#: processor_box.cc:2057
+#: processor_box.cc:2367
 msgid "Rename Processor"
 msgstr "Переименовать обработчик"
 
-#: processor_box.cc:2088
+#: processor_box.cc:2398
 msgid "At least 100 IO objects exist with a name like %1 - name not changed"
 msgstr ""
 "Существует по крайней мере 100 объектов IO с именем, как %1 - имя не изменено"
 
-#: processor_box.cc:2226
+#: processor_box.cc:2536
 msgid "plugin insert constructor failed"
 msgstr "Сбой конструктора вставки плагина"
 
-#: processor_box.cc:2237
+#: processor_box.cc:2547
 msgid ""
 "Copying the set of processors on the clipboard failed,\n"
 "probably because the I/O configuration of the plugins\n"
@@ -9289,7 +9617,7 @@ msgstr ""
 "буфер обмена. Вероятно, конфигурация входа и выхода\n"
 "плагинов не совпала с конфигурацией этой дорожки."
 
-#: processor_box.cc:2283
+#: processor_box.cc:2593
 msgid ""
 "Do you really want to remove all processors from %1?\n"
 "(this cannot be undone)"
@@ -9298,15 +9626,15 @@ msgstr ""
 "обработчики из \"%1\" ?\n"
 "(отмена невозможна)"
 
-#: processor_box.cc:2287 processor_box.cc:2312
+#: processor_box.cc:2597 processor_box.cc:2622
 msgid "Yes, remove them all"
 msgstr "Да, удалить их все"
 
-#: processor_box.cc:2289 processor_box.cc:2314
+#: processor_box.cc:2599 processor_box.cc:2624
 msgid "Remove processors"
 msgstr "Удалить обработчики"
 
-#: processor_box.cc:2304
+#: processor_box.cc:2614
 msgid ""
 "Do you really want to remove all pre-fader processors from %1?\n"
 "(this cannot be undone)"
@@ -9315,7 +9643,7 @@ msgstr ""
 "предфейдерные обработчики из \"%1\" ?\n"
 "(отмена невозможна)"
 
-#: processor_box.cc:2307
+#: processor_box.cc:2617
 msgid ""
 "Do you really want to remove all post-fader processors from %1?\n"
 "(this cannot be undone)"
@@ -9324,59 +9652,59 @@ msgstr ""
 "послефейдерные обработчики из \"%1\" ?\n"
 "(отмена невозможна)"
 
-#: processor_box.cc:2495
+#: processor_box.cc:2805
 msgid "New Plugin"
 msgstr "Добавить плагин"
 
-#: processor_box.cc:2498
+#: processor_box.cc:2808
 msgid "New Insert"
 msgstr "Добавить возврат"
 
-#: processor_box.cc:2501
+#: processor_box.cc:2811
 msgid "New External Send ..."
 msgstr "Добавить внешний посыл с портом JACK..."
 
-#: processor_box.cc:2505
+#: processor_box.cc:2815
 msgid "New Aux Send ..."
 msgstr "Добавить внешний посыл без порта JACK..."
 
-#: processor_box.cc:2508
+#: processor_box.cc:2818
 msgid "Send Options"
 msgstr "Параметры отправки"
 
-#: processor_box.cc:2510
+#: processor_box.cc:2820
 msgid "Clear (all)"
 msgstr "Очистить (всё)"
 
-#: processor_box.cc:2512
+#: processor_box.cc:2822
 msgid "Clear (pre-fader)"
 msgstr "Очистить (до фейдера)"
 
-#: processor_box.cc:2514
+#: processor_box.cc:2824
 msgid "Clear (post-fader)"
 msgstr "Очистить (после фейдера)"
 
-#: processor_box.cc:2540
+#: processor_box.cc:2846
 msgid "Activate All"
 msgstr "Активировать все"
 
-#: processor_box.cc:2542
+#: processor_box.cc:2848
 msgid "Deactivate All"
 msgstr "Деактивировать все"
 
-#: processor_box.cc:2544
+#: processor_box.cc:2850
 msgid "A/B Plugins"
 msgstr "Отключить все"
 
-#: processor_box.cc:2553
+#: processor_box.cc:2859
 msgid "Edit with generic controls..."
 msgstr "Изменить с интерфейсом хоста..."
 
-#: processor_box.cc:2856
+#: processor_box.cc:3162
 msgid "%1: %2 (by %3)"
 msgstr "%1: %2 (автор — %3)"
 
-#: processor_box.cc:2858
+#: processor_box.cc:3164
 msgid "%1 (by %2)"
 msgstr "%1 (на %2)"
 
@@ -9428,193 +9756,268 @@ msgstr "Начало привязки ноты"
 msgid "Snap note end"
 msgstr "Конец привязки ноты"
 
-#: rc_option_editor.cc:80
-msgid "Click audio file:"
-msgstr "Файл щелчка доли:"
-
-#: rc_option_editor.cc:83 rc_option_editor.cc:90
+#: rc_option_editor.cc:81 rc_option_editor.cc:82
 msgid "Browse..."
 msgstr "Просмотр..."
 
 #: rc_option_editor.cc:87
+msgid "Emphasis on first beat:"
+msgstr "Усиление на первой доле:"
+
+#: rc_option_editor.cc:93
+msgid "Use default Click:"
+msgstr "Использовать обычный щелчок:"
+
+#: rc_option_editor.cc:99
+msgid "Click audio file:"
+msgstr "Файл щелчка доли:"
+
+#: rc_option_editor.cc:106
 msgid "Click emphasis audio file:"
 msgstr "Файл щелчка сильной доли:"
 
-#: rc_option_editor.cc:119
+#: rc_option_editor.cc:152
 msgid "Choose Click"
 msgstr "Выберите щелчок метронома"
 
-#: rc_option_editor.cc:142
+#: rc_option_editor.cc:175
 msgid "Choose Click Emphasis"
 msgstr "Выберите акцентирующий щелчок метронома"
 
-#: rc_option_editor.cc:173
+#: rc_option_editor.cc:236
 msgid "Limit undo history to"
 msgstr "Ограничивать историю действий"
 
-#: rc_option_editor.cc:174
+#: rc_option_editor.cc:237
 msgid "Save undo history of"
 msgstr "Ограничивать сохранение истории действий"
 
-#: rc_option_editor.cc:183 rc_option_editor.cc:190
+#: rc_option_editor.cc:246 rc_option_editor.cc:253
 msgid "commands"
 msgstr "командами"
 
-#: rc_option_editor.cc:333
+#: rc_option_editor.cc:376
+msgid ""
+"\n"
+"Changes to this setting will only persist after your project has been saved."
+msgstr ""
+
+#: rc_option_editor.cc:387 rc_option_editor.cc:449
+msgid "<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"
+msgstr "<b>Рекомендуется: %1 + клавиша 3 (правая клавиша мыши)</b>%2"
+
+#: rc_option_editor.cc:401
 msgid "Select Keyboard layout:"
 msgstr "Раскладка клавиатуры:"
 
-#: rc_option_editor.cc:352
+#: rc_option_editor.cc:420
 msgid "When Clicking:"
 msgstr "При щелчке:"
 
-#: rc_option_editor.cc:359
+#: rc_option_editor.cc:427
 msgid "Edit using:"
 msgstr "Редактировать с:"
 
-#: rc_option_editor.cc:365 rc_option_editor.cc:394 rc_option_editor.cc:423
+#: rc_option_editor.cc:433 rc_option_editor.cc:463 rc_option_editor.cc:493
 msgid "+ button"
 msgstr "+ клавиша"
 
-#: rc_option_editor.cc:388
+#: rc_option_editor.cc:457
 msgid "Delete using:"
 msgstr "Удалять с:"
 
-#: rc_option_editor.cc:417
+#: rc_option_editor.cc:479
+msgid "<b>Recommended Setting: %1 + button 1 (left mouse button)</b>%2"
+msgstr "<b>Рекомендуется: %1 + клавиша 1 (левая клавиша мыши)</b>%2"
+
+#: rc_option_editor.cc:487
 msgid "Insert note using:"
 msgstr "Вставлять ноты с:"
 
-#: rc_option_editor.cc:435
+#: rc_option_editor.cc:505
 msgid "When Beginning a Drag:"
 msgstr "В начале перетаскивания:"
 
-#: rc_option_editor.cc:453
+#: rc_option_editor.cc:516 rc_option_editor.cc:543 rc_option_editor.cc:576
+#: rc_option_editor.cc:597 rc_option_editor.cc:641 rc_option_editor.cc:674
+#: rc_option_editor.cc:700 rc_option_editor.cc:728 rc_option_editor.cc:757
+#: rc_option_editor.cc:779
+msgid "<b>Recommended Setting: %1</b>%2"
+msgstr "<b>Рекомендуется: %1</b>%2"
+
+#: rc_option_editor.cc:530
 msgid "Copy items using:"
 msgstr "Копировать объекты с:"
 
-#: rc_option_editor.cc:473
+#: rc_option_editor.cc:557
 msgid "Constrain drag using:"
 msgstr "Ограничить перемещение с:"
 
-#: rc_option_editor.cc:481
+#: rc_option_editor.cc:565
 msgid "When Beginning a Trim:"
 msgstr ""
 
-#: rc_option_editor.cc:499
+#: rc_option_editor.cc:584
 msgid "Trim contents using:"
 msgstr ""
 
-#: rc_option_editor.cc:519
+#: rc_option_editor.cc:605
 msgid "Anchored trim using:"
 msgstr ""
 
-#: rc_option_editor.cc:562
+#: rc_option_editor.cc:649
 msgid "Resize notes relatively using:"
 msgstr ""
 
-#: rc_option_editor.cc:571
+#: rc_option_editor.cc:658
 msgid "While Dragging:"
 msgstr "При перетаскивании:"
 
-#: rc_option_editor.cc:589
+#: rc_option_editor.cc:682
 msgid "Ignore snap using:"
 msgstr "Игнорировать привязку с:"
 
-#: rc_option_editor.cc:609
+#: rc_option_editor.cc:708
 msgid "Snap relatively using:"
 msgstr ""
 
-#: rc_option_editor.cc:617
+#: rc_option_editor.cc:716
 msgid "While Trimming:"
 msgstr ""
 
-#: rc_option_editor.cc:635
-msgid "Resize overlaped regions using:"
+#: rc_option_editor.cc:736
+msgid "Resize overlapped regions using:"
 msgstr ""
 
-#: rc_option_editor.cc:643
+#: rc_option_editor.cc:744
 msgid "While Dragging Control Points:"
 msgstr "При перетаскивании контрольных точек:"
 
-#: rc_option_editor.cc:661
+#: rc_option_editor.cc:765
 msgid "Fine adjust using:"
 msgstr ""
 
-#: rc_option_editor.cc:681
+#: rc_option_editor.cc:787
 msgid "Push points using:"
 msgstr ""
 
-#: rc_option_editor.cc:922
+#: rc_option_editor.cc:1027
 msgid "GUI and Font scaling:"
 msgstr "Масштаб интерфейса и шрифта:"
 
-#: rc_option_editor.cc:925
+#: rc_option_editor.cc:1030
 msgid "Default"
 msgstr "По умолчанию"
 
-#: rc_option_editor.cc:951
-msgid "Adjusting the scale require an application restart to re-layout."
-msgstr "После коррекции масштаба необходимо перезапустить приложение"
+#: rc_option_editor.cc:1056
+msgid "Adjusting the scale requires an application restart to re-layout."
+msgstr ""
+
+#: rc_option_editor.cc:1098
+msgid "∞"
+msgstr "∞"
+
+#: rc_option_editor.cc:1099
+msgid "30 sec"
+msgstr "30 с"
+
+#: rc_option_editor.cc:1100
+msgid "1 min"
+msgstr "1 мин"
+
+#: rc_option_editor.cc:1101
+msgid "2 mins"
+msgstr "2 мин"
+
+#: rc_option_editor.cc:1102
+msgid "3 mins"
+msgstr "3 мин"
+
+#: rc_option_editor.cc:1103
+msgid "4 mins"
+msgstr "4 мин"
 
-#: rc_option_editor.cc:992
+#: rc_option_editor.cc:1104
+msgid "5 mins"
+msgstr "5 мин"
+
+#: rc_option_editor.cc:1107
+msgid ""
+"Specify the default timeout for plugin instantiation. Plugins that require "
+"more time to load will be blacklisted. A value of 0 disables the timeout."
+msgstr ""
+
+#: rc_option_editor.cc:1109
+msgid "Scan Time Out:"
+msgstr "Как быстро прекратить сканирование, если нет результатов:"
+
+#: rc_option_editor.cc:1157
 msgid "Waveform Clip Level (dBFS):"
 msgstr "Уровень обрезки волновой формы (dBFS):"
 
-#: rc_option_editor.cc:1046
+#: rc_option_editor.cc:1210
 msgid "Small sessions (4-16 tracks)"
 msgstr "Небольшие сессии (4—16 дорожек)"
 
-#: rc_option_editor.cc:1047
+#: rc_option_editor.cc:1211
 msgid "Medium sessions (16-64 tracks)"
 msgstr "Средние сессии (16—64 дорожек)"
 
-#: rc_option_editor.cc:1048
+#: rc_option_editor.cc:1212
 msgid "Large sessions (64+ tracks)"
 msgstr "Большие сессии (от 64 дорожек и больше)"
 
-#: rc_option_editor.cc:1049
+#: rc_option_editor.cc:1213
 msgid "Custom (set by sliders below)"
 msgstr ""
 
-#: rc_option_editor.cc:1053 export_video_dialog.cc:168
+#: rc_option_editor.cc:1217 export_video_dialog.cc:167
 msgid "Preset:"
 msgstr "Профиль:"
 
-#: rc_option_editor.cc:1065
+#: rc_option_editor.cc:1229
 msgid "Playback (seconds of buffering):"
 msgstr "Воспроизведение (в секундах буферизации):"
 
-#: rc_option_editor.cc:1078
+#: rc_option_editor.cc:1242
 msgid "Recording (seconds of buffering):"
 msgstr "Запись (в секундах буферизации):"
 
-#: rc_option_editor.cc:1156
+#: rc_option_editor.cc:1320
 msgid "programming error: unknown buffering preset string, index = %1"
 msgstr ""
 
-#: rc_option_editor.cc:1188
+#: rc_option_editor.cc:1352
 msgid "Control Surface Protocol"
 msgstr "Устройства управления"
 
-#: rc_option_editor.cc:1197
-msgid "Double-click on a name to edit settings for an enabled protocol"
-msgstr ""
-"Двойной щелчок по названию открывает редактор параметров включённого "
-"протокола"
+#: rc_option_editor.cc:1366
+msgid ""
+"Click to edit the settings for selected protocol ( it must be ENABLED "
+"first ):"
+msgstr "Нажмите для настройки управления (протокол должен быть включен):"
 
-#: rc_option_editor.cc:1354
+#: rc_option_editor.cc:1370
+msgid "Show Protocol Settings"
+msgstr "Показать параметры протокола"
+
+#: rc_option_editor.cc:1493
+msgid "Configuration"
+msgstr "Настройка"
+
+#: rc_option_editor.cc:1546
 msgid "Show Video Export Info before export"
 msgstr "Показывать диалог со справкой об экспорте видео"
 
-#: rc_option_editor.cc:1355
+#: rc_option_editor.cc:1547
 msgid "Show Video Server Startup Dialog"
 msgstr "Показывать диалог с параметрами видеосервера"
 
-#: rc_option_editor.cc:1356
+#: rc_option_editor.cc:1548
 msgid "Advanced Setup (remote video server)"
 msgstr "Дополнительные параметры удалённого видеосервера"
 
-#: rc_option_editor.cc:1364
+#: rc_option_editor.cc:1556
 msgid ""
 "<b>When enabled</b> you can speficify a custom video-server URL and docroot. "
 "- Do not enable this option unless you know what you are doing."
@@ -9623,11 +10026,11 @@ msgstr ""
 "корневой каталог данных. Не используйте эту функцию, если точно не знаете, "
 "что делаете."
 
-#: rc_option_editor.cc:1366
+#: rc_option_editor.cc:1558
 msgid "Video Server URL:"
 msgstr "URL видеосервера:"
 
-#: rc_option_editor.cc:1371
+#: rc_option_editor.cc:1563
 msgid ""
 "Base URL of the video-server including http prefix. This is usually 'http://"
 "hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when "
@@ -9637,11 +10040,11 @@ msgstr ""
 "example.org: 1554/' и по умолчанию 'http://localhost:1554/', когда "
 "видеосервер работает локально"
 
-#: rc_option_editor.cc:1373
+#: rc_option_editor.cc:1565
 msgid "Video Folder:"
 msgstr "Папка с видео:"
 
-#: rc_option_editor.cc:1378
+#: rc_option_editor.cc:1570
 msgid ""
 "Local path to the video-server document-root. Only files below this "
 "directory will be accessible by the video-server. If the server run on a "
@@ -9656,7 +10059,7 @@ msgstr ""
 "используется для местного видео - просмотра и выбора файлов при открытии/"
 "добавлении видеофайла."
 
-#: rc_option_editor.cc:1385
+#: rc_option_editor.cc:1577
 msgid ""
 "<b>When enabled</b> an information window with details is displayed before "
 "the video-export dialog."
@@ -9664,7 +10067,7 @@ msgstr ""
 "<b>Когда включено,</b> перед экспортом видео показывается окно со справочной "
 "информацией"
 
-#: rc_option_editor.cc:1390
+#: rc_option_editor.cc:1582
 msgid ""
 "<b>When enabled</b> the video server is never launched automatically without "
 "confirmation"
@@ -9672,206 +10075,91 @@ msgstr ""
 "<b>Если включено,</b> видеосервер никогда автоматически не запускается без "
 "подтверждения"
 
-#: rc_option_editor.cc:1473
-msgid "Always Display Plugin Scan Progress"
-msgstr "Всегда показывать прогресс сканирования плагинов"
+#: rc_option_editor.cc:1723
+msgid "%1 Preferences"
+msgstr "Параметры %1"
 
-#: rc_option_editor.cc:1474
-msgid "Scan for [new] VST Plugins on Application Start"
-msgstr "Искать новые плагины VST при запуске приложения"
+#: rc_option_editor.cc:1734
+msgid "DSP CPU Utilization"
+msgstr "Использование ЦП"
 
-#: rc_option_editor.cc:1475
-msgid "Scan for AudioUnit Plugins on Application Start"
-msgstr "Искать новые плагины AudioUnit при запуске приложения"
+#: rc_option_editor.cc:1738
+msgid "Signal processing uses"
+msgstr "При обработке используются"
 
-#: rc_option_editor.cc:1476
-msgid "Verbose Plugin Scan"
-msgstr ""
+#: rc_option_editor.cc:1743
+msgid "all but one processor"
+msgstr "Все процессоры кроме одного"
 
-#: rc_option_editor.cc:1487
-msgid "General"
-msgstr "Главное"
+#: rc_option_editor.cc:1744
+msgid "all available processors"
+msgstr "Все доступные процессоры"
 
-#: rc_option_editor.cc:1493 startup.cc:349
-msgid "Scan for Plugins"
-msgstr "Просканировать плагины"
+#: rc_option_editor.cc:1747
+msgid "%1 processors"
+msgstr "%1 процессора"
 
-#: rc_option_editor.cc:1500
-msgid ""
-"<b>When enabled</b> a popup window showing plugin scan progress is displayed "
-"for indexing (cache load) and discovery (detect new plugins)"
-msgstr ""
-"<b>Когда включено,</b> всплывающее окно показывает прогресс поиска и "
-"индексации звуковых плагинов в системе"
+#: rc_option_editor.cc:1750
+msgid "This setting will only take effect when %1 is restarted."
+msgstr "Это изменение вступит в силу при следующем запуске %1."
 
-#: rc_option_editor.cc:1507
-msgid ""
-"Specify the default timeout for plugin instantiation in 1/10 seconds. "
-"Plugins that require more time to load will be blacklisted. A value of 0 "
-"disables the timeout."
-msgstr ""
-"Укажите используемый по умолчанию тайм-аут для инстанцирования плагина в "
-"десятых долях секунды. Плагины, требующие больше времени для загрузки, будут "
-"блокироваться. Если значение равно нулю, тайм-аут отключается."
+#: rc_option_editor.cc:1755
+msgid "Options|Undo"
+msgstr "История действий"
 
-#: rc_option_editor.cc:1509
-msgid "Scan Time Out [deciseconds]"
-msgstr "Тайм-аут сканирования [децисек.]"
+#: rc_option_editor.cc:1762
+msgid "Verify removal of last capture"
+msgstr "Проверять удаление последней записи"
 
-#: rc_option_editor.cc:1517
-msgid "VST"
-msgstr "VST"
+#: rc_option_editor.cc:1767
+msgid "Session Management"
+msgstr "Управление сессиями"
 
-#: rc_option_editor.cc:1523
-msgid "Clear VST Cache"
-msgstr "Очистить кэш VST"
+#: rc_option_editor.cc:1772
+msgid "Make periodic backups of the session file"
+msgstr "Периодически создавать резервные копии файла сессии"
 
-#: rc_option_editor.cc:1527
-msgid "Clear VST Blacklist"
-msgstr "Очистить чёрный список VST"
+#: rc_option_editor.cc:1780
+msgid "Always copy imported files"
+msgstr "Всегда копировать импортируемые файлы"
 
-#: rc_option_editor.cc:1535
-msgid ""
-"<b>When enabled</b> new VST plugins are searched, tested and added to the "
-"cache index on application start. When disabled new plugins will only be "
-"available after triggering a 'Scan' manually"
-msgstr ""
-"<b>Когда включено,</b> при запуске приложения выполняется поиск, "
-"тестирование и добавление новых плагинов VST в индекс кэша. Когда отключено, "
-"новые плагины становятся доступными лишь после запуска сканирования вручную."
+#: rc_option_editor.cc:1787
+msgid "Default folder for new sessions:"
+msgstr "Папка для новых сессий по умолчанию:"
 
-#: rc_option_editor.cc:1538
-msgid "Linux VST Path:"
-msgstr "Размещение Linux VST:"
+#: rc_option_editor.cc:1795
+msgid "Maximum number of recent sessions"
+msgstr "Максимальное число недавних сессий"
 
-#: rc_option_editor.cc:1545
-msgid "Windows VST Path:"
-msgstr "Размещение Windows VST:"
+#: rc_option_editor.cc:1808
+msgid "Click gain level"
+msgstr "Уровень щелчка метронома"
 
-#: rc_option_editor.cc:1554
-msgid ""
-"<b>When enabled</b> additional information for every plugin is added to the "
-"Log Window."
-msgstr ""
-
-#: rc_option_editor.cc:1560
-msgid "Audio Unit"
-msgstr "Audio Unit"
-
-#: rc_option_editor.cc:1569
-msgid ""
-"<b>When enabled</b> Audio Unit Plugins are discovered on application start. "
-"When disabled AU plugins will only be available after triggering a 'Scan' "
-"manually. The first successful scan will enable AU auto-scan, Any crash "
-"during plugin discovery will disable it."
-msgstr ""
-"<b>Когда включено,</b> при запуске программы выполняется поиск плагинов "
-"Audio Unit. Когда отключено, новые плагины AU становятся доступными только "
-"после запуска сканирования вручную. При первом успешном сканировании будет "
-"включено автоматическое сканирование плагинов AU. При любом падении "
-"программы во время сканирования автоматическое сканирование будет отключено."
-
-#: rc_option_editor.cc:1572
-msgid "Clear AU Cache"
-msgstr "Очистить кэш AU"
-
-#: rc_option_editor.cc:1576
-msgid "Clear AU Blacklist"
-msgstr "Очистить чёрный список AU"
-
-#: rc_option_editor.cc:1670
-msgid "Set Windows VST Search Path"
-msgstr "Установка пути поиска Windows VST"
-
-#: rc_option_editor.cc:1685
-msgid "Set Linux VST Search Path"
-msgstr "Установка пути поиска Linux VST"
-
-#: rc_option_editor.cc:1766
-msgid "%1 Preferences"
-msgstr "Параметры %1"
-
-#: rc_option_editor.cc:1778
-msgid "DSP CPU Utilization"
-msgstr "Использование ЦП"
-
-#: rc_option_editor.cc:1782
-msgid "Signal processing uses"
-msgstr "При обработке используются"
-
-#: rc_option_editor.cc:1787
-msgid "all but one processor"
-msgstr "Все процессоры кроме одного"
-
-#: rc_option_editor.cc:1788
-msgid "all available processors"
-msgstr "Все доступные процессоры"
-
-#: rc_option_editor.cc:1791
-msgid "%1 processors"
-msgstr "%1 процессора"
-
-#: rc_option_editor.cc:1794
-msgid "This setting will only take effect when %1 is restarted."
-msgstr "Это изменение вступит в силу при следующем запуске %1."
-
-#: rc_option_editor.cc:1799
-msgid "Options|Undo"
-msgstr "История действий"
-
-#: rc_option_editor.cc:1806
-msgid "Verify removal of last capture"
-msgstr "Проверять удаление последней записи"
-
-#: rc_option_editor.cc:1814
-msgid "Make periodic backups of the session file"
-msgstr "Периодически создавать резервные копии файла сессии"
-
-#: rc_option_editor.cc:1819
-msgid "Session Management"
-msgstr "Управление сессиями"
-
-#: rc_option_editor.cc:1824
-msgid "Always copy imported files"
-msgstr "Всегда копировать импортируемые файлы"
-
-#: rc_option_editor.cc:1831
-msgid "Default folder for new sessions:"
-msgstr "Папка для новых сессий по умолчанию:"
-
-#: rc_option_editor.cc:1839
-msgid "Maximum number of recent sessions"
-msgstr "Максимальное число недавних сессий"
-
-#: rc_option_editor.cc:1852
-msgid "Click gain level"
-msgstr "Уровень щелчка метронома"
-
-#: rc_option_editor.cc:1857 route_time_axis.cc:268 route_time_axis.cc:832
+#: rc_option_editor.cc:1813 route_time_axis.cc:269 route_time_axis.cc:833
 msgid "Automation"
 msgstr "Автоматизация"
 
-#: rc_option_editor.cc:1862
+#: rc_option_editor.cc:1818
 msgid "Thinning factor (larger value => less data)"
 msgstr "Фактор разведения (большее значение => меньше данных)"
 
-#: rc_option_editor.cc:1871
+#: rc_option_editor.cc:1827
 msgid "Automation sampling interval (milliseconds)"
 msgstr "Интервал сэмплирования для автоматизации (мс)"
 
-#: rc_option_editor.cc:1879
+#: rc_option_editor.cc:1835
 msgid "Transport Options"
 msgstr "Параметры транспорта"
 
-#: rc_option_editor.cc:1885
+#: rc_option_editor.cc:1841
 msgid "Keep record-enable engaged on stop"
 msgstr "Готовность к записи сохраняется после остановки"
 
-#: rc_option_editor.cc:1894
+#: rc_option_editor.cc:1850
 msgid "Play loop is a transport mode"
 msgstr "Петля воспроизведения как режим транспорта"
 
-#: rc_option_editor.cc:1899
+#: rc_option_editor.cc:1855
 msgid ""
 "<b>When enabled</b> the loop button does not start playback but forces "
 "playback to always play the loop\n"
@@ -9885,11 +10173,11 @@ msgstr ""
 "<b>Когда выключено,</b> кнопка петли запускает воспроизведение, но при "
 "остановке режим циклического воспроизведения отключается."
 
-#: rc_option_editor.cc:1905
+#: rc_option_editor.cc:1861
 msgid "Stop recording when an xrun occurs"
 msgstr "Останавливать запись при рассинхронизации"
 
-#: rc_option_editor.cc:1910
+#: rc_option_editor.cc:1866
 msgid ""
 "<b>When enabled</b> %1 will stop recording if an over- or underrun is "
 "detected by the audio engine"
@@ -9897,15 +10185,15 @@ msgstr ""
 "<b>Когда включено,</b> %1 остановит запись, если звуковым движком обнаружено "
 "переполнение или опустошение буфера"
 
-#: rc_option_editor.cc:1916
+#: rc_option_editor.cc:1872
 msgid "Create markers where xruns occur"
 msgstr "Создавать маркеры в точках рассинхронизации"
 
-#: rc_option_editor.cc:1925
+#: rc_option_editor.cc:1881
 msgid "Stop at the end of the session"
 msgstr "Останавливаться в конце сессии"
 
-#: rc_option_editor.cc:1930
+#: rc_option_editor.cc:1886
 msgid ""
 "<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the "
 "transport when it reaches the current session end marker\n"
@@ -9918,13 +10206,13 @@ msgstr ""
 "\n"
 "<b>Когда выключено</b>, %1 будет воспроизводить дальше маркера конца сессии."
 
-#: rc_option_editor.cc:1938
+#: rc_option_editor.cc:1894
 msgid "Do seamless looping (not possible when slaved to MTC, LTC etc)"
 msgstr ""
 "Бесшовное циклическое воспроизведение (невозможно, когда Ardour ведом по "
 "MTC, LTC и т.д.)"
 
-#: rc_option_editor.cc:1943
+#: rc_option_editor.cc:1899
 msgid ""
 "<b>When enabled</b> this will loop by reading ahead and wrapping around at "
 "the loop point, preventing any need to do a transport locate at the end of "
@@ -9941,11 +10229,11 @@ msgstr ""
 "обратно в начало цикла, когда %1 достигает конца, что будет часто приводить "
 "к небольшим щелчкам или задержке."
 
-#: rc_option_editor.cc:1951
+#: rc_option_editor.cc:1907
 msgid "Disable per-track record disarm while rolling"
 msgstr "Сделать невозможным отключение готовности к записи при захвате"
 
-#: rc_option_editor.cc:1955
+#: rc_option_editor.cc:1911
 msgid ""
 "<b>When enabled</b> this will prevent you from accidentally stopping "
 "specific tracks recording during a take"
@@ -9953,11 +10241,11 @@ msgstr ""
 "<b>Если включено</b>, вы не сможете нечаянно выключить готовность к записи "
 "во время захвата сигнала"
 
-#: rc_option_editor.cc:1960
+#: rc_option_editor.cc:1916
 msgid "12dB gain reduction during fast-forward and fast-rewind"
 msgstr "Приглушение громкости на 12Дб при перемотке"
 
-#: rc_option_editor.cc:1964
+#: rc_option_editor.cc:1920
 msgid ""
 "This will reduce the unpleasant increase in perceived volume that occurs "
 "when fast-forwarding or rewinding through some kinds of audio"
@@ -9965,19 +10253,56 @@ msgstr ""
 "При перемотке воспринимаемое на слух резкое увеличение громкости будет "
 "нивелировано"
 
-#: rc_option_editor.cc:1968
+#: rc_option_editor.cc:1926
+msgid "Preroll"
+msgstr ""
+
+#: rc_option_editor.cc:1931
+msgid ""
+"The amount of preroll (in seconds) to apply when <b>Play with Preroll</b> is "
+"initiated.\n"
+"\n"
+"If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead "
+"position when a region is selected or trimmed."
+msgstr ""
+
+#: rc_option_editor.cc:1933
+msgid "0 (no pre-roll)"
+msgstr ""
+
+#: rc_option_editor.cc:1934
+msgid "0.1 second"
+msgstr "0,1 с"
+
+#: rc_option_editor.cc:1935
+msgid "0.25 second"
+msgstr "0,25 с"
+
+#: rc_option_editor.cc:1936
+msgid "0.5 second"
+msgstr "0,5 с"
+
+#: rc_option_editor.cc:1937
+msgid "1.0 second"
+msgstr "1 с"
+
+#: rc_option_editor.cc:1938
+msgid "2.0 seconds"
+msgstr "2 с"
+
+#: rc_option_editor.cc:1941
 msgid "Sync/Slave"
 msgstr "Синхронизация и ведомый режим"
 
-#: rc_option_editor.cc:1972
+#: rc_option_editor.cc:1945
 msgid "External timecode source"
 msgstr "Внешний источник синхросигнала"
 
-#: rc_option_editor.cc:1981
+#: rc_option_editor.cc:1954
 msgid "Match session video frame rate to external timecode"
 msgstr "Адаптировать частоту кадров видео в сессии к внешнему тайм-коду"
 
-#: rc_option_editor.cc:1987
+#: rc_option_editor.cc:1960
 msgid ""
 "This option controls the value of the video frame rate <i>while chasing</i> "
 "an external timecode source.\n"
@@ -10000,11 +10325,11 @@ msgstr ""
 "этого индикатор частоты кадров в основном счётчике будет мерцать красным, а "
 "%1 будет конвертировать внешний тайм-код в тайм-код сессии."
 
-#: rc_option_editor.cc:1997
+#: rc_option_editor.cc:1970
 msgid "Sync-lock timecode to clock (disable drift compensation)"
 msgstr "Привязать тайм-код к часам (отключить компенсацию смещения)"
 
-#: rc_option_editor.cc:2003
+#: rc_option_editor.cc:1976
 msgid ""
 "<b>When enabled</b> %1 will never varispeed when slaved to external "
 "timecode. Sync Lock indicates that the selected external timecode source "
@@ -10025,11 +10350,11 @@ msgstr ""
 "<b>Когда выключено,</b> %1 компенсирует потенциальное смещение вне "
 "зависимости от того, разделяет ли источник тайм-кода синхронизацию часов."
 
-#: rc_option_editor.cc:2018
+#: rc_option_editor.cc:1991
 msgid "Lock to 29.9700 fps instead of 30000/1001"
 msgstr "Принудительно использовать 29,9700 к/с вместо 30000/1001"
 
-#: rc_option_editor.cc:2024
+#: rc_option_editor.cc:1997
 msgid ""
 "<b>When enabled</b> the external timecode source is assumed to use 29.97 fps "
 "instead of 30000/1001.\n"
@@ -10052,27 +10377,27 @@ msgstr ""
 "несмотря на её противоречие спецификации, потому что использование именно "
 "29,97 кадров в секунду имеет нулевое смещение тайм-кода.\n"
 
-#: rc_option_editor.cc:2034
+#: rc_option_editor.cc:2007
 msgid "LTC Reader"
 msgstr "Чтение LTC"
 
-#: rc_option_editor.cc:2038
+#: rc_option_editor.cc:2011
 msgid "LTC incoming port"
 msgstr "Порт чтения LTC"
 
-#: rc_option_editor.cc:2053
+#: rc_option_editor.cc:2027
 msgid "LTC Generator"
 msgstr "Генератор LTC"
 
-#: rc_option_editor.cc:2058
+#: rc_option_editor.cc:2032
 msgid "Enable LTC generator"
 msgstr "Включить генератор LTC"
 
-#: rc_option_editor.cc:2065
+#: rc_option_editor.cc:2039
 msgid "Send LTC while stopped"
 msgstr "Отправлять LTC в остановленном состоянии"
 
-#: rc_option_editor.cc:2071
+#: rc_option_editor.cc:2045
 msgid ""
 "<b>When enabled</b> %1 will continue to send LTC information even when the "
 "transport (playhead) is not moving"
@@ -10080,11 +10405,11 @@ msgstr ""
 "<b>Когда включено,</b> %1 продолжит передавать LTC даже когда транспорт "
 "(воспроизведение) не движется"
 
-#: rc_option_editor.cc:2077
+#: rc_option_editor.cc:2051
 msgid "LTC generator level"
 msgstr "Уровень генератора LTC"
 
-#: rc_option_editor.cc:2081
+#: rc_option_editor.cc:2055
 msgid ""
 "Specify the Peak Volume of the generated LTC signal in dbFS. A good value "
 "is  0dBu ^= -18dbFS in an EBU calibrated system"
@@ -10092,394 +10417,418 @@ msgstr ""
 "Укажите пиковую громкость генерируемого сигнала LTC в dbFS. Хорошее качество "
 "это 0dBu ^ =-18dbFS в выщеуказанной EBU калиброванной системе"
 
-#: rc_option_editor.cc:2093
+#: rc_option_editor.cc:2064
+msgid "Make rubberband selection rectangle snap to the grid"
+msgstr "Прямоугольное выделение привязывается к сетке"
+
+#: rc_option_editor.cc:2071
+msgid "Name new markers"
+msgstr "Спрашивать об имени каждого нового маркера"
+
+#: rc_option_editor.cc:2076
+msgid ""
+"If enabled, popup a dialog when a new marker is created to allow its name to "
+"be set as it is created.\n"
+"\n"
+"You can always rename markers by right-clicking on them"
+msgstr ""
+"Если включено, при создании нового маркера будет всплывать диалог, где можно "
+"задать имя маркера.\n"
+"\n"
+"Вы всегда можете позднее переименовать маркеры, щелкнув по ним правой "
+"кнопкой мыши."
+
+#: rc_option_editor.cc:2082
 msgid "Allow dragging of playhead"
 msgstr "Разрешить перетаскивание указателя воспроизведения"
 
-#: rc_option_editor.cc:2101
-msgid "Move relevant automation when audio regions are moved"
-msgstr "Перемещать автоматизацию вместе с областями"
-
-#: rc_option_editor.cc:2109
+#: rc_option_editor.cc:2090
 msgid "Show meters on tracks in the editor"
 msgstr "Показывать индикаторы громкости в дорожках"
 
-#: rc_option_editor.cc:2117
+#: rc_option_editor.cc:2098
 msgid "Display master-meter in the toolbar"
 msgstr "Показывать индикатор громкости мастер-шины в панели"
 
+#: rc_option_editor.cc:2107
+msgid "Show zoom toolbar (if torn off)"
+msgstr "Показывать панель масштаба (если она откреплена)"
+
+#: rc_option_editor.cc:2116
+msgid "Update editor window during drags of the summary"
+msgstr "Обновлять окно редактора при изменениях в панели сводки"
+
 #: rc_option_editor.cc:2124
+msgid "Auto-scroll editor window when dragging near its edges"
+msgstr ""
+"Автоматически прокручивать окно редактора при перетаскивании близко к краям"
+
+#: rc_option_editor.cc:2132
+msgid "Show gain envelopes in audio regions"
+msgstr "Показывать огибающие усиления"
+
+#: rc_option_editor.cc:2133
+msgid "in all modes"
+msgstr "Во всех режимах"
+
+#: rc_option_editor.cc:2134
+msgid "only in Draw and Internal Edit modes"
+msgstr "Только в режимах рисования и правки содержимого"
+
+#: rc_option_editor.cc:2139
+msgid "Editor Behavior"
+msgstr "Поведение редактора"
+
+#: rc_option_editor.cc:2144
+msgid "Move relevant automation when audio regions are moved"
+msgstr "Перемещать автоматизацию вместе с областями"
+
+#: rc_option_editor.cc:2151
 msgid "Default fade shape"
 msgstr "Форма фейда по умолчанию"
 
-#: rc_option_editor.cc:2143
+#: rc_option_editor.cc:2170
 msgid "Regions in active edit groups are edited together"
 msgstr "Области в активных редактируемых группах меняются вместе"
 
-#: rc_option_editor.cc:2144
+#: rc_option_editor.cc:2171
 msgid "whenever they overlap in time"
 msgstr "Когда пересекаются по времени"
 
-#: rc_option_editor.cc:2145
+#: rc_option_editor.cc:2172
 msgid "only if they have identical length, position and origin"
 msgstr "При одинаковой длительности, позиции и происхождении"
 
-#: rc_option_editor.cc:2154
+#: rc_option_editor.cc:2181
 msgid "Layering model"
-msgstr "Способ наслоения"
+msgstr "Способ наслаивания"
 
-#: rc_option_editor.cc:2159
+#: rc_option_editor.cc:2186
 msgid "later is higher"
 msgstr "Более поздние — сверху"
 
-#: rc_option_editor.cc:2160
+#: rc_option_editor.cc:2187
 msgid "manual layering"
 msgstr "Наслаивание вручную"
 
-#: rc_option_editor.cc:2166
-msgid "Make rubberband selection rectangle snap to the grid"
-msgstr "Прямоугольное выделение привязывается к сетке"
+#: rc_option_editor.cc:2192
+msgid "After splitting selected regions, select"
+msgstr "После разделения выбранных областей выбирать"
 
-#: rc_option_editor.cc:2174
-msgid "Show waveforms in regions"
-msgstr "Показывать форму волны в областях"
+#: rc_option_editor.cc:2197
+msgid "no regions"
+msgstr "Не выбирать области"
 
-#: rc_option_editor.cc:2182
-msgid "Show gain envelopes in audio regions"
-msgstr "Показывать огибающие усиления"
+#: rc_option_editor.cc:2200
+msgid "newly-created regions"
+msgstr "Только что созданные области"
 
-#: rc_option_editor.cc:2183
-msgid "in all modes"
-msgstr "Во всех режимах"
+#: rc_option_editor.cc:2204
+msgid "existing selection and newly-created regions"
+msgstr "Как выбранные ранее, так и только что созданные области"
 
-#: rc_option_editor.cc:2184
-msgid "only in Draw and Internal Edit modes"
-msgstr "Только в режимах рисования и правки содержимого"
+#: rc_option_editor.cc:2208
+msgid "Waveforms"
+msgstr "Волновая форма сигнала"
 
-#: rc_option_editor.cc:2191
+#: rc_option_editor.cc:2214
+msgid "Show waveforms in regions"
+msgstr "Показывать форму сигнала в областях"
+
+#: rc_option_editor.cc:2223
+msgid "Show waveforms for audio while it is being recorded"
+msgstr "Показывать форму записываемого сигнала при захвате"
+
+#: rc_option_editor.cc:2230
 msgid "Waveform scale"
 msgstr "Масштаб сигнала"
 
-#: rc_option_editor.cc:2196
+#: rc_option_editor.cc:2235
 msgid "linear"
 msgstr "Линейный"
 
-#: rc_option_editor.cc:2197
+#: rc_option_editor.cc:2236
 msgid "logarithmic"
 msgstr "Логарифмический"
 
-#: rc_option_editor.cc:2203
+#: rc_option_editor.cc:2242
 msgid "Waveform shape"
 msgstr "Форма сигнала"
 
-#: rc_option_editor.cc:2208
+#: rc_option_editor.cc:2247
 msgid "traditional"
 msgstr "Обычная"
 
-#: rc_option_editor.cc:2209
+#: rc_option_editor.cc:2248
 msgid "rectified"
 msgstr "От низа"
 
-#: rc_option_editor.cc:2218
-msgid "Show waveforms for audio while it is being recorded"
-msgstr "Показывать форму сигнала при записи"
-
-#: rc_option_editor.cc:2226
-msgid "Show zoom toolbar"
-msgstr "Показывать панель для управления масштабом"
-
-#: rc_option_editor.cc:2234
-msgid "Update editor window during drags of the summary"
-msgstr "Обновлять окно редактора при изменениях в панели сводки"
-
-#: rc_option_editor.cc:2241
-msgid "Name new markers"
-msgstr "Спрашивать об имени каждого нового маркера"
-
-#: rc_option_editor.cc:2247
-msgid ""
-"If enabled, popup a dialog when a new marker is created to allow its name to "
-"be set as it is created.\n"
-"\n"
-"You can always rename markers by right-clicking on them"
-msgstr ""
-"Если включено, при создании нового маркера будет всплывать диалог, где можно "
-"задать имя маркера.\n"
-"\n"
-"Вы всегда можете позднее переименовать маркеры, щелкнув по ним правой "
-"кнопкой мыши."
-
-#: rc_option_editor.cc:2253
-msgid "Auto-scroll editor window when dragging near its edges"
-msgstr ""
-"Автоматически прокручивать окно редактора при перетаскивании близко к краям"
-
-#: rc_option_editor.cc:2260
-msgid "After splitting selected regions, select"
-msgstr "После разделения выбранных областей выбирать"
-
-#: rc_option_editor.cc:2265
-msgid "no regions"
-msgstr "Не выбирать области"
-
-#: rc_option_editor.cc:2268
-msgid "newly-created regions"
-msgstr "Только что созданные области"
-
-#: rc_option_editor.cc:2272
-msgid "existing selection and newly-created regions"
-msgstr "Как выбранные ранее, так и только что созданные области"
-
-#: rc_option_editor.cc:2279
+#: rc_option_editor.cc:2257
 msgid "Buffering"
 msgstr "Буферизация"
 
-#: rc_option_editor.cc:2287
+#: rc_option_editor.cc:2265
 msgid "Record monitoring handled by"
 msgstr "Мониторинг записи выполняется"
 
-#: rc_option_editor.cc:2293
+#: rc_option_editor.cc:2271
 msgid "via Audio Driver"
 msgstr "Через аудиодрайвер"
 
-#: rc_option_editor.cc:2299
+#: rc_option_editor.cc:2277
 msgid "audio hardware"
 msgstr "Аппаратным обеспечением"
 
-#: rc_option_editor.cc:2306
+#: rc_option_editor.cc:2284
 msgid "Tape machine mode"
 msgstr "Режим плёночного магнитофона"
 
-#: rc_option_editor.cc:2311
+#: rc_option_editor.cc:2290
 msgid "Connection of tracks and busses"
 msgstr "Соединение дорожек и шин"
 
-#: rc_option_editor.cc:2316
+#: rc_option_editor.cc:2295
 msgid "Auto-connect master/monitor busses"
 msgstr "Автоматически соединять шины master/monitor"
 
-#: rc_option_editor.cc:2323
+#: rc_option_editor.cc:2302
 msgid "Connect track inputs"
 msgstr "Соединять входы дорожек"
 
-#: rc_option_editor.cc:2328
+#: rc_option_editor.cc:2307
 msgid "automatically to physical inputs"
 msgstr "Автоматически с физическими входами"
 
-#: rc_option_editor.cc:2329 rc_option_editor.cc:2342
+#: rc_option_editor.cc:2308 rc_option_editor.cc:2321
 msgid "manually"
 msgstr "Вручную"
 
-#: rc_option_editor.cc:2335
+#: rc_option_editor.cc:2314
 msgid "Connect track and bus outputs"
 msgstr "Соединять выходы дорожек и шин"
 
-#: rc_option_editor.cc:2340
+#: rc_option_editor.cc:2319
 msgid "automatically to physical outputs"
 msgstr "Автоматически с физическими выходами"
 
-#: rc_option_editor.cc:2341
+#: rc_option_editor.cc:2320
 msgid "automatically to master bus"
 msgstr "Автоматически с общей шиной"
 
-#: rc_option_editor.cc:2346
+#: rc_option_editor.cc:2326
 msgid "Denormals"
 msgstr "Отклонения сигнала"
 
-#: rc_option_editor.cc:2351
+#: rc_option_editor.cc:2331
 msgid "Use DC bias to protect against denormals"
 msgstr "Использовать смещение для защиты от денормализации"
 
-#: rc_option_editor.cc:2358
+#: rc_option_editor.cc:2338
 msgid "Processor handling"
 msgstr "Что делать с обработчиками"
 
-#: rc_option_editor.cc:2364
+#: rc_option_editor.cc:2344
 msgid "no processor handling"
 msgstr "Ничего не делать"
 
-#: rc_option_editor.cc:2370
+#: rc_option_editor.cc:2350
 msgid "use FlushToZero"
 msgstr "Использовать FlushToZero"
 
-#: rc_option_editor.cc:2377
+#: rc_option_editor.cc:2357
 msgid "use DenormalsAreZero"
 msgstr "Использовать DenormalsAreZero"
 
-#: rc_option_editor.cc:2384
+#: rc_option_editor.cc:2364
 msgid "use FlushToZero and DenormalsAreZero"
 msgstr "Использовать FlushToZero и DenormalsAreZero"
 
-#: rc_option_editor.cc:2400
+#: rc_option_editor.cc:2380
 msgid "Silence plugins when the transport is stopped"
 msgstr "Приглушать плагины при остановке транспорта"
 
-#: rc_option_editor.cc:2408
+#: rc_option_editor.cc:2388
 msgid "Make new plugins active"
 msgstr "Делать новые плагины активными"
 
-#: rc_option_editor.cc:2418
+#: rc_option_editor.cc:2398
 msgid "Enable automatic analysis of audio"
 msgstr "Включить автоматический анализ звука"
 
-#: rc_option_editor.cc:2426
+#: rc_option_editor.cc:2406
 msgid "Replicate missing region channels"
 msgstr "Воссоздавать отсутствующие каналы области"
 
-#: rc_option_editor.cc:2433 rc_option_editor.cc:2435 rc_option_editor.cc:2450
-#: rc_option_editor.cc:2462 rc_option_editor.cc:2474 rc_option_editor.cc:2486
-#: rc_option_editor.cc:2490 rc_option_editor.cc:2498 rc_option_editor.cc:2506
-#: rc_option_editor.cc:2514 rc_option_editor.cc:2516 rc_option_editor.cc:2524
-#: rc_option_editor.cc:2532 rc_option_editor.cc:2540 rc_option_editor.cc:2548
-#: rc_option_editor.cc:2550
+#: rc_option_editor.cc:2413 rc_option_editor.cc:2422 rc_option_editor.cc:2424
+#: rc_option_editor.cc:2432 rc_option_editor.cc:2440 rc_option_editor.cc:2448
+#: rc_option_editor.cc:2466 rc_option_editor.cc:2478 rc_option_editor.cc:2490
+#: rc_option_editor.cc:2492 rc_option_editor.cc:2494 rc_option_editor.cc:2502
+#: rc_option_editor.cc:2510 rc_option_editor.cc:2518 rc_option_editor.cc:2526
+#: rc_option_editor.cc:2528
 msgid "Solo / mute"
 msgstr "Соло/Приглушение"
 
-#: rc_option_editor.cc:2438
-msgid "Solo-in-place mute cut (dB)"
-msgstr "Приглушение сигнала при солировании (dB)"
-
-#: rc_option_editor.cc:2445
+#: rc_option_editor.cc:2417
 msgid "Solo controls are Listen controls"
 msgstr "Управление солированием работает как управление прослушиванием"
 
-#: rc_option_editor.cc:2454
+#: rc_option_editor.cc:2427
+msgid "Exclusive solo"
+msgstr "Эксклюзивное солирование"
+
+#: rc_option_editor.cc:2435
+msgid "Show solo muting"
+msgstr "Показывать приглушение при солировании"
+
+#: rc_option_editor.cc:2443
+msgid "Soloing overrides muting"
+msgstr "Солирование приоритетнее приглушения"
+
+#: rc_option_editor.cc:2451
+msgid "Solo-in-place mute cut (dB)"
+msgstr "Приглушение сигнала при солировании (dB)"
+
+#: rc_option_editor.cc:2458
 msgid "Listen Position"
 msgstr "Положение прослушивания"
 
-#: rc_option_editor.cc:2459
+#: rc_option_editor.cc:2463
 msgid "after-fader (AFL)"
 msgstr "После фейдера (AFL)"
 
-#: rc_option_editor.cc:2460
+#: rc_option_editor.cc:2464
 msgid "pre-fader (PFL)"
 msgstr "До фейдера (PFL)"
 
-#: rc_option_editor.cc:2466
+#: rc_option_editor.cc:2470
 msgid "PFL signals come from"
 msgstr "Источник сигнала PFL"
 
-#: rc_option_editor.cc:2471
+#: rc_option_editor.cc:2475
 msgid "before pre-fader processors"
 msgstr "До послефейдерных обработчиков"
 
-#: rc_option_editor.cc:2472
+#: rc_option_editor.cc:2476
 msgid "pre-fader but after pre-fader processors"
 msgstr "До фейдера, но после предфейдерных обработчиков"
 
-#: rc_option_editor.cc:2478
+#: rc_option_editor.cc:2482
 msgid "AFL signals come from"
 msgstr "Источник сигнала AFL"
 
-#: rc_option_editor.cc:2483
+#: rc_option_editor.cc:2487
 msgid "immediately post-fader"
 msgstr "Сразу после фейдера"
 
-#: rc_option_editor.cc:2484
+#: rc_option_editor.cc:2488
 msgid "after post-fader processors (before pan)"
 msgstr "За послефейдерными обработчиками и до панорамирования"
 
-#: rc_option_editor.cc:2493
-msgid "Exclusive solo"
-msgstr "Эксклюзивное солирование"
-
-#: rc_option_editor.cc:2501
-msgid "Show solo muting"
-msgstr "Показывать приглушение при солировании"
-
-#: rc_option_editor.cc:2509
-msgid "Soloing overrides muting"
-msgstr "Солирование приоритетнее приглушения"
-
-#: rc_option_editor.cc:2514
+#: rc_option_editor.cc:2492
 msgid "Default track / bus muting options"
 msgstr "Приглушение дорожек и шин по умолчанию затрагивает"
 
-#: rc_option_editor.cc:2519
+#: rc_option_editor.cc:2497
 msgid "Mute affects pre-fader sends"
 msgstr "Предфейдерные посылы"
 
-#: rc_option_editor.cc:2527
+#: rc_option_editor.cc:2505
 msgid "Mute affects post-fader sends"
 msgstr "Послефейдерные посылы"
 
-#: rc_option_editor.cc:2535
+#: rc_option_editor.cc:2513
 msgid "Mute affects control outputs"
 msgstr "Выходы мониторинга"
 
-#: rc_option_editor.cc:2543
+#: rc_option_editor.cc:2521
 msgid "Mute affects main outputs"
 msgstr "Основные выходы"
 
-#: rc_option_editor.cc:2548
+#: rc_option_editor.cc:2526
 msgid "Send Routing"
 msgstr "Маршрутизация посылов"
 
-#: rc_option_editor.cc:2553
+#: rc_option_editor.cc:2531
 msgid "Link panners of Aux and External Sends with main panner by default"
 msgstr "По умолчанию связывать внешние посылы с основным регулятором панорамы"
 
-#: rc_option_editor.cc:2561
+#: rc_option_editor.cc:2536
+msgid "MIDI Preferences"
+msgstr "Параметры MIDI"
+
+#: rc_option_editor.cc:2541
 msgid "MIDI read-ahead time (seconds)"
 msgstr "Чтение MIDI с упреждением (в секундах)"
 
-#: rc_option_editor.cc:2579
+#: rc_option_editor.cc:2551
+msgid "Initial program change"
+msgstr "Исходная смена программы"
+
+#: rc_option_editor.cc:2560
+msgid "Display first MIDI bank/program as 0"
+msgstr "Показывать первый банк/программу MIDI как 0"
+
+#: rc_option_editor.cc:2568
+msgid "Never display periodic MIDI messages (MTC, MIDI Clock)"
+msgstr "Никогда не показывать периодические сообщения MIDI (MTC, MIDI Clock)"
+
+#: rc_option_editor.cc:2576
+msgid "Sound MIDI notes as they are selected in the editor"
+msgstr "Воспроизводить выбираемые в редакторе ноты MIDI"
+
+#: rc_option_editor.cc:2584
+msgid "Send MIDI control feedback"
+msgstr "Отправлять отклик на контрольные события MIDI"
+
+#: rc_option_editor.cc:2589
+msgid "MIDI Clock"
+msgstr "MIDI Clock"
+
+#: rc_option_editor.cc:2599
+msgid "MIDI Time Code (MTC)"
+msgstr "Там-код MIDI (MTC)"
+
+#: rc_option_editor.cc:2604
 msgid "Send MIDI Time Code"
 msgstr "Передавать MIDI Time Code"
 
-#: rc_option_editor.cc:2587
+#: rc_option_editor.cc:2612
 msgid "Percentage either side of normal transport speed to transmit MTC"
 msgstr "Процент по обе стороны от нормальной трансп. скорости для передачи MTC"
 
-#: rc_option_editor.cc:2596
+#: rc_option_editor.cc:2618
+msgid "Midi Machine Control (MMC)"
+msgstr "Midi Machine Control (MMC)"
+
+#: rc_option_editor.cc:2623
 msgid "Obey MIDI Machine Control commands"
 msgstr "Выполнять команды MIDI Machine Control"
 
-#: rc_option_editor.cc:2604
+#: rc_option_editor.cc:2631
 msgid "Send MIDI Machine Control commands"
 msgstr "Отправлять команды MIDI Machine Control"
 
-#: rc_option_editor.cc:2612
-msgid "Send MIDI control feedback"
-msgstr "Отправлять отклик на контрольные события MIDI"
-
-#: rc_option_editor.cc:2620
+#: rc_option_editor.cc:2639
 msgid "Inbound MMC device ID"
 msgstr "Идентификатор входящего устройства MMC"
 
-#: rc_option_editor.cc:2629
+#: rc_option_editor.cc:2648
 msgid "Outbound MMC device ID"
 msgstr "Идентификатор выходящего устройства MMC"
 
-#: rc_option_editor.cc:2638
-msgid "Initial program change"
-msgstr "Исходная смена программы"
-
-#: rc_option_editor.cc:2647
-msgid "Display first MIDI bank/program as 0"
-msgstr "Показывать первый банк/программу MIDI как 0"
-
-#: rc_option_editor.cc:2655
-msgid "Never display periodic MIDI messages (MTC, MIDI Clock)"
-msgstr "Никогда не показывать периодические сообщения MIDI (MTC, MIDI Clock)"
-
-#: rc_option_editor.cc:2663
-msgid "Sound MIDI notes as they are selected"
-msgstr "Воспроизводить ноты MIDI при их выделении"
-
-#: rc_option_editor.cc:2668
+#: rc_option_editor.cc:2654
 msgid "Midi Audition"
 msgstr "Прослушивание MIDI"
 
-#: rc_option_editor.cc:2672
+#: rc_option_editor.cc:2658
 msgid "Midi Audition Synth (LV2)"
 msgstr "Инструмент для прослушивания MIDI (LV2)"
 
-#: rc_option_editor.cc:2703 rc_option_editor.cc:2713 rc_option_editor.cc:2715
+#: rc_option_editor.cc:2689 rc_option_editor.cc:2699 rc_option_editor.cc:2701
 msgid "User interaction"
 msgstr "Взаимодействие с пользователем"
 
-#: rc_option_editor.cc:2706
+#: rc_option_editor.cc:2692
 msgid ""
 "Use translations of %1 messages\n"
 "   <i>(requires a restart of %1 to take effect)</i>\n"
@@ -10489,152 +10838,274 @@ msgstr ""
 "   <i>(вступает в силу после перезапуска %1)</i>\n"
 "   <i>(если локализация для вашего языка доступна)</i>"
 
-#: rc_option_editor.cc:2713
+#: rc_option_editor.cc:2699
 msgid "Keyboard"
 msgstr "Клавиатура"
 
-#: rc_option_editor.cc:2723
+#: rc_option_editor.cc:2709
 msgid "Control surface remote ID"
 msgstr "ID для удалённого управления"
 
-#: rc_option_editor.cc:2728
+#: rc_option_editor.cc:2714
 msgid "assigned by user"
 msgstr "Назначенные пользователем"
 
-#: rc_option_editor.cc:2729
-msgid "follows order of mixer"
-msgstr "Следуют порядку микшера"
+#: rc_option_editor.cc:2715
+msgid "follows order of mixer"
+msgstr "Следуют порядку микшера"
+
+#: rc_option_editor.cc:2723
+msgid "General"
+msgstr "Главное"
+
+#: rc_option_editor.cc:2726 startup.cc:351
+msgid "Scan for Plugins"
+msgstr "Просканировать плагины"
+
+#: rc_option_editor.cc:2731
+msgid "Always Display Plugin Scan Progress"
+msgstr "Всегда показывать прогресс сканирования плагинов"
+
+#: rc_option_editor.cc:2737
+msgid ""
+"<b>When enabled</b> a popup window showing plugin scan progress is displayed "
+"for indexing (cache load) and discovery (detect new plugins)"
+msgstr ""
+"<b>Когда включено,</b> всплывающее окно показывает прогресс поиска и "
+"индексации звуковых плагинов в системе"
+
+#: rc_option_editor.cc:2742
+msgid "VST"
+msgstr "VST"
+
+#: rc_option_editor.cc:2746
+msgid "Scan for [new] VST Plugins on Application Start"
+msgstr "Искать новые плагины VST при запуске приложения"
+
+#: rc_option_editor.cc:2752
+msgid ""
+"<b>When enabled</b> new VST plugins are searched, tested and added to the "
+"cache index on application start. When disabled new plugins will only be "
+"available after triggering a 'Scan' manually"
+msgstr ""
+"<b>Когда включено,</b> при запуске приложения выполняется поиск, "
+"тестирование и добавление новых плагинов VST в индекс кэша. Когда отключено, "
+"новые плагины становятся доступными лишь после запуска сканирования вручную."
+
+#: rc_option_editor.cc:2758
+msgid "Verbose Plugin Scan"
+msgstr ""
+
+#: rc_option_editor.cc:2764
+msgid ""
+"<b>When enabled</b> additional information for every plugin is added to the "
+"Log Window."
+msgstr ""
+"<b>Если включено</b>, дополнительная информация о каждом плагине выводится в "
+"окно журнала."
+
+#: rc_option_editor.cc:2772
+msgid "VST Cache:"
+msgstr "Кэш VST:"
+
+#: rc_option_editor.cc:2777
+msgid "VST Blacklist:"
+msgstr "Чёрный список VST:"
+
+#: rc_option_editor.cc:2784
+msgid "Linux VST Path:"
+msgstr "Размещение Linux VST:"
+
+#: rc_option_editor.cc:2789 rc_option_editor.cc:2802
+msgid "Path:"
+msgstr "Расположение:"
+
+#: rc_option_editor.cc:2798
+msgid "Windows VST Path:"
+msgstr "Размещение Windows VST:"
+
+#: rc_option_editor.cc:2808
+msgid "Audio Unit"
+msgstr "Audio Unit"
+
+#: rc_option_editor.cc:2812
+msgid "Scan for AudioUnit Plugins on Application Start"
+msgstr "Искать новые плагины AudioUnit при запуске приложения"
+
+#: rc_option_editor.cc:2818
+msgid ""
+"<b>When enabled</b> Audio Unit Plugins are discovered on application start. "
+"When disabled AU plugins will only be available after triggering a 'Scan' "
+"manually. The first successful scan will enable AU auto-scan, Any crash "
+"during plugin discovery will disable it."
+msgstr ""
+"<b>Когда включено,</b> при запуске программы выполняется поиск плагинов "
+"Audio Unit. Когда отключено, новые плагины AU становятся доступными только "
+"после запуска сканирования вручную. При первом успешном сканировании будет "
+"включено автоматическое сканирование плагинов AU. При любом падении "
+"программы во время сканирования автоматическое сканирование будет отключено."
+
+#: rc_option_editor.cc:2823
+msgid "AU Cache:"
+msgstr "Кэш AU:"
+
+#: rc_option_editor.cc:2828
+msgid "AU Blacklist:"
+msgstr "Чёрный список AU:"
+
+#: rc_option_editor.cc:2832
+msgid "Plugin GUI"
+msgstr "Интерфейс плагинов"
+
+#: rc_option_editor.cc:2836
+msgid "Automatically open the plugin GUI when adding a new plugin"
+msgstr "Автоматически открывать окно плагина после его добавления"
 
-#: rc_option_editor.cc:2746
-msgid "Possibly improve slow graphical performance"
-msgstr ""
+#: rc_option_editor.cc:2847
+msgid "Disable Graphics Hardware Acceleration (requires restart)"
+msgstr "Отключить аппаратное ускорение графики (требует перезапуска)"
 
-#: rc_option_editor.cc:2751
-msgid "This requires restarting %1 before having an effect"
+#: rc_option_editor.cc:2853
+msgid ""
+"Render large parts of the application user-interface in software, instead of "
+"using 2D-graphics acceleration.\n"
+"This requires restarting %1 before having an effect"
 msgstr ""
 
-#: rc_option_editor.cc:2752 rc_option_editor.cc:2755 rc_option_editor.cc:2764
-#: rc_option_editor.cc:2773 rc_option_editor.cc:2783 rc_option_editor.cc:2808
-#: rc_option_editor.cc:2823 rc_option_editor.cc:2836 rc_option_editor.cc:2845
+#: rc_option_editor.cc:2854 rc_option_editor.cc:2866 rc_option_editor.cc:2869
+#: rc_option_editor.cc:2878 rc_option_editor.cc:2887 rc_option_editor.cc:2906
+#: rc_option_editor.cc:2922 rc_option_editor.cc:2938 rc_option_editor.cc:2952
+#: rc_option_editor.cc:2961
 msgid "Preferences|GUI"
 msgstr "Интерфейс"
 
-#: rc_option_editor.cc:2758
+#: rc_option_editor.cc:2860
+msgid "Possibly improve slow graphical performance (requires restart)"
+msgstr ""
+
+#: rc_option_editor.cc:2865
+msgid ""
+"Disables hardware gradient rendering on buggy video drivers (\"buggy "
+"gradients patch\").\n"
+"This requires restarting %1 before having an effect"
+msgstr ""
+
+#: rc_option_editor.cc:2872
 msgid "Graphically indicate mouse pointer hovering over various widgets"
 msgstr "Подсвечивать элементы интерфейса под указателем мыши"
 
-#: rc_option_editor.cc:2767
+#: rc_option_editor.cc:2881
 msgid "Show tooltips if mouse hovers over a control"
 msgstr "Показывать всплывающие подсказки к элементам интерфейса"
 
-#: rc_option_editor.cc:2776
+#: rc_option_editor.cc:2890
 msgid "Use name highlight bars in region displays (requires a restart)"
 msgstr "Подсвечивать названия областей (требует перезапуска)"
 
-#: rc_option_editor.cc:2789
-msgid "update transport clock display at FPS instead of every 100ms"
-msgstr "Обновлять часы транспорта по FPS, а не каждые 100 мс"
+#: rc_option_editor.cc:2898
+msgid "Update transport clock display at FPS instead of every 100ms"
+msgstr "Обновлять счётчик транспорта по FPS, а не каждые 100 мс"
 
-#: rc_option_editor.cc:2799
+#: rc_option_editor.cc:2913
 msgid "Waveform image cache size (megabytes)"
 msgstr "Размер кэша для графики волновой формы (МБ)"
 
-#: rc_option_editor.cc:2807
+#: rc_option_editor.cc:2921
 msgid ""
 "Increasing the cache size uses more memory to store waveform images, which "
 "can improve graphical performance."
 msgstr ""
 
-#: rc_option_editor.cc:2814
+#: rc_option_editor.cc:2929
 msgid "Lock timeout (seconds)"
 msgstr "Тайм-аут блокировки (секунды)"
 
-#: rc_option_editor.cc:2822
+#: rc_option_editor.cc:2937
 msgid "Lock GUI after this many idle seconds (zero to never lock)"
 msgstr ""
 "Блокировка GUI после этого количества секунд простоя\n"
 "(0 - никогда не блокировать)"
 
-#: rc_option_editor.cc:2838
+#: rc_option_editor.cc:2954
 msgid "Mixer Strip"
 msgstr "Полоса микшера"
 
-#: rc_option_editor.cc:2848
+#: rc_option_editor.cc:2964
 msgid "Use narrow strips in the mixer by default"
 msgstr "Использовать тонкие полоски в микшере по умолчанию"
 
-#: rc_option_editor.cc:2853 rc_option_editor.cc:2867 rc_option_editor.cc:2884
-#: rc_option_editor.cc:2900 rc_option_editor.cc:2916 rc_option_editor.cc:2930
-#: rc_option_editor.cc:2956 rc_option_editor.cc:2974 rc_option_editor.cc:2985
-#: rc_option_editor.cc:2992 rc_option_editor.cc:2994
+#: rc_option_editor.cc:2969 rc_option_editor.cc:2983 rc_option_editor.cc:3000
+#: rc_option_editor.cc:3016 rc_option_editor.cc:3032 rc_option_editor.cc:3046
+#: rc_option_editor.cc:3072 rc_option_editor.cc:3090 rc_option_editor.cc:3101
+#: rc_option_editor.cc:3108 rc_option_editor.cc:3110
 msgid "Preferences|Metering"
 msgstr "Замер"
 
-#: rc_option_editor.cc:2857
+#: rc_option_editor.cc:2973
 msgid "Peak hold time"
 msgstr "Удерживание пика"
 
-#: rc_option_editor.cc:2863
+#: rc_option_editor.cc:2979
 msgid "short"
 msgstr "Короткое"
 
-#: rc_option_editor.cc:2864
+#: rc_option_editor.cc:2980
 msgid "medium"
 msgstr "Среднее"
 
-#: rc_option_editor.cc:2865
+#: rc_option_editor.cc:2981
 msgid "long"
 msgstr "Долгое"
 
-#: rc_option_editor.cc:2871
+#: rc_option_editor.cc:2987
 msgid "DPM fall-off"
 msgstr "Скорость спадания"
 
-#: rc_option_editor.cc:2877
+#: rc_option_editor.cc:2993
 msgid "slowest [6.6dB/sec]"
 msgstr "Самое медленное [6,6 Дб/с]"
 
-#: rc_option_editor.cc:2878
+#: rc_option_editor.cc:2994
 msgid "slow [8.6dB/sec] (BBC PPM, EBU PPM)"
 msgstr "Медленное [8,6 Дб/с] (BBC PPM, EBU PPM)"
 
-#: rc_option_editor.cc:2879
+#: rc_option_editor.cc:2995
 msgid "moderate [12.0dB/sec] (DIN)"
 msgstr "Умеренное [12 Дб/с] (DIN)"
 
-#: rc_option_editor.cc:2880
+#: rc_option_editor.cc:2996
 msgid "medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"
 msgstr "Среднее [13,3 Дб/с] (EBU Digi PPM, IRT Digi PPM)"
 
-#: rc_option_editor.cc:2881
+#: rc_option_editor.cc:2997
 msgid "fast [20dB/sec]"
 msgstr "Быстрое [20 Дб/с]"
 
-#: rc_option_editor.cc:2882
+#: rc_option_editor.cc:2998
 msgid "very fast [32dB/sec]"
 msgstr "Очень быстрое [32 Дб/с]"
 
-#: rc_option_editor.cc:2888
+#: rc_option_editor.cc:3004
 msgid "Meter line-up level; 0dBu"
 msgstr "Точка выравнивания индикатора; 0dBu"
 
-#: rc_option_editor.cc:2893 rc_option_editor.cc:2909
+#: rc_option_editor.cc:3009 rc_option_editor.cc:3025
 msgid "-24dBFS (SMPTE US: 4dBu = -20dBFS)"
 msgstr "-24dBFS (SMPTE US: 4dBu = -20dBFS)"
 
-#: rc_option_editor.cc:2894 rc_option_editor.cc:2910
+#: rc_option_editor.cc:3010 rc_option_editor.cc:3026
 msgid "-20dBFS (SMPTE RP.0155)"
 msgstr "-20dBFS (SMPTE RP.0155)"
 
-#: rc_option_editor.cc:2895 rc_option_editor.cc:2911
+#: rc_option_editor.cc:3011 rc_option_editor.cc:3027
 msgid "-18dBFS (EBU, BBC)"
 msgstr "-18dBFS (EBU, BBC)"
 
-#: rc_option_editor.cc:2896 rc_option_editor.cc:2912
+#: rc_option_editor.cc:3012 rc_option_editor.cc:3028
 msgid "-15dBFS (DIN)"
 msgstr "-15dBFS (DIN)"
 
-#: rc_option_editor.cc:2898
+#: rc_option_editor.cc:3014
 msgid ""
 "Configure meter-marks and color-knee point for dBFS scale DPM, set reference "
 "level for IEC1/Nordic, IEC2 PPM and VU meter."
@@ -10642,51 +11113,51 @@ msgstr ""
 "Настройка измер. маркеров и цвета точки узла для dBFS масштабирования шкалы "
 "DPM, установка эталонного уровня для IEC1/Nordic, PPM и VU-метра."
 
-#: rc_option_editor.cc:2904
+#: rc_option_editor.cc:3020
 msgid "IEC1/DIN Meter line-up level; 0dBu"
 msgstr "Точка выравнивания индикатора IEC1/DIN; 0dBu"
 
-#: rc_option_editor.cc:2914
+#: rc_option_editor.cc:3030
 msgid "Reference level for IEC1/DIN meter."
 msgstr "Референсный уровень индикатора IEC1/DIN"
 
-#: rc_option_editor.cc:2920
+#: rc_option_editor.cc:3036
 msgid "VU Meter standard"
 msgstr "Стандарт индикатора VU"
 
-#: rc_option_editor.cc:2925
+#: rc_option_editor.cc:3041
 msgid "0VU = -2dBu (France)"
 msgstr "0VU = -2dBu (Франция)"
 
-#: rc_option_editor.cc:2926
+#: rc_option_editor.cc:3042
 msgid "0VU = 0dBu (North America, Australia)"
 msgstr "0VU = 0dBu (Северная Америка, Австралия)"
 
-#: rc_option_editor.cc:2927
+#: rc_option_editor.cc:3043
 msgid "0VU = +4dBu (standard)"
 msgstr "0VU = +4dBu (стандарт)"
 
-#: rc_option_editor.cc:2928
+#: rc_option_editor.cc:3044
 msgid "0VU = +8dBu"
 msgstr "0VU = +8dBu"
 
-#: rc_option_editor.cc:2934
+#: rc_option_editor.cc:3050
 msgid "Peak threshold [dBFS]"
 msgstr "Порог пика (dbFS)"
 
-#: rc_option_editor.cc:2943
+#: rc_option_editor.cc:3059
 msgid "Default Meter Type for Master Bus"
 msgstr "Тип индикатора по умолчанию для мастер-шины"
 
-#: rc_option_editor.cc:2961
+#: rc_option_editor.cc:3077
 msgid "Default Meter Type for Busses"
 msgstr "Тип индикатора по умолчанию для шин"
 
-#: rc_option_editor.cc:2978
+#: rc_option_editor.cc:3094
 msgid "Default Meter Type for Tracks"
 msgstr "Тип индикатора по умолчанию для дорожек"
 
-#: rc_option_editor.cc:2990
+#: rc_option_editor.cc:3106
 msgid ""
 "Specify the audio signal level in dbFS at and above which the meter-peak "
 "indicator will flash red."
@@ -10694,67 +11165,75 @@ msgstr ""
 "Укажите в dbFS номинальный уровень звукового сигнала и пикового, когда "
 "индикатор мигает красным цветом."
 
-#: rc_option_editor.cc:2997
+#: rc_option_editor.cc:3113
 msgid "LED meter style"
 msgstr "Индикатор в стиле LED"
 
-#: rc_option_editor.cc:3005
+#: rc_option_editor.cc:3121
 msgid "Theme"
 msgstr "Тема"
 
-#: region_editor.cc:79
+#: rc_option_editor.cc:3194
+msgid "Set Linux VST Search Path"
+msgstr "Установка пути поиска Linux VST"
+
+#: rc_option_editor.cc:3208
+msgid "Set Windows VST Search Path"
+msgstr "Установка пути поиска Windows VST"
+
+#: region_editor.cc:81
 msgid "audition this region"
 msgstr "Прослушивание области"
 
-#: region_editor.cc:88 region_layering_order_editor.cc:75
+#: region_editor.cc:90 region_layering_order_editor.cc:75
 msgid "Position:"
 msgstr "Позиция:"
 
-#: region_editor.cc:90 add_video_dialog.cc:155
+#: region_editor.cc:92 add_video_dialog.cc:155
 msgid "End:"
 msgstr "Конец:"
 
-#: region_editor.cc:92 sfdb_ui.cc:144
+#: region_editor.cc:94 sfdb_ui.cc:145
 msgid "Length:"
 msgstr "Длительность:"
 
-#: region_editor.cc:94
+#: region_editor.cc:96
 msgid "Sync point (relative to region):"
 msgstr "Точка синхронизации (относительно области):"
 
-#: region_editor.cc:96
+#: region_editor.cc:98
 msgid "Sync point (absolute):"
 msgstr "Точка синхронизации (абсолютная):"
 
-#: region_editor.cc:98
+#: region_editor.cc:100
 msgid "File start:"
 msgstr "Начало файла:"
 
-#: region_editor.cc:102
+#: region_editor.cc:104
 msgid "Sources:"
 msgstr "Источники:"
 
-#: region_editor.cc:104
+#: region_editor.cc:106
 msgid "Source:"
 msgstr "Источник:"
 
-#: region_editor.cc:166
+#: region_editor.cc:168
 msgid "Region '%1'"
 msgstr "Область %1"
 
-#: region_editor.cc:277
+#: region_editor.cc:279
 msgid "change region start position"
 msgstr "Смена позиции начала области"
 
-#: region_editor.cc:297
+#: region_editor.cc:299
 msgid "change region end position"
 msgstr "Смена позиции конца области"
 
-#: region_editor.cc:320
+#: region_editor.cc:322
 msgid "change region length"
 msgstr "Смена длительности области"
 
-#: region_editor.cc:414 region_editor.cc:426
+#: region_editor.cc:416 region_editor.cc:428
 msgid "change region sync point"
 msgstr "Смена синхронизатора областей"
 
@@ -10774,34 +11253,34 @@ msgstr "Дорожка:"
 msgid "Choose Top Region"
 msgstr "Выбрать верхнюю область"
 
-#: region_view.cc:277
+#: region_view.cc:270
 msgid "SilenceText"
 msgstr "Текст без сведений"
 
-#: region_view.cc:292 region_view.cc:311
+#: region_view.cc:285 region_view.cc:304
 msgid "minutes"
 msgstr "минут"
 
-#: region_view.cc:295 region_view.cc:314
+#: region_view.cc:288 region_view.cc:307
 msgid "msecs"
 msgstr "мс"
 
-#: region_view.cc:298 region_view.cc:317
+#: region_view.cc:291 region_view.cc:310
 msgid "secs"
 msgstr "с"
 
-#: region_view.cc:301
+#: region_view.cc:294
 msgid "%1 silent segment"
 msgid_plural "%1 silent segments"
 msgstr[0] "%1 тихий сегмент"
 msgstr[1] "%1 тихих сегмента"
 msgstr[2] "%1 тихих сегментов"
 
-#: region_view.cc:303
+#: region_view.cc:296
 msgid "shortest = %1 %2"
 msgstr "кратчайший = %1 %2"
 
-#: region_view.cc:320
+#: region_view.cc:313
 msgid ""
 "\n"
 "  (shortest audible segment = %1 %2)"
@@ -10877,7 +11356,7 @@ msgstr "Функция определения"
 msgid "Trigger gap"
 msgstr "Интервал триггера"
 
-#: rhythm_ferret.cc:122 strip_silence_dialog.cc:64
+#: rhythm_ferret.cc:122 strip_silence_dialog.cc:65
 msgid "Threshold"
 msgstr "Порог"
 
@@ -10921,7 +11400,7 @@ msgstr "Готовность к записи"
 msgid "Active state"
 msgstr "Активное состояние"
 
-#: route_group_dialog.cc:53 route_group_dialog.cc:82 theme_manager.cc:92
+#: route_group_dialog.cc:53 route_group_dialog.cc:82 theme_manager.cc:87
 msgid "Color"
 msgstr "Цвет"
 
@@ -10970,292 +11449,292 @@ msgstr "НЕТ ДОРОЖЕК"
 msgid "No Track or Bus Selected"
 msgstr "Нет выбранных дорожек или шин"
 
-#: route_time_axis.cc:104
+#: route_time_axis.cc:105
 msgid "RTAV|G"
 msgstr "Г"
 
-#: route_time_axis.cc:105
+#: route_time_axis.cc:106
 msgid "RTAV|P"
 msgstr "П"
 
-#: route_time_axis.cc:106
+#: route_time_axis.cc:107
 msgid "RTAV|A"
 msgstr "А"
 
-#: route_time_axis.cc:183
+#: route_time_axis.cc:184
 msgid "Record (Right-click for Step Edit)"
 msgstr "Запись (правая клавиша мыши активирует пошаговый ввод)"
 
-#: route_time_axis.cc:186
+#: route_time_axis.cc:187
 msgid "Record"
 msgstr "Запись"
 
-#: route_time_axis.cc:256
+#: route_time_axis.cc:257
 msgid "Route Group"
 msgstr "Группа маршрутизации"
 
-#: route_time_axis.cc:266
+#: route_time_axis.cc:267
 msgid "MIDI Controllers and Automation"
 msgstr "MIDI-контроллеры и автоматизация"
 
-#: route_time_axis.cc:497
+#: route_time_axis.cc:498
 msgid "Show All Automation"
 msgstr "Показать всю автоматизацию"
 
-#: route_time_axis.cc:500
+#: route_time_axis.cc:501
 msgid "Show Existing Automation"
 msgstr "Показать существующую автоматизацию"
 
-#: route_time_axis.cc:503
+#: route_time_axis.cc:504
 msgid "Hide All Automation"
 msgstr "Скрыть всю автоматизацию"
 
-#: route_time_axis.cc:512
+#: route_time_axis.cc:513
 msgid "Processor automation"
 msgstr "Автоматизация обработчика"
 
-#: route_time_axis.cc:519
+#: route_time_axis.cc:520
 msgid "Fader"
 msgstr "Фейдер"
 
-#: route_time_axis.cc:546
+#: route_time_axis.cc:547
 msgid "Pan"
 msgstr "Панорама"
 
-#: route_time_axis.cc:637
+#: route_time_axis.cc:638
 msgid "Overlaid"
 msgstr "Перекрывают друг друга"
 
-#: route_time_axis.cc:643
+#: route_time_axis.cc:644
 msgid "Stacked"
 msgstr "В стопке"
 
-#: route_time_axis.cc:651
+#: route_time_axis.cc:652
 msgid "Layers"
 msgstr "Слои"
 
-#: route_time_axis.cc:720
+#: route_time_axis.cc:721
 msgid "Automatic (based on I/O connections)"
 msgstr "Автоматическое (по соединениям входа-выхода)"
 
-#: route_time_axis.cc:729
+#: route_time_axis.cc:730
 msgid "(Currently: Existing Material)"
 msgstr "(Сейчас: с записанным материалом)"
 
-#: route_time_axis.cc:732
+#: route_time_axis.cc:733
 msgid "(Currently: Capture Time)"
 msgstr "(Сейчас: по времени захвата)"
 
-#: route_time_axis.cc:740
-msgid "Align With Existing Material"
-msgstr "С записанным материалом"
+#: route_time_axis.cc:741
+msgid "Align with Existing Material"
+msgstr ""
 
-#: route_time_axis.cc:745
-msgid "Align With Capture Time"
-msgstr "По времени захвата"
+#: route_time_axis.cc:746
+msgid "Align with Capture Time"
+msgstr ""
 
-#: route_time_axis.cc:750
+#: route_time_axis.cc:751
 msgid "Alignment"
 msgstr "Выравнивание"
 
-#: route_time_axis.cc:785
+#: route_time_axis.cc:786
 msgid "Normal Mode"
 msgstr "Обычный режим"
 
-#: route_time_axis.cc:791
+#: route_time_axis.cc:792
 msgid "Tape Mode"
 msgstr "Плёночный режим"
 
-#: route_time_axis.cc:797
+#: route_time_axis.cc:798
 msgid "Non-Layered Mode"
 msgstr "Бесслойный режим"
 
-#: route_time_axis.cc:803
+#: route_time_axis.cc:804
 msgid "Record Mode"
 msgstr "Режим записи"
 
-#: route_time_axis.cc:810 route_time_axis.cc:1801
+#: route_time_axis.cc:811 route_time_axis.cc:1806
 msgid "Playlist"
 msgstr "Список"
 
-#: route_time_axis.cc:1104
+#: route_time_axis.cc:1109
 msgid "Rename Playlist"
 msgstr "Переименовать список воспроизведения"
 
-#: route_time_axis.cc:1105
+#: route_time_axis.cc:1110
 msgid "New name for playlist:"
 msgstr "Новое название списка воспроизведения:"
 
-#: route_time_axis.cc:1190
+#: route_time_axis.cc:1195
 msgid "New Copy Playlist"
 msgstr "Новая копия списка воспроизведения"
 
-#: route_time_axis.cc:1191 route_time_axis.cc:1244
+#: route_time_axis.cc:1196 route_time_axis.cc:1249
 msgid "Name for new playlist:"
 msgstr "Название нового списка воспроизведения:"
 
-#: route_time_axis.cc:1243
+#: route_time_axis.cc:1248
 msgid "New Playlist"
 msgstr "Новый список воспроизведения"
 
-#: route_time_axis.cc:1447
+#: route_time_axis.cc:1452
 msgid "You cannot create a track with that name as it is reserved for %1"
 msgstr ""
 "Вы не можете добавить дорожку с названием, которое зарезервировано для %1"
 
-#: route_time_axis.cc:1690
+#: route_time_axis.cc:1695
 msgid "New Copy..."
 msgstr "Создать копию..."
 
-#: route_time_axis.cc:1694
+#: route_time_axis.cc:1699
 msgid "New Take"
 msgstr "Новый дубль"
 
-#: route_time_axis.cc:1695
+#: route_time_axis.cc:1700
 msgid "Copy Take"
 msgstr "Скопировать дубль"
 
-#: route_time_axis.cc:1700
+#: route_time_axis.cc:1705
 msgid "Clear Current"
 msgstr "Очистить текущий"
 
-#: route_time_axis.cc:1703
-msgid "Select From All..."
-msgstr "Выбрать из всех..."
+#: route_time_axis.cc:1708
+msgid "Select from All..."
+msgstr ""
 
-#: route_time_axis.cc:1791
+#: route_time_axis.cc:1796
 msgid "Take: %1.%2"
 msgstr "Дубль: %1.%2"
 
-#: route_time_axis.cc:2197 selection.cc:1007 selection.cc:1061
+#: route_time_axis.cc:2202 selection.cc:1009 selection.cc:1063
 msgid "programming error: "
 msgstr "Ошибка в программе: "
 
-#: route_time_axis.cc:2613
+#: route_time_axis.cc:2622
 msgid "Underlays"
 msgstr "Подслойка"
 
-#: route_time_axis.cc:2616
+#: route_time_axis.cc:2625
 msgid "Remove \"%1\""
 msgstr "Удалить «%1»"
 
-#: route_time_axis.cc:2666 route_time_axis.cc:2703
+#: route_time_axis.cc:2675 route_time_axis.cc:2712
 msgid "programming error: underlay reference pointer pairs are inconsistent!"
 msgstr "Ошибка в программе: пары подложка и указатель ссылки несовместимы!"
 
-#: route_time_axis.cc:2730
+#: route_time_axis.cc:2739
 msgid "After-fade listen (AFL)"
 msgstr "Прослушивание после фейдера (AFL)"
 
-#: route_time_axis.cc:2734
+#: route_time_axis.cc:2743
 msgid "Pre-fade listen (PFL)"
 msgstr "Прослушивание до фейдера (PFL)"
 
-#: route_ui.cc:142
+#: route_ui.cc:153
 msgid "Mute this track"
 msgstr "Приглушить эту дорожку"
 
-#: route_ui.cc:146
+#: route_ui.cc:157
 msgid "Mute other (non-soloed) tracks"
 msgstr "Приглушить другие (не солирующие) дорожки"
 
-#: route_ui.cc:152
+#: route_ui.cc:163
 msgid "Enable recording on this track"
 msgstr "Включить готовность к записи этой дорожки"
 
-#: route_ui.cc:160
+#: route_ui.cc:171
 msgid "make mixer strips show sends to this bus"
 msgstr "Показывать в полосках микшера посылы к этой шине"
 
-#: route_ui.cc:165
+#: route_ui.cc:176
 msgid "Monitor input"
 msgstr "Мониторинг входа"
 
-#: route_ui.cc:171
+#: route_ui.cc:182
 msgid "Monitor playback"
 msgstr "Мониторинг воспроизведения"
 
-#: route_ui.cc:678
+#: route_ui.cc:691
 msgid "Not connected to AudioEngine - cannot engage record"
 msgstr "Не подключено к AudioEngine.  Нельзя записывать."
 
-#: route_ui.cc:877
+#: route_ui.cc:890
 msgid "Step Entry"
 msgstr "Пошаговый ввод"
 
-#: route_ui.cc:950
+#: route_ui.cc:963
 msgid "Assign all tracks (prefader)"
 msgstr "Назначить всем дорожкам (до фейдера)"
 
-#: route_ui.cc:954
+#: route_ui.cc:967
 msgid "Assign all tracks and buses (prefader)"
 msgstr "Назначить всем дорожкам и шинам (до фейдера)"
 
-#: route_ui.cc:958
+#: route_ui.cc:971
 msgid "Assign all tracks (postfader)"
 msgstr "Назначить всем дорожкам (после фейдера)"
 
-#: route_ui.cc:962
+#: route_ui.cc:975
 msgid "Assign all tracks and buses (postfader)"
 msgstr "Назначить всем дорожкам и шинам (после фейдера)"
 
-#: route_ui.cc:966
+#: route_ui.cc:979
 msgid "Assign selected tracks (prefader)"
 msgstr "Назначить выбранным дорожкам (до фейдера)"
 
-#: route_ui.cc:970
+#: route_ui.cc:983
 msgid "Assign selected tracks and buses (prefader)"
 msgstr "Назначить выбранным дорожкам и шинам (до фейдера)"
 
-#: route_ui.cc:973
+#: route_ui.cc:986
 msgid "Assign selected tracks (postfader)"
 msgstr "Назначить выбранным дорожкам (после фейдера)"
 
-#: route_ui.cc:977
+#: route_ui.cc:990
 msgid "Assign selected tracks and buses (postfader)"
 msgstr "Назначить выбранным дорожкам и шинам (после фейдера)"
 
-#: route_ui.cc:980
+#: route_ui.cc:993
 msgid "Copy track/bus gains to sends"
 msgstr "Скопировать фейдеры дорожки/шины в посылы"
 
-#: route_ui.cc:981
+#: route_ui.cc:994
 msgid "Set sends gain to -inf"
 msgstr "Установка посылает усиление на -inf"
 
-#: route_ui.cc:982
+#: route_ui.cc:995
 msgid "Set sends gain to 0dB"
 msgstr "Установка посылает усиление на 0dB"
 
-#: route_ui.cc:1301
+#: route_ui.cc:1314
 msgid "Solo Isolate"
 msgstr "Изолировать соло"
 
-#: route_ui.cc:1308
+#: route_ui.cc:1321
 msgid "Solo Safe"
 msgstr "Блокировка солирования"
 
-#: route_ui.cc:1330
+#: route_ui.cc:1343
 msgid "Pre Fader Sends"
 msgstr "Посылки префейдера"
 
-#: route_ui.cc:1336
+#: route_ui.cc:1349
 msgid "Post Fader Sends"
 msgstr "Посылки постфейдера"
 
-#: route_ui.cc:1342
+#: route_ui.cc:1355
 msgid "Control Outs"
 msgstr "Контрольные выходы"
 
-#: route_ui.cc:1348
+#: route_ui.cc:1361
 msgid "Main Outs"
 msgstr "Главные выходы"
 
-#: route_ui.cc:1485
+#: route_ui.cc:1527
 msgid "Color Selection"
 msgstr "Выбор цвета"
 
-#: route_ui.cc:1550
+#: route_ui.cc:1592
 msgid ""
 "The use of colons (':') is discouraged in track and bus names.\n"
 "Do you want to use this new name?"
@@ -11263,51 +11742,51 @@ msgstr ""
 "Использование двоеточия в названиях дорожек и шин не поощряется.\n"
 "Вы точно хотите оставить двоеточие?"
 
-#: route_ui.cc:1554
+#: route_ui.cc:1596
 msgid "Use the new name"
 msgstr "Использовать новое имя"
 
-#: route_ui.cc:1555
+#: route_ui.cc:1597
 msgid "Re-edit the name"
 msgstr "Повторно изменить название"
 
-#: route_ui.cc:1568
+#: route_ui.cc:1610
 msgid "Rename Track"
 msgstr "Переименование дорожки"
 
-#: route_ui.cc:1570
+#: route_ui.cc:1612
 msgid "Rename Bus"
 msgstr "Переименование шины"
 
-#: route_ui.cc:1638
+#: route_ui.cc:1680
 msgid ": comment editor"
 msgstr ": Редактор комментариев"
 
-#: route_ui.cc:1804
+#: route_ui.cc:1852
 msgid " latency"
 msgstr " задержка"
 
-#: route_ui.cc:1817
+#: route_ui.cc:1892
 msgid "Cannot create route template directory %1"
 msgstr "Не удалось создать папку с шаблонами маршрутизации %1"
 
-#: route_ui.cc:1823
+#: route_ui.cc:1898
 msgid "Save As Template"
 msgstr "Сохранить как шаблон"
 
-#: route_ui.cc:1824
+#: route_ui.cc:1899
 msgid "Template name:"
 msgstr "Название шаблона:"
 
-#: route_ui.cc:1905
+#: route_ui.cc:1976
 msgid "Remote Control ID"
 msgstr "ID для удалённого управления"
 
-#: route_ui.cc:1915
+#: route_ui.cc:1986
 msgid "Remote control ID:"
 msgstr "ID для удалённого управления:"
 
-#: route_ui.cc:1929
+#: route_ui.cc:2000
 msgid ""
 "The remote control ID of %1 is: %2\n"
 "\n"
@@ -11319,15 +11798,15 @@ msgstr ""
 "\n"
 "%3 не может получить другой ID."
 
-#: route_ui.cc:1933
+#: route_ui.cc:2004
 msgid "the master bus"
 msgstr "Мастер-шина"
 
-#: route_ui.cc:1933
+#: route_ui.cc:2004
 msgid "the monitor bus"
 msgstr "Шина мониторинга"
 
-#: route_ui.cc:1935
+#: route_ui.cc:2006
 msgid ""
 "The remote control ID of %5 is: %2\n"
 "\n"
@@ -11346,7 +11825,7 @@ msgstr ""
 "%3Используйте вкладку пользовательской интеракции  окна Установки, если вы "
 "хотите изменить это %4"
 
-#: route_ui.cc:1992
+#: route_ui.cc:2063
 msgid ""
 "Left-click to invert (phase reverse) channel %1 of this track.  Right-click "
 "to show menu."
@@ -11354,7 +11833,7 @@ msgstr ""
 "Щелчком левой клавиши мыши инвертируется (инверсия фазы) \n"
 "канал %1 этой дорожки. По правой клавише вызывается меню."
 
-#: route_ui.cc:1994
+#: route_ui.cc:2065
 msgid "Click to show a menu of channels for inversion (phase reverse)"
 msgstr "Кликните для проказа меню каналов для инверсии (реверс фазы)"
 
@@ -11398,122 +11877,130 @@ msgstr "В папке сессии"
 msgid "Send "
 msgstr "Посыл"
 
-#: session_dialog.cc:61
+#: session_dialog.cc:71
 msgid "Session Setup"
 msgstr "Настройка сессии"
 
-#: session_dialog.cc:66
+#: session_dialog.cc:76
 msgid "Advanced options ..."
 msgstr "Дополнительные параметры"
 
-#: session_dialog.cc:263
+#: session_dialog.cc:163 session_dialog.cc:394
+msgid "Recent Sessions"
+msgstr "Недавние сессии"
+
+#: session_dialog.cc:311
+msgid "Sample Rate"
+msgstr "Частота сэмплирования"
+
+#: session_dialog.cc:312
+msgid "File Resolution"
+msgstr "Разрядность"
+
+#: session_dialog.cc:313
+msgid "Last Modified"
+msgstr "Дата модификации"
+
+#: session_dialog.cc:338
 msgid "New Session"
 msgstr "Создать сессию"
 
-#: session_dialog.cc:301
+#: session_dialog.cc:376
 msgid "Check the website for more..."
 msgstr "Проверьте веб-сайт для более..."
 
-#: session_dialog.cc:304
+#: session_dialog.cc:379
 msgid "Click to open the program website in your web browser"
 msgstr "Нажмите, чтобы открыть веб-сайт программы в веб-браузере"
 
-#: session_dialog.cc:324
-msgid "Sample Rate"
-msgstr "Частота сэмплирования"
-
-#: session_dialog.cc:325
-msgid "Disk Format"
-msgstr "Формат диска"
-
-#: session_dialog.cc:343
+#: session_dialog.cc:401
 msgid "Select session file"
 msgstr "Выберите файл сессии"
 
-#: session_dialog.cc:358
+#: session_dialog.cc:414
 msgid "Other Sessions"
 msgstr "Другие сессии"
 
-#: session_dialog.cc:384
+#: session_dialog.cc:421
+msgid "Safe Mode: Disable all Plugins"
+msgstr "Безопасный режим: отключить все плагины"
+
+#: session_dialog.cc:451
 msgid "Open"
 msgstr "Открыть"
 
-#: session_dialog.cc:451
+#: session_dialog.cc:518
 msgid "Session name:"
 msgstr "Название сессии:"
 
-#: session_dialog.cc:473
+#: session_dialog.cc:540
 msgid "Create session folder in:"
 msgstr "Создать папку сессии в:"
 
-#: session_dialog.cc:496
+#: session_dialog.cc:561
 msgid "Select folder for session"
 msgstr "Выберите папку для сессии"
 
-#: session_dialog.cc:525
+#: session_dialog.cc:588
 msgid "Use this template"
 msgstr "Использовать этот шаблон"
 
-#: session_dialog.cc:528
+#: session_dialog.cc:591
 msgid "no template"
 msgstr "Без шаблона"
 
-#: session_dialog.cc:663 session_dialog.cc:699
-msgid "32 bit float"
-msgstr "32 bit float"
+#: session_dialog.cc:743 session_dialog.cc:790
+msgid "32-bit float"
+msgstr "32-bit float"
 
-#: session_dialog.cc:666 session_dialog.cc:702
-msgid "24 bit"
-msgstr "24 бита"
+#: session_dialog.cc:746 session_dialog.cc:793
+msgid "24-bit"
+msgstr "24-bit"
 
-#: session_dialog.cc:669 session_dialog.cc:705
-msgid "16 bit"
-msgstr "16 bit"
+#: session_dialog.cc:749 session_dialog.cc:796
+msgid "16-bit"
+msgstr "16-bit"
 
-#: session_dialog.cc:747 session_dialog.cc:748 session_dialog.cc:749
+#: session_dialog.cc:874 session_dialog.cc:875 session_dialog.cc:876
 msgid "channels"
 msgstr "канал(-ов)"
 
-#: session_dialog.cc:763
+#: session_dialog.cc:890
 msgid "<b>Busses</b>"
 msgstr "<b>Шины</b>"
 
-#: session_dialog.cc:764
+#: session_dialog.cc:891
 msgid "<b>Inputs</b>"
 msgstr "<b>Входы</b>"
 
-#: session_dialog.cc:765
+#: session_dialog.cc:892
 msgid "<b>Outputs</b>"
 msgstr "<b>Выходы</b>"
 
-#: session_dialog.cc:773
+#: session_dialog.cc:900
 msgid "Create master bus"
 msgstr "Создать мастер-шину"
 
-#: session_dialog.cc:783
+#: session_dialog.cc:910
 msgid "Automatically connect to physical inputs"
 msgstr "Автоматически подключить к физическим входам"
 
-#: session_dialog.cc:790 session_dialog.cc:849
+#: session_dialog.cc:917 session_dialog.cc:976
 msgid "Use only"
 msgstr "Использовать только"
 
-#: session_dialog.cc:843
+#: session_dialog.cc:970
 msgid "Automatically connect outputs"
 msgstr "Автоматически подключить выходы"
 
-#: session_dialog.cc:865
+#: session_dialog.cc:992
 msgid "... to master bus"
 msgstr "... к мастер-шине"
 
-#: session_dialog.cc:875
+#: session_dialog.cc:1002
 msgid "... to physical outputs"
 msgstr "... к физическим выходам"
 
-#: session_import_dialog.cc:65
-msgid "Import from Session"
-msgstr "Импортировать из сессии"
-
 #: session_import_dialog.cc:74
 msgid "Elements"
 msgstr "Элементы"
@@ -11880,165 +12367,181 @@ msgid "Destructive crossfade length"
 msgstr "Длительность разрушающего кроссфейда"
 
 #: session_option_editor.cc:146
+msgid "Declick when transport starts and stops"
+msgstr ""
+
+#: session_option_editor.cc:153
+msgid "Declick when monitor state changes"
+msgstr ""
+
+#: session_option_editor.cc:160
 msgid "Region fades active"
 msgstr "Фейды области активны"
 
-#: session_option_editor.cc:153
+#: session_option_editor.cc:167
 msgid "Region fades visible"
 msgstr "Фейды области видны"
 
-#: session_option_editor.cc:160 session_option_editor.cc:173
-#: session_option_editor.cc:187
+#: session_option_editor.cc:174 session_option_editor.cc:187
+#: session_option_editor.cc:208
 msgid "Media"
 msgstr "Данные"
 
-#: session_option_editor.cc:160
+#: session_option_editor.cc:174
 msgid "Audio file format"
 msgstr "Формат звуковых файлов"
 
-#: session_option_editor.cc:164
+#: session_option_editor.cc:178
 msgid "Sample format"
 msgstr "Формат сэмплов"
 
-#: session_option_editor.cc:169
+#: session_option_editor.cc:183
 msgid "32-bit floating point"
 msgstr "32-bit floating point"
 
-#: session_option_editor.cc:170
+#: session_option_editor.cc:184
 msgid "24-bit integer"
 msgstr "24-bit integer"
 
-#: session_option_editor.cc:171
+#: session_option_editor.cc:185
 msgid "16-bit integer"
 msgstr "16-bit integer"
 
-#: session_option_editor.cc:177
+#: session_option_editor.cc:191
 msgid "File type"
 msgstr "Тип файлов"
 
-#: session_option_editor.cc:182
-msgid "Broadcast WAVE"
-msgstr "Broadcast WAVE"
+#: session_option_editor.cc:196
+msgid "Broadcast WAVE (4GB size limit)"
+msgstr "Broadcast WAVE (ограничение до 4Гб)"
 
-#: session_option_editor.cc:183
-msgid "WAVE"
-msgstr "WAVE"
+#: session_option_editor.cc:198
+msgid "Broadcast RF64"
+msgstr "Broadcast RF64"
 
-#: session_option_editor.cc:184
+#: session_option_editor.cc:200
+msgid "WAVE (4GB size limit)"
+msgstr "WAVE (ограничение до 4Гб)"
+
+#: session_option_editor.cc:201
 msgid "WAVE-64"
 msgstr "WAVE-64"
 
-#: session_option_editor.cc:189
+#: session_option_editor.cc:205
+msgid "RF64 (WAV compatible)"
+msgstr "RF64 (совместим с WAV)"
+
+#: session_option_editor.cc:210
 msgid "File locations"
 msgstr "Расположение файлов"
 
-#: session_option_editor.cc:191
+#: session_option_editor.cc:212
 msgid "Search for audio files in:"
 msgstr "Где искать звуковые файлы:"
 
-#: session_option_editor.cc:197
+#: session_option_editor.cc:218
 msgid "Search for MIDI files in:"
 msgstr "Где искать файлы MIDI:"
 
-#: session_option_editor.cc:206 session_option_editor.cc:218
-#: session_option_editor.cc:228 session_option_editor.cc:239
+#: session_option_editor.cc:227 session_option_editor.cc:239
+#: session_option_editor.cc:249 session_option_editor.cc:260
 msgid "Filenames"
 msgstr "Имена файлов"
 
-#: session_option_editor.cc:206
+#: session_option_editor.cc:227
 msgid "File Naming"
 msgstr "Именовать файлы"
 
-#: session_option_editor.cc:212
+#: session_option_editor.cc:233
 msgid "Prefix Track number"
 msgstr "Ставить в префикс номер дорожки"
 
-#: session_option_editor.cc:217
+#: session_option_editor.cc:238
 msgid ""
 "Adds the current track number to the beginning of the recorded file name."
 msgstr "Добавляет текущий номер дорожки к началу записанного имени файла."
 
-#: session_option_editor.cc:222
+#: session_option_editor.cc:243
 msgid "Prefix Take Name"
 msgstr "Ставить в префикс имя дубля"
 
-#: session_option_editor.cc:227
+#: session_option_editor.cc:248
 msgid "Adds the Take Name to the beginning of the recorded file name."
 msgstr "Добавляет взятое имя в начало имени файла записи."
 
-#: session_option_editor.cc:232
+#: session_option_editor.cc:253
 msgid "Take Name"
 msgstr "Имя дубля"
 
-#: session_option_editor.cc:245
+#: session_option_editor.cc:266
 msgid ""
 "Track Input Monitoring automatically follows transport state (\"auto-input\")"
 msgstr ""
 "Мониторинг входа дорожки автоматически следует состоянию транспорта "
 "(«автовход»)"
 
-#: session_option_editor.cc:252
+#: session_option_editor.cc:273
 msgid "Use monitor section in this session"
 msgstr "Использовать секцию мониторинга в этой сессии"
 
-#: session_option_editor.cc:257 session_option_editor.cc:259
-#: session_option_editor.cc:266 session_option_editor.cc:273
-#: session_option_editor.cc:280 session_option_editor.cc:282
-#: session_option_editor.cc:289 session_option_editor.cc:296
-#: session_option_editor.cc:303 session_option_editor.cc:310
-#: session_option_editor.cc:312
+#: session_option_editor.cc:278 session_option_editor.cc:280
+#: session_option_editor.cc:287 session_option_editor.cc:294
+#: session_option_editor.cc:301 session_option_editor.cc:303
+#: session_option_editor.cc:310 session_option_editor.cc:317
+#: session_option_editor.cc:324 session_option_editor.cc:331
+#: session_option_editor.cc:333
 msgid "Meterbridge"
 msgstr "Панель индикаторов"
 
-#: session_option_editor.cc:257
+#: session_option_editor.cc:278
 msgid "Route Display"
 msgstr "Показывать в маршрутизации"
 
-#: session_option_editor.cc:261
+#: session_option_editor.cc:282
 msgid "Show Midi Tracks"
 msgstr "MIDI-дорожки"
 
-#: session_option_editor.cc:268
+#: session_option_editor.cc:289
 msgid "Show Busses"
 msgstr "Шины"
 
-#: session_option_editor.cc:275
+#: session_option_editor.cc:296
 msgid "Include Master Bus"
 msgstr "Мастер-шина"
 
-#: session_option_editor.cc:280
+#: session_option_editor.cc:301
 msgid "Button Area"
 msgstr "Показывать в кнопках"
 
-#: session_option_editor.cc:284
+#: session_option_editor.cc:305
 msgid "Rec-enable Button"
 msgstr "Переключатель записываемости"
 
-#: session_option_editor.cc:291
+#: session_option_editor.cc:312
 msgid "Mute Button"
 msgstr "Переключатель приглушения"
 
-#: session_option_editor.cc:298
+#: session_option_editor.cc:319
 msgid "Solo Button"
 msgstr "Переключатель солирования"
 
-#: session_option_editor.cc:305
+#: session_option_editor.cc:326
 msgid "Monitor Buttons"
 msgstr "Кнопки монитора"
 
-#: session_option_editor.cc:310
+#: session_option_editor.cc:331
 msgid "Name Labels"
 msgstr "Показывать в метках имён"
 
-#: session_option_editor.cc:314
+#: session_option_editor.cc:335
 msgid "Track Name"
 msgstr "Название дорожи"
 
-#: session_option_editor.cc:325
+#: session_option_editor.cc:346
 msgid "MIDI region copies are independent"
 msgstr "Копии MIDI-областей независимы"
 
-#: session_option_editor.cc:332
+#: session_option_editor.cc:353
 msgid ""
 "Policy for handling overlapping notes\n"
 " on the same MIDI channel"
@@ -12046,220 +12549,215 @@ msgstr ""
 "Политика обработки перекрывающихся\n"
 "нот на одном и том же MIDI-канале"
 
-#: session_option_editor.cc:337
+#: session_option_editor.cc:358
 msgid "never allow them"
 msgstr "Никогда не допускать их"
 
-#: session_option_editor.cc:338
+#: session_option_editor.cc:359
 msgid "don't do anything in particular"
 msgstr "Ничего не делать"
 
-#: session_option_editor.cc:339
+#: session_option_editor.cc:360
 msgid "replace any overlapped existing note"
 msgstr "Заменять любые перекрывающиеся ноты"
 
-#: session_option_editor.cc:340
+#: session_option_editor.cc:361
 msgid "shorten the overlapped existing note"
 msgstr "Укорачивать существующую ноту"
 
-#: session_option_editor.cc:341
+#: session_option_editor.cc:362
 msgid "shorten the overlapping new note"
 msgstr "Укорачивать добавляемую ноту"
 
-#: session_option_editor.cc:342
+#: session_option_editor.cc:363
 msgid "replace both overlapping notes with a single note"
 msgstr "Заменять обе ноты одной новой"
 
-#: session_option_editor.cc:346
+#: session_option_editor.cc:367
 msgid "Glue to bars and beats"
 msgstr "Приклевание к тактам и долям"
 
-#: session_option_editor.cc:350
+#: session_option_editor.cc:371
 msgid "Glue new markers to bars and beats"
 msgstr "Приклеивать новые маркеры к тактам и долям"
 
-#: session_option_editor.cc:357
+#: session_option_editor.cc:378
 msgid "Glue new regions to bars and beats"
 msgstr "Приклеивать новые области к тактам и долям"
 
-#: session_option_editor.cc:362
+#: session_option_editor.cc:383
 msgid "Defaults"
 msgstr "По умолчанию"
 
-#: session_option_editor.cc:364
+#: session_option_editor.cc:385
 msgid "Use these settings as defaults"
 msgstr "Используйте эти настройки, как по умолчанию"
 
-#: sfdb_ui.cc:89 sfdb_ui.cc:109 sfdb_ui.cc:118
+#: sfdb_ui.cc:90 sfdb_ui.cc:110 sfdb_ui.cc:119
 msgid "as new tracks"
 msgstr "как новые дорожки"
 
-#: sfdb_ui.cc:91 sfdb_ui.cc:111
+#: sfdb_ui.cc:92 sfdb_ui.cc:112
 msgid "to selected tracks"
 msgstr "в выделенные дорожки"
 
-#: sfdb_ui.cc:93 sfdb_ui.cc:113
+#: sfdb_ui.cc:94 sfdb_ui.cc:114
 msgid "to region list"
 msgstr "в список областей"
 
-#: sfdb_ui.cc:95 sfdb_ui.cc:115
+#: sfdb_ui.cc:96 sfdb_ui.cc:116
 msgid "as new tape tracks"
 msgstr "как новые плёночные дорожки"
 
-#: sfdb_ui.cc:99
+#: sfdb_ui.cc:100
 msgid "programming error: unknown import mode string %1"
 msgstr "Ошибка в программе: неизвестная строка режима импорта %1"
 
-#: sfdb_ui.cc:126
+#: sfdb_ui.cc:127
 msgid "Auto-play"
 msgstr "Автовоспр."
 
-#: sfdb_ui.cc:134 sfdb_ui.cc:323
+#: sfdb_ui.cc:135 sfdb_ui.cc:324
 msgid "<b>Sound File Information</b>"
 msgstr "<b>Информация о файле</b>"
 
-#: sfdb_ui.cc:146
+#: sfdb_ui.cc:147
 msgid "Timestamp:"
 msgstr "Отметка времени:"
 
-#: sfdb_ui.cc:148
+#: sfdb_ui.cc:149
 msgid "Format:"
 msgstr "Формат:"
 
-#: sfdb_ui.cc:187 sfdb_ui.cc:652
+#: sfdb_ui.cc:188 sfdb_ui.cc:658
 msgid "Tags:"
 msgstr "Метки:"
 
-#: sfdb_ui.cc:292 sfdb_ui.cc:408
+#: sfdb_ui.cc:293 sfdb_ui.cc:409
 msgid "Could not read file: %1 (%2)."
 msgstr "Не удалось прочитать файл: %1 (%2)"
 
-#: sfdb_ui.cc:296
+#: sfdb_ui.cc:297
 msgid "<b>Midi File Information</b>"
 msgstr "<b>Сведения о MIDI файле<b>"
 
-#: sfdb_ui.cc:457
+#: sfdb_ui.cc:458
 msgid "Could not access soundfile: "
 msgstr "Файл недоступен: "
 
-#: sfdb_ui.cc:529
+#: sfdb_ui.cc:530
 msgid "SoundFileBox: Could not tokenize string: "
 msgstr "SoundFileBox: Не удалось разметить строку: "
 
-#: sfdb_ui.cc:549 sfdb_ui.cc:551
+#: sfdb_ui.cc:550 sfdb_ui.cc:552
 msgid "Search"
 msgstr "Искать"
 
-#: sfdb_ui.cc:575
+#: sfdb_ui.cc:581
 msgid "Audio and MIDI files"
 msgstr "Звуковые и MIDI-файлы"
 
-#: sfdb_ui.cc:578
+#: sfdb_ui.cc:584
 msgid "Audio files"
 msgstr "Звуковые файлы"
 
-#: sfdb_ui.cc:581
+#: sfdb_ui.cc:587
 msgid "MIDI files"
 msgstr "Файлы MIDI"
 
-#: sfdb_ui.cc:584 add_video_dialog.cc:123
+#: sfdb_ui.cc:590 add_video_dialog.cc:123
 msgid "All files"
 msgstr "Все файлы"
 
-#: sfdb_ui.cc:603 add_video_dialog.cc:246
+#: sfdb_ui.cc:609 add_video_dialog.cc:246
 msgid "Browse Files"
 msgstr "Обзор файлов"
 
-#: sfdb_ui.cc:632
+#: sfdb_ui.cc:638
 msgid "Paths"
 msgstr "Расположения"
 
-#: sfdb_ui.cc:641
+#: sfdb_ui.cc:647
 msgid "Search Tags"
 msgstr "Поиск по меткам"
 
-#: sfdb_ui.cc:657
+#: sfdb_ui.cc:663
 msgid "Sort:"
 msgstr "Критерий сортировки:"
 
-#: sfdb_ui.cc:665
+#: sfdb_ui.cc:671
 msgid "Longest"
 msgstr "Более длинные"
 
-#: sfdb_ui.cc:666
+#: sfdb_ui.cc:672
 msgid "Shortest"
 msgstr "Более короткие"
 
-#: sfdb_ui.cc:667
+#: sfdb_ui.cc:673
 msgid "Newest"
 msgstr "Более новые"
 
-#: sfdb_ui.cc:668
+#: sfdb_ui.cc:674
 msgid "Oldest"
 msgstr "Более старые"
 
-#: sfdb_ui.cc:669
+#: sfdb_ui.cc:675
 msgid "Most downloaded"
 msgstr "Чаще скачиваемые"
 
-#: sfdb_ui.cc:670
+#: sfdb_ui.cc:676
 msgid "Least downloaded"
 msgstr "Реже скачиваемые"
 
-#: sfdb_ui.cc:671
+#: sfdb_ui.cc:677
 msgid "Highest rated"
 msgstr "Выше оценённые"
 
-#: sfdb_ui.cc:672
+#: sfdb_ui.cc:678
 msgid "Lowest rated"
 msgstr "Ниже оценённые"
 
-#: sfdb_ui.cc:677
+#: sfdb_ui.cc:683
 msgid "More"
 msgstr "Ещё"
 
-#: sfdb_ui.cc:681
+#: sfdb_ui.cc:687
 msgid "Similar"
 msgstr "Дубликат"
 
-#: sfdb_ui.cc:693
+#: sfdb_ui.cc:699
 msgid "ID"
 msgstr "ID"
 
-#: sfdb_ui.cc:694 add_video_dialog.cc:83
+#: sfdb_ui.cc:700 add_video_dialog.cc:83
 msgid "Filename"
 msgstr "Имя файла"
 
-#: sfdb_ui.cc:696
+#: sfdb_ui.cc:702
 msgid "Duration"
 msgstr "Длительность"
 
-#: sfdb_ui.cc:697
+#: sfdb_ui.cc:703
 msgid "Size"
 msgstr "Размер"
 
-#: sfdb_ui.cc:698
+#: sfdb_ui.cc:704
 msgid "Samplerate"
 msgstr "Частота сэмплирования"
 
-#: sfdb_ui.cc:699
+#: sfdb_ui.cc:705
 msgid "License"
 msgstr "Лицензия"
 
-#: sfdb_ui.cc:717
+#: sfdb_ui.cc:723
 msgid "Search Freesound"
 msgstr "Поиск по Freesound"
 
-#: sfdb_ui.cc:737
-msgid "Press to import selected files and close this window"
-msgstr "Нажмите, чтобы импортировать выбранные файлы и закрыть это окно"
-
-#: sfdb_ui.cc:738
-msgid "Press to import selected files and leave this window open"
-msgstr ""
-"Нажмите, чтобы импортировать выбранные файлы и оставить это окно открытым"
-
 #: sfdb_ui.cc:739
+msgid "Press to import selected files"
+msgstr "Нажмите для импорта выбранных файлов"
+
+#: sfdb_ui.cc:740
 msgid "Press to close this window without importing any files"
 msgstr "Нажмите, чтобы закрыть это окно, ничего не импортируя"
 
@@ -12294,39 +12792,39 @@ msgstr "МБ"
 msgid "GB"
 msgstr "ГБ"
 
-#: sfdb_ui.cc:1424 sfdb_ui.cc:1737 sfdb_ui.cc:1800 sfdb_ui.cc:1818
+#: sfdb_ui.cc:1429 sfdb_ui.cc:1734 sfdb_ui.cc:1795 sfdb_ui.cc:1813
 msgid "one track per file"
 msgstr "Одна дорожка на файл"
 
-#: sfdb_ui.cc:1427 sfdb_ui.cc:1801 sfdb_ui.cc:1819
+#: sfdb_ui.cc:1432 sfdb_ui.cc:1796 sfdb_ui.cc:1814
 msgid "one track per channel"
 msgstr "Одна дорожка на канал"
 
-#: sfdb_ui.cc:1435 sfdb_ui.cc:1803 sfdb_ui.cc:1820
+#: sfdb_ui.cc:1440 sfdb_ui.cc:1798 sfdb_ui.cc:1815
 msgid "sequence files"
 msgstr "Файлы последовательности"
 
-#: sfdb_ui.cc:1438 sfdb_ui.cc:1808
+#: sfdb_ui.cc:1443 sfdb_ui.cc:1803
 msgid "all files in one track"
 msgstr "Все файлы в одну дорожку"
 
-#: sfdb_ui.cc:1439 sfdb_ui.cc:1802
+#: sfdb_ui.cc:1444 sfdb_ui.cc:1797
 msgid "merge files"
 msgstr "Объединить файлы"
 
-#: sfdb_ui.cc:1445 sfdb_ui.cc:1805
+#: sfdb_ui.cc:1450 sfdb_ui.cc:1800
 msgid "one region per file"
 msgstr "Одна область на файл"
 
-#: sfdb_ui.cc:1448 sfdb_ui.cc:1806
+#: sfdb_ui.cc:1453 sfdb_ui.cc:1801
 msgid "one region per channel"
 msgstr "Одна область на канал"
 
-#: sfdb_ui.cc:1453 sfdb_ui.cc:1807 sfdb_ui.cc:1821
+#: sfdb_ui.cc:1458 sfdb_ui.cc:1802 sfdb_ui.cc:1816
 msgid "all files in one region"
 msgstr "Все файлы в одной области"
 
-#: sfdb_ui.cc:1520
+#: sfdb_ui.cc:1525
 msgid ""
 "One or more of the selected files\n"
 "cannot be used by %1"
@@ -12334,104 +12832,104 @@ msgstr ""
 "Один или более выбранных файлов\n"
 "не могут быть использованы в %1"
 
-#: sfdb_ui.cc:1664
+#: sfdb_ui.cc:1669
 msgid "Copy files to session"
 msgstr "Скопировать файлы в сессию"
 
-#: sfdb_ui.cc:1681 sfdb_ui.cc:1858
+#: sfdb_ui.cc:1688 sfdb_ui.cc:1856
 msgid "file timestamp"
 msgstr "По отметке времени файла"
 
-#: sfdb_ui.cc:1682 sfdb_ui.cc:1860
+#: sfdb_ui.cc:1689 sfdb_ui.cc:1858
 msgid "edit point"
 msgstr "По курсору редактора"
 
-#: sfdb_ui.cc:1683 sfdb_ui.cc:1862
+#: sfdb_ui.cc:1690 sfdb_ui.cc:1860
 msgid "playhead"
 msgstr "По указателю воспр."
 
-#: sfdb_ui.cc:1684
+#: sfdb_ui.cc:1691
 msgid "session start"
 msgstr "В начало сессии"
 
-#: sfdb_ui.cc:1690
-msgid "<b>Add files as ...</b>"
-msgstr "<b>Добавить файлы как...</b>"
+#: sfdb_ui.cc:1697
+msgid "<b>Add files ...</b>"
+msgstr "<b>Добавить файлы...</b>"
 
-#: sfdb_ui.cc:1712
+#: sfdb_ui.cc:1709
 msgid "<b>Insert at</b>"
 msgstr "<b>Куда вставить</b>"
 
-#: sfdb_ui.cc:1725
+#: sfdb_ui.cc:1722
 msgid "<b>Mapping</b>"
 msgstr "<b>Способ вставки</b>"
 
-#: sfdb_ui.cc:1743
+#: sfdb_ui.cc:1740
 msgid "<b>Conversion quality</b>"
 msgstr "<b>Качество преобразования:</b>"
 
-#: sfdb_ui.cc:1755
+#: sfdb_ui.cc:1752
 msgid "<b>Instrument</b>"
 msgstr "<b>Инструмент</b>"
 
-#: sfdb_ui.cc:1767 sfdb_ui.cc:1874
+#: sfdb_ui.cc:1764 sfdb_ui.cc:1872
 msgid "Best"
 msgstr "Наилучшее"
 
-#: sfdb_ui.cc:1768 sfdb_ui.cc:1876
+#: sfdb_ui.cc:1765 sfdb_ui.cc:1874
 msgid "Good"
 msgstr "Хорошее"
 
-#: sfdb_ui.cc:1769 sfdb_ui.cc:1878
+#: sfdb_ui.cc:1766 sfdb_ui.cc:1876
 msgid "Quick"
 msgstr "Быстрое"
 
-#: sfdb_ui.cc:1771
+#: sfdb_ui.cc:1768
 msgid "Fastest"
 msgstr "Быстрее всего"
 
-#: shuttle_control.cc:56
+#: shuttle_control.cc:57
 msgid "Shuttle speed control (Context-click for options)"
 msgstr "Контроль скорости воспроизведения (параметры — в контекстном меню)"
 
-#: shuttle_control.cc:183
+#: shuttle_control.cc:184
 msgid "Percent"
 msgstr "Проценты"
 
-#: shuttle_control.cc:191
+#: shuttle_control.cc:192
 msgid "Units"
 msgstr "Единица измерения"
 
-#: shuttle_control.cc:197 shuttle_control.cc:620
+#: shuttle_control.cc:198 shuttle_control.cc:633
 msgid "Sprung"
 msgstr "Прыжок"
 
-#: shuttle_control.cc:201 shuttle_control.cc:623
+#: shuttle_control.cc:202 shuttle_control.cc:636
 msgid "Wheel"
 msgstr "Переход"
 
-#: shuttle_control.cc:235
+#: shuttle_control.cc:236
 msgid "Maximum speed"
 msgstr "Макс. скорость"
 
-#: shuttle_control.cc:579
+#: shuttle_control.cc:239
+msgid "Reset to 100%"
+msgstr "Вернуться к 100%"
+
+#: shuttle_control.cc:592
 msgid "Playing"
 msgstr "Воспроизведение"
 
-#: shuttle_control.cc:594
+#: shuttle_control.cc:607
 #, c-format
 msgid "<<< %+d semitones"
 msgstr "<<< %+d полутон"
 
-#: shuttle_control.cc:596
+#: shuttle_control.cc:609
 #, c-format
 msgid ">>> %+d semitones"
 msgstr ">>> %+d полутон"
 
-#: shuttle_control.cc:601
-msgid "Stopped"
-msgstr "Остановлено"
-
 #: soundcloud_export_selector.cc:44
 msgid "User Email"
 msgstr "Email пользователя"
@@ -12456,7 +12954,7 @@ msgstr "Сделать файлы скачиваемыми"
 msgid "%1: %2 of %3 bytes uploaded"
 msgstr "%1: %2 из %3 байт загружено"
 
-#: splash.cc:73
+#: splash.cc:75
 msgid "%1 loading ..."
 msgstr "Загружается %1..."
 
@@ -12472,7 +12970,7 @@ msgstr "Удалить громкоговоритель"
 msgid "Azimuth:"
 msgstr "Азимут:"
 
-#: startup.cc:68
+#: startup.cc:70
 msgid ""
 "Use an external mixer or the hardware mixer of your audio interface.\n"
 "%1 will play NO role in monitoring"
@@ -12480,11 +12978,11 @@ msgstr ""
 "Использовать внешний микшер или микшер звукового интерфейса.\n"
 "%1 никак не будет участвовать в мониторинге."
 
-#: startup.cc:70
+#: startup.cc:72
 msgid "Ask %1 to play back material as it is being recorded"
 msgstr "Дать %1 воспроизводить материал при его записи"
 
-#: startup.cc:143
+#: startup.cc:145
 msgid ""
 "<span size=\"larger\">%1 is a digital audio workstation. You can use it to "
 "record, edit and mix multi-track audio. You can produce your own CDs, mix "
@@ -12501,15 +12999,15 @@ msgstr ""
 "\n"
 "Перед началом работы с программой необходимо кое-что настроить.</span>"
 
-#: startup.cc:169
+#: startup.cc:171
 msgid "Welcome to %1"
 msgstr "Приветствуем вас в %1"
 
-#: startup.cc:192
+#: startup.cc:194
 msgid "Default folder for %1 sessions"
 msgstr "Папка для сессий %1 по умолчанию"
 
-#: startup.cc:198
+#: startup.cc:200
 msgid ""
 "Each project that you work on with %1 has its own folder.\n"
 "These can require a lot of disk space if you are recording audio.\n"
@@ -12527,11 +13025,11 @@ msgstr ""
 "<i>(Сохранять сессии можно будет где угодно, просто указанная\n"
 "папка будет использоваться по умолчанию)</i>"
 
-#: startup.cc:221
+#: startup.cc:223
 msgid "Default folder for new sessions"
 msgstr "Папка для новых сессий по умолчанию"
 
-#: startup.cc:242
+#: startup.cc:244
 msgid ""
 "While recording instruments or vocals, you probably want to listen to the\n"
 "signal as well as record it. This is called \"monitoring\". There are\n"
@@ -12556,15 +13054,15 @@ msgstr ""
 "<i>Если вы не понимаете смысл этого параметра, просто используйте \n"
 "предлагаемый по умолчанию вариант.</i>"
 
-#: startup.cc:263
+#: startup.cc:265
 msgid "Monitoring Choices"
 msgstr "Способ мониторинга"
 
-#: startup.cc:286
+#: startup.cc:288
 msgid "Use a Master bus directly"
 msgstr "Использовать мастер-шину напрямую"
 
-#: startup.cc:288
+#: startup.cc:290
 msgid ""
 "Connect the Master bus directly to your hardware outputs. This is preferable "
 "for simple usage."
@@ -12572,11 +13070,11 @@ msgstr ""
 "Соединить мастер-шину напрямую с выходами звукового интерфейса.\n"
 "Предпочтительно для простого использования."
 
-#: startup.cc:297
+#: startup.cc:299
 msgid "Use an additional Monitor bus"
 msgstr "Использовать дополнительную шину мониторинга"
 
-#: startup.cc:300
+#: startup.cc:302
 msgid ""
 "Use a Monitor bus between Master bus and hardware outputs for \n"
 "greater control in monitoring without affecting the mix."
@@ -12584,7 +13082,7 @@ msgstr ""
 "Использовать шину мониторинга между мастер-шиной и выходами \n"
 "звукового интерфейса для полного контроля без вмешательства в микс."
 
-#: startup.cc:322
+#: startup.cc:324
 msgid ""
 "<i>You can change this preference at any time via the Preferences dialog.\n"
 "You can also add or remove the monitor section to/from any session.</i>\n"
@@ -12597,7 +13095,7 @@ msgstr ""
 "<i>Если вы не понимаете смысл этого параметра, просто используйте\n"
 "предлагаемое по умолчанию.</i>"
 
-#: startup.cc:333
+#: startup.cc:335
 msgid "Monitor Section"
 msgstr "Секция монитора"
 
@@ -12985,20 +13483,20 @@ msgstr "Переключить ввод аккордов"
 msgid "Sustain Selected Notes by Note Length"
 msgstr "Выдерживать выбранные ноты по длине"
 
-#: stereo_panner.cc:128
+#: stereo_panner.cc:129
 #, c-format
 msgid "L:%3d R:%3d Width:%d%%"
 msgstr "Левый:%3d, Правый:%3d, Ширина: %d%%"
 
-#: stereo_panner.cc:271
+#: stereo_panner.cc:272
 msgid "Panner|M"
 msgstr "М"
 
-#: stereo_panner_editor.cc:35
+#: stereo_panner_editor.cc:37
 msgid "Stereo Panner"
 msgstr "Стереопанорама"
 
-#: stereo_panner_editor.cc:49
+#: stereo_panner_editor.cc:51
 msgid "Width"
 msgstr "Ширина"
 
@@ -13006,14 +13504,18 @@ msgstr "Ширина"
 msgid "Strip Silence"
 msgstr "Вырезать тишину"
 
-#: strip_silence_dialog.cc:75
+#: strip_silence_dialog.cc:76
 msgid "Minimum length"
 msgstr "Минимальная длина"
 
-#: strip_silence_dialog.cc:83
+#: strip_silence_dialog.cc:84
 msgid "Fade length"
 msgstr "Длина фейда"
 
+#: strip_silence_dialog.cc:111 strip_silence_dialog.cc:298
+msgid "Analyzing"
+msgstr "Выполняется анализ"
+
 #: tempo_dialog.cc:41 tempo_dialog.cc:57
 msgid "bar:"
 msgstr "в такте:"
@@ -13103,71 +13605,75 @@ msgstr "Размер начинается в такте:"
 msgid "incomprehensible meter note type (%1)"
 msgstr "непонятный тип нотного ритма (%1)"
 
-#: theme_manager.cc:67
+#: theme_manager.cc:61
 msgid "Dark Theme"
 msgstr "Тёмная тема"
 
-#: theme_manager.cc:68
+#: theme_manager.cc:62
 msgid "Light Theme"
 msgstr "Светлая тема"
 
-#: theme_manager.cc:69
+#: theme_manager.cc:63
 msgid "Restore Defaults"
 msgstr "Восстановить исходные значения"
 
-#: theme_manager.cc:70
+#: theme_manager.cc:64
 msgid "Draw \"flat\" buttons"
 msgstr "Рисовать кнопки плоскими"
 
-#: theme_manager.cc:71
+#: theme_manager.cc:65
 msgid "Blink Rec-Arm buttons"
 msgstr "Мигать кнопками готовности к записи"
 
-#: theme_manager.cc:72
+#: theme_manager.cc:66
 msgid "Color regions using their track's color"
 msgstr "Раскрашивать области цветом дорожки"
 
-#: theme_manager.cc:73
+#: theme_manager.cc:67
 msgid "Show waveform clipping"
 msgstr "Показывать клиппинг волновой формы"
 
-#: theme_manager.cc:75
+#: theme_manager.cc:69
 msgid "Waveforms color gradient depth"
 msgstr "Глубина градиента волновой формы сигнала"
 
-#: theme_manager.cc:77
+#: theme_manager.cc:71
 msgid "Timeline item gradient depth"
 msgstr "Глубина градиента объектов на таймлайне"
 
-#: theme_manager.cc:78
+#: theme_manager.cc:72
 msgid "All floating windows are dialogs"
 msgstr "Все плавающие окна являются диалогами"
 
-#: theme_manager.cc:79
+#: theme_manager.cc:73
 msgid "Transient windows follow front window."
 msgstr "Временные окна следуют за получающим фокус основным окном"
 
-#: theme_manager.cc:80
+#: theme_manager.cc:74
+msgid "Float detached monitor-section window"
+msgstr ""
+
+#: theme_manager.cc:75
 msgid "Icon Set"
 msgstr "Набор значков:"
 
-#: theme_manager.cc:89
+#: theme_manager.cc:84
 msgid "Object"
 msgstr "Объект"
 
-#: theme_manager.cc:165
+#: theme_manager.cc:162
 msgid "Items"
 msgstr "Элементы"
 
-#: theme_manager.cc:166
+#: theme_manager.cc:163
 msgid "Palette"
 msgstr "Палитра"
 
-#: theme_manager.cc:167
+#: theme_manager.cc:164
 msgid "Transparency"
 msgstr "Прозрачность"
 
-#: theme_manager.cc:197
+#: theme_manager.cc:195
 msgid ""
 "Mark all floating windows to be type \"Dialog\" rather than using \"Utility"
 "\" for some.\n"
@@ -13178,7 +13684,7 @@ msgstr ""
 "Это может помочь с некоторыми оконными менеджерами.\n"
 "Изменения вступят в силу после перезапуска %1."
 
-#: theme_manager.cc:201
+#: theme_manager.cc:199
 msgid ""
 "Make transient windows follow the front window when toggling between the "
 "editor and mixer.\n"
@@ -13188,7 +13694,14 @@ msgstr ""
 "при переключении между редактором и микшером.\n"
 "Это изменение вступит в силу после перезапуска %1."
 
-#: theme_manager.cc:635
+#: theme_manager.cc:202
+msgid ""
+"When detaching the monitoring section, mark it as \"Utility\" window to stay "
+"in front.\n"
+"This requires a restart of %1 to take effect"
+msgstr ""
+
+#: theme_manager.cc:643
 msgid "Color Palette"
 msgstr "Цветовая палитра"
 
@@ -13196,7 +13709,7 @@ msgstr "Цветовая палитра"
 msgid "Track/Bus name (double click to edit)"
 msgstr "Имя дорожки/шины (двойной клик для редактирования)"
 
-#: time_axis_view_item.cc:333
+#: time_axis_view_item.cc:326
 msgid "new duration %1 frame is out of bounds for %2"
 msgid_plural "new duration of %1 frames is out of bounds for %2"
 msgstr[0] "Новая длительность размером %1 кадр находится за пределами %2"
@@ -13335,97 +13848,101 @@ msgstr "Транспонировать MIDI"
 msgid "Transpose"
 msgstr "Транспонировать"
 
-#: ui_config.cc:179 ui_config.cc:317
+#: ui_config.cc:230 ui_config.cc:368
 msgid "Loading default ui configuration file %1"
 msgstr "Загрузка файла конфигурации UI по умолчанию %1"
 
-#: ui_config.cc:182 ui_config.cc:320
+#: ui_config.cc:233 ui_config.cc:371
 msgid "cannot read default ui configuration file \"%1\""
 msgstr "Невозможно прочитать основной файл конфигурации интерфейса \"%1\""
 
-#: ui_config.cc:185 ui_config.cc:325
+#: ui_config.cc:236 ui_config.cc:376
 msgid "default ui configuration file \"%1\" not loaded successfully."
 msgstr "Основной файл конфигурации интерфейса \"%1\" не был успешно загружен"
 
-#: ui_config.cc:193
+#: ui_config.cc:244
 msgid "Could not find default UI configuration file %1"
 msgstr "Не удалось найти конфигурационный файл %1 для интерфейса"
 
-#: ui_config.cc:236
+#: ui_config.cc:287
 msgid "Loading color file %1"
 msgstr "Загружается файл %1 с описанием цветовой схемы"
 
-#: ui_config.cc:239
+#: ui_config.cc:290
 msgid "cannot read color file \"%1\""
 msgstr "Невозможно прочитать файл %1 с описанием цветовой схемы"
 
-#: ui_config.cc:244
+#: ui_config.cc:295
 msgid "color file \"%1\" not loaded successfully."
 msgstr "Файл %1 с описанием цветовой схемы не был успешно загружен."
 
-#: ui_config.cc:250
+#: ui_config.cc:301
 msgid "Color file %1 not found"
 msgstr "Файл %1 с описанием цветовой схемы не найден"
 
-#: ui_config.cc:299 ui_config.cc:378
+#: ui_config.cc:350 ui_config.cc:429
 msgid "Color file %1 not saved"
 msgstr "Файл %1 с описанием цветовой схемы не сохранён"
 
-#: ui_config.cc:334
+#: ui_config.cc:385
 msgid "Loading user ui configuration file %1"
 msgstr "Загрузка файла пользовательской конфигурации UI %1"
 
-#: ui_config.cc:337
+#: ui_config.cc:388
 msgid "cannot read ui configuration file \"%1\""
 msgstr "Невозможно прочитать файл конфигурации UI \"%1\""
 
-#: ui_config.cc:342
+#: ui_config.cc:393
 msgid "user ui configuration file \"%1\" not loaded successfully."
 msgstr "Конфигурация UI интерфейса файлa \"%1\" не загружена успешно."
 
-#: ui_config.cc:350
+#: ui_config.cc:401
 msgid "could not find any ui configuration file, canvas will look broken."
 msgstr "Невозможно найти файл конфигурации UI, это будет выглядеть сломаным."
 
-#: ui_config.cc:368
+#: ui_config.cc:419
 msgid "Config file %1 not saved"
 msgstr "Конфигурационный файл %1 не сохранён"
 
-#: ui_config.cc:609
+#: ui_config.cc:660
 msgid "Color %1 not found"
 msgstr "Цвет %1 не обнаружен"
 
-#: ui_config.cc:679
+#: ui_config.cc:730
 msgid "Unable to find UI style file %1 in search path %2. %3 will look strange"
 msgstr ""
 "Не удается найти файл стилей пользовательского интерфейса %1 в пути поиска "
 "%2. % 3 будет выглядеть странно"
 
-#: utils.cc:117 utils.cc:160
+#: utils.cc:114 utils.cc:157
 msgid "bad XPM header %1"
 msgstr "Плохой заголовок XPM %1"
 
-#: utils.cc:577
+#: utils.cc:574
 msgid "cannot find XPM file for %1"
 msgstr "Невозможно найти файл XPM для %1"
 
-#: utils.cc:597 utils.cc:627 utils.cc:641
+#: utils.cc:594 utils.cc:624 utils.cc:638
 msgid "default"
 msgstr "по умолчанию"
 
-#: utils.cc:642
+#: utils.cc:639
 msgid "icon \"%1\" not found for icon set \"%2\", fallback to default"
 msgstr ""
 "значок \"%1\" не найден для набора \"%2\", возврат к установкам по умолчанию"
 
-#: utils.cc:649
+#: utils.cc:646
 msgid "cannot find icon image for %1 using %2"
 msgstr "Невозможно найти файл значка для %1 с помощью %2"
 
-#: utils.cc:666 utils.cc:682
+#: utils.cc:663 utils.cc:679
 msgid "Caught exception while loading icon named %1"
 msgstr "Получено исключение при загрузке значка с именем %1"
 
+#: utils.cc:939
+msgid "Overwrite"
+msgstr "Перезаписать"
+
 #: add_video_dialog.cc:54
 msgid "Set Video Track"
 msgstr "Установка видеодорожки"
@@ -13524,11 +14041,13 @@ msgstr ""
 msgid "Video-monitor 'xjadeo' cannot be launched."
 msgstr "Видеомонитор 'xjadeo' не может быть запущен."
 
-#: video_timeline.cc:769
+#: video_timeline.cc:770
 msgid ""
-"Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.8.0 or "
+"Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.7.7 or "
 "later. http://xjadeo.sf.net/"
 msgstr ""
+"Видеомонитор 'xjadeo' слишком стар. Пожалуйста, установите xjadeo версию "
+"0.7.7 или более позднюю. http://xjadeo.sf.net/"
 
 #: video_monitor.cc:285
 msgid "Video Monitor: File Not Found."
@@ -13536,9 +14055,9 @@ msgstr "Видеомонитор: файл не найден"
 
 #: transcode_ffmpeg.cc:56
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system.\n"
-"Video import and export is not possible until you install those tools.\n"
+"ffmpeg installation was not found on this system.\n"
 "%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
+"Video import and export is not possible until you install tools.\n"
 "\n"
 "The tools are included with the %1 releases from ardour.org and also "
 "available with the video-server at http://x42.github.com/harvid/\n"
@@ -13551,21 +14070,6 @@ msgid ""
 "\n"
 "see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
-"Исполняемые файлы ffprobe или ffmpeg не найжены в системе.\n"
-"Импорт и экспорт видео будет невозможен, пока вы не установите эти "
-"инструменты.\n"
-"%1 требует ffmpeg и ffprobe версии 1.1 или новее от ffmpeg.org.\n"
-"\n"
-"Эти инструменты входя в состав сборок %1 с ardour.org ,а также доступны на "
-"странице http://x42.github.com/harvid/.\n"
-"\n"
-"Важно: файлы должны быть установлены в $PATH и названы ffmpeg_harvid и "
-"ffprobe_harvid.\n"
-"Если у вас уже есть подходящий установленный в вашей системе ffmpeg, "
-"рекомендуем создать символические ссылки с ffmpeg на ffmpeg_harvid и с "
-"ffprobe на ffprobe_harvid.\n"
-"\n"
-"Также см. http://manual.ardour.org/video-timeline/setup/."
 
 #: transcode_video_dialog.cc:56
 msgid "Transcode/Import Video File "
@@ -13584,10 +14088,14 @@ msgid "Height = "
 msgstr "Высота = "
 
 #: transcode_video_dialog.cc:66
+msgid "Extract LTC from audio and align video"
+msgstr "Извлечь LTC из звуковой дорожки и выровнять видео"
+
+#: transcode_video_dialog.cc:67
 msgid "Manual Override"
 msgstr "Ручное управление"
 
-#: transcode_video_dialog.cc:70 export_video_dialog.cc:99
+#: transcode_video_dialog.cc:71 export_video_dialog.cc:99
 msgid "Debug Mode: Print ffmpeg command and output to stdout."
 msgstr "Режим отладки: вывод команд ffmpeg в stdout"
 
@@ -13597,12 +14105,9 @@ msgstr "<b>Информация о файле</b>"
 
 #: transcode_video_dialog.cc:113
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system. Video Import "
-"is not possible until you install those tools. See the Log window for more "
-"information."
+"ffmpeg installation was not found. Video Import is not possible. See the Log "
+"window for more information."
 msgstr ""
-"Исполняемые файлы ffprobe и ffmpeg не найдены в системе. Импорт видео "
-"невозможен, пока вы их не установите. Подробности приведены в окне журнала."
 
 #: transcode_video_dialog.cc:120
 msgid ""
@@ -13636,63 +14141,63 @@ msgstr "??"
 msgid "<b>Import Settings</b>"
 msgstr "<b>Параметры импорта</b>"
 
-#: transcode_video_dialog.cc:186
-msgid "Reference From Current Location (Previously Transcoded Files Only)"
-msgstr "Reference From Current Location (Только ранее перекодированные файлы)"
+#: transcode_video_dialog.cc:184
+msgid "Reference from Current Location (Previously Transcoded Files Only)"
+msgstr ""
 
-#: transcode_video_dialog.cc:187
+#: transcode_video_dialog.cc:185
 msgid "Import/Transcode Video to Session"
 msgstr "Импортировать/перекодировать видео в сессию"
 
-#: transcode_video_dialog.cc:190 transcode_video_dialog.cc:200
+#: transcode_video_dialog.cc:188 transcode_video_dialog.cc:198
 msgid "Do Not Import Video (Audio Import Only)"
-msgstr "Не импортировать видео (Только аудиоимпрт)"
+msgstr "Не импортировать видео (только импорт звука)"
 
-#: transcode_video_dialog.cc:210
+#: transcode_video_dialog.cc:208
 msgid "Do Not Import Video"
-msgstr ""
+msgstr "Не импортировать видео"
 
-#: transcode_video_dialog.cc:226
+#: transcode_video_dialog.cc:224
 msgid "Scale Video: Width = "
 msgstr "Масштаб видео: Ширина = "
 
-#: transcode_video_dialog.cc:233
+#: transcode_video_dialog.cc:230
 msgid "Original Width"
 msgstr "Исходная ширина"
 
-#: transcode_video_dialog.cc:248
+#: transcode_video_dialog.cc:245
 msgid "Bitrate (KBit/s):"
 msgstr "Скорость потока (Кбит/с):"
 
-#: transcode_video_dialog.cc:253
+#: transcode_video_dialog.cc:250
 msgid "Extract Audio:"
 msgstr "Извлечь звук:"
 
-#: transcode_video_dialog.cc:258
+#: transcode_video_dialog.cc:255
 msgid "No Audio Track Present"
 msgstr "Нет звуковой дорожки"
 
-#: transcode_video_dialog.cc:261
+#: transcode_video_dialog.cc:258
 msgid "Do Not Extract Audio"
 msgstr "Не извлекать аудио"
 
-#: transcode_video_dialog.cc:376
+#: transcode_video_dialog.cc:374
 msgid "Extracting Audio.."
 msgstr "Извлекается звук..."
 
-#: transcode_video_dialog.cc:379
+#: transcode_video_dialog.cc:377
 msgid "Audio Extraction Failed."
 msgstr "Не удалось извлечь звуковую дорожку."
 
-#: transcode_video_dialog.cc:405
+#: transcode_video_dialog.cc:403
 msgid "Transcoding Video.."
 msgstr "Перекодирование видео..."
 
-#: transcode_video_dialog.cc:439
+#: transcode_video_dialog.cc:437
 msgid "Transcoding Failed."
 msgstr "Не удалось выполнить перекодирование."
 
-#: transcode_video_dialog.cc:529
+#: transcode_video_dialog.cc:541
 msgid "Save Transcoded Video File"
 msgstr "Сохранить перекодированный видеофайл"
 
@@ -13712,7 +14217,7 @@ msgstr "Корневая папка документов сервера:"
 msgid "Don't show this dialog again. (Reset in Edit->Preferences)."
 msgstr "Больше не показывать этот диалог"
 
-#: video_server_dialog.cc:97
+#: video_server_dialog.cc:94
 msgid ""
 "The external video server 'harvid' can not be found.\n"
 "The tool is included with the %1 releases from ardour.org, alternatively you "
@@ -13728,19 +14233,19 @@ msgstr ""
 "\n"
 "См. так же http://manual.ardour.org/video-timeline/setup/"
 
-#: video_server_dialog.cc:129
+#: video_server_dialog.cc:126
 msgid "Listen Address:"
 msgstr "Слушать адрес:"
 
-#: video_server_dialog.cc:134
+#: video_server_dialog.cc:131
 msgid "Listen Port:"
 msgstr "Слушать порт:"
 
-#: video_server_dialog.cc:139
+#: video_server_dialog.cc:136
 msgid "Cache Size:"
 msgstr "Размер кэша:"
 
-#: video_server_dialog.cc:145
+#: video_server_dialog.cc:142
 msgid ""
 "%1 relies on an external video server for the videotimeline.\n"
 "The server configured in Edit -> Preferences -> Video is not reachable.\n"
@@ -13751,20 +14256,20 @@ msgstr ""
 "сейчас недоступен.\n"
 "Вы хотите, чтобы %1 запустил 'harvid' на этом компьютере?"
 
-#: video_server_dialog.cc:189
+#: video_server_dialog.cc:186
 msgid "Set Video Server Executable"
 msgstr "Установить видеосервер исполняемым"
 
-#: video_server_dialog.cc:209
+#: video_server_dialog.cc:206
 msgid "Server docroot"
 msgstr "Корневая папка документов видеосервера"
 
-#: utils_videotl.cc:60
+#: utils_videotl.cc:61
 msgid "Destination is outside Video Server's docroot. "
 msgstr ""
 "Направление находится за пределами корневой папки документов видеосервера."
 
-#: utils_videotl.cc:61
+#: utils_videotl.cc:62
 msgid ""
 "The destination file path is outside of the Video Server's docroot. The file "
 "will not be readable by the Video Server. Do you still want to continue?"
@@ -13773,19 +14278,15 @@ msgstr ""
 "видеосервера. Файл будет недоступен на видеосервере. Вы все еще хотите "
 "продолжить?"
 
-#: utils_videotl.cc:64
+#: utils_videotl.cc:65
 msgid "Continue"
 msgstr "Дальше"
 
-#: utils_videotl.cc:70
+#: utils_videotl.cc:72
 msgid "Confirm Overwrite"
 msgstr "Подтвердите перезапись"
 
-#: utils_videotl.cc:71
-msgid "A file with the same name already exists.  Do you want to overwrite it?"
-msgstr "Снимок с таким названием уже есть. Перезаписать его?"
-
-#: utils_videotl.cc:81 utils_videotl.cc:97
+#: utils_videotl.cc:82 utils_videotl.cc:98
 msgid "Cannot create video folder \"%1\" (%2)"
 msgstr "Не удалось создать папку для видео: \"%1\" (%2)"
 
@@ -13839,13 +14340,9 @@ msgstr "Включить метаданные сессии"
 
 #: export_video_dialog.cc:115
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system. Video Export "
-"is not possible until you install those tools. See the Log window for more "
-"information."
+"ffmpeg installation was not found. Video Export is not possible. See the Log "
+"window for more information."
 msgstr ""
-"Исполняемые файлы ffprobe или ffmpeg в системе не обнаружены. Экспорт видео "
-"будет недоступен до тех пор, пока вы их не установите. См. подробнее в окне "
-"журнала."
 
 #: export_video_dialog.cc:126
 msgid "<b>Output:</b> (file extension defines format)"
@@ -13863,77 +14360,77 @@ msgstr "Звук:"
 msgid "Master Bus"
 msgstr "Мастер-шина"
 
-#: export_video_dialog.cc:154
+#: export_video_dialog.cc:153
 msgid "from the %1 session's start to the session's end"
 msgstr "от начала до конца сессии %1"
 
-#: export_video_dialog.cc:157
+#: export_video_dialog.cc:156
 msgid "<b>Settings:</b>"
 msgstr "<b>Параметры:</b>"
 
-#: export_video_dialog.cc:165
+#: export_video_dialog.cc:164
 msgid "Range:"
 msgstr "Диапазон:"
 
-#: export_video_dialog.cc:171
+#: export_video_dialog.cc:170
 msgid "Video Codec:"
 msgstr "Видеокодек:"
 
-#: export_video_dialog.cc:174
+#: export_video_dialog.cc:173
 msgid "Video KBit/s:"
 msgstr "Скорость видеопотока (Кбит/с):"
 
-#: export_video_dialog.cc:177
+#: export_video_dialog.cc:176
 msgid "Audio Codec:"
 msgstr "Звуковой кодек:"
 
-#: export_video_dialog.cc:180
+#: export_video_dialog.cc:179
 msgid "Audio KBit/s:"
 msgstr "Скорость звукового потока (Кбит/с):"
 
-#: export_video_dialog.cc:183
+#: export_video_dialog.cc:182
 msgid "Audio Samplerate:"
 msgstr "Частота сэмплирования звука:"
 
-#: export_video_dialog.cc:218 export_video_dialog.cc:227
-#: export_video_dialog.cc:810 export_video_dialog.cc:813
+#: export_video_dialog.cc:215 export_video_dialog.cc:223
+#: export_video_dialog.cc:801 export_video_dialog.cc:804
 msgid "(default for format)"
 msgstr "(по умолчанию для контейнера)"
 
-#: export_video_dialog.cc:238 export_video_dialog.cc:251
-#: export_video_dialog.cc:817 export_video_dialog.cc:826
+#: export_video_dialog.cc:233 export_video_dialog.cc:244
+#: export_video_dialog.cc:808 export_video_dialog.cc:817
 msgid "(default)"
 msgstr "(по умолчанию)"
 
-#: export_video_dialog.cc:252 export_video_dialog.cc:820
+#: export_video_dialog.cc:245 export_video_dialog.cc:811
 msgid "(retain)"
 msgstr "(исходная)"
 
-#: export_video_dialog.cc:344
+#: export_video_dialog.cc:335
 msgid "from 00:00:00:00 to the video's end"
 msgstr "от 00:00:00:00 до конца видео"
 
-#: export_video_dialog.cc:346
+#: export_video_dialog.cc:337
 msgid "from the video's start to the video's end"
 msgstr "от начала до конца видео"
 
-#: export_video_dialog.cc:349
+#: export_video_dialog.cc:340
 msgid "Selected range"
 msgstr "Выбранный диапазон"
 
-#: export_video_dialog.cc:569
+#: export_video_dialog.cc:560
 msgid "Normalizing audio"
 msgstr "Выполняется нормировка звука"
 
-#: export_video_dialog.cc:573
+#: export_video_dialog.cc:564
 msgid "Exporting audio"
 msgstr "Экспорт звука"
 
-#: export_video_dialog.cc:628
+#: export_video_dialog.cc:619
 msgid "Exporting Audio..."
 msgstr "Экспортируется звук..."
 
-#: export_video_dialog.cc:685
+#: export_video_dialog.cc:676
 msgid ""
 "Export Video: Cannot query duration of video-file, using duration from "
 "timeline instead."
@@ -13941,36 +14438,36 @@ msgstr ""
 "Экспорт видео: невозможно запросить длительность видеофайла, вместо неё "
 "используется длительность проекта."
 
-#: export_video_dialog.cc:715
+#: export_video_dialog.cc:706
 msgid "Export Video: export-range does not include video."
 msgstr "Экспорт видео: экспортный диапазон не содержит видео."
 
-#: export_video_dialog.cc:728
+#: export_video_dialog.cc:719
 msgid "Export Video: No Master Out Ports to Connect for Audio Export"
 msgstr ""
 "Экспорт видео: нет соединяемых портов выхода мастер-шины для экспорта звука"
 
-#: export_video_dialog.cc:770
+#: export_video_dialog.cc:761
 msgid "Encoding Video..."
 msgstr "Кодируется видео..."
 
-#: export_video_dialog.cc:790
+#: export_video_dialog.cc:781
 msgid "Export Video: Video input file cannot be read."
 msgstr "Экспорт видео: не удалось прочитать используемый видеофайл"
 
-#: export_video_dialog.cc:896
+#: export_video_dialog.cc:887
 msgid "Encoding Video.. Pass 1/2"
 msgstr "Выполняется кодирование видео. Проход 1/2."
 
-#: export_video_dialog.cc:908
+#: export_video_dialog.cc:899
 msgid "Encoding Video.. Pass 2/2"
 msgstr "Выполняется кодирование видео. Проход 2/2."
 
-#: export_video_dialog.cc:1011
+#: export_video_dialog.cc:1002
 msgid "Transcoding failed."
 msgstr "Не удалось выполнить перекодировку."
 
-#: export_video_dialog.cc:1247 export_video_dialog.cc:1267
+#: export_video_dialog.cc:1238 export_video_dialog.cc:1258
 msgid "Save Exported Video File"
 msgstr "Сохранить экспортированный видеофайл"
 
@@ -13988,18 +14485,285 @@ msgstr "<b>Справка по экспорту видео</b>"
 
 #: export_video_infobox.cc:51
 msgid ""
+"%1 does not include commercial licenses for encoding audio/video. Visit "
+"mpegla.com for information about licensing various audio/video codecs.\n"
+"\n"
 "Video encoding is a non-trivial task with many details.\n"
 "\n"
-"Please see the manual at %1/video-timeline/operations/#export.\n"
+"Please see the manual at %2/video-timeline/operations/#export.\n"
 "\n"
 "Open Manual in Browser? "
 msgstr ""
-"Кодирование видео — нетривиальная задача с множеством нюансов.\n"
-"\n"
-"Рекомендуем прочитать руководство по адресу\n"
-"%1/video-timeline/operations/#export.\n"
-"\n"
-"Открыть руководство в браузере? "
+
+#~ msgid "Adjusting the scale require an application restart to re-layout."
+#~ msgstr "После коррекции масштаба необходимо перезапустить приложение"
+
+#~ msgid ""
+#~ "No ffprobe or ffmpeg executables could be found on this system.\n"
+#~ "Video import and export is not possible until you install those tools.\n"
+#~ "%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
+#~ "\n"
+#~ "The tools are included with the %1 releases from ardour.org and also "
+#~ "available with the video-server at http://x42.github.com/harvid/\n"
+#~ "\n"
+#~ "Important: the files need to be installed in $PATH and named "
+#~ "ffmpeg_harvid and ffprobe_harvid.\n"
+#~ "If you already have a suitable ffmpeg installation on your system, we "
+#~ "recommend creating symbolic links from ffmpeg to ffmpeg_harvid and from "
+#~ "ffprobe to ffprobe_harvid.\n"
+#~ "\n"
+#~ "see also http://manual.ardour.org/video-timeline/setup/"
+#~ msgstr ""
+#~ "Исполняемые файлы ffprobe или ffmpeg не найжены в системе.\n"
+#~ "Импорт и экспорт видео будет невозможен, пока вы не установите эти "
+#~ "инструменты.\n"
+#~ "%1 требует ffmpeg и ffprobe версии 1.1 или новее от ffmpeg.org.\n"
+#~ "\n"
+#~ "Эти инструменты входя в состав сборок %1 с ardour.org ,а также доступны "
+#~ "на странице http://x42.github.com/harvid/.\n"
+#~ "\n"
+#~ "Важно: файлы должны быть установлены в $PATH и названы ffmpeg_harvid и "
+#~ "ffprobe_harvid.\n"
+#~ "Если у вас уже есть подходящий установленный в вашей системе ffmpeg, "
+#~ "рекомендуем создать символические ссылки с ffmpeg на ffmpeg_harvid и с "
+#~ "ffprobe на ffprobe_harvid.\n"
+#~ "\n"
+#~ "Также см. http://manual.ardour.org/video-timeline/setup/."
+
+#~ msgid ""
+#~ "No ffprobe or ffmpeg executables could be found on this system. Video "
+#~ "Import is not possible until you install those tools. See the Log window "
+#~ "for more information."
+#~ msgstr ""
+#~ "Исполняемые файлы ffprobe и ffmpeg не найдены в системе. Импорт видео "
+#~ "невозможен, пока вы их не установите. Подробности приведены в окне "
+#~ "журнала."
+
+#~ msgid ""
+#~ "No ffprobe or ffmpeg executables could be found on this system. Video "
+#~ "Export is not possible until you install those tools. See the Log window "
+#~ "for more information."
+#~ msgstr ""
+#~ "Исполняемые файлы ffprobe или ffmpeg в системе не обнаружены. Экспорт "
+#~ "видео будет недоступен до тех пор, пока вы их не установите. См. "
+#~ "подробнее в окне журнала."
+
+#~ msgid ""
+#~ "Specify the default timeout for plugin instantiation in 1/10 seconds. "
+#~ "Plugins that require more time to load will be blacklisted. A value of 0 "
+#~ "disables the timeout."
+#~ msgstr ""
+#~ "Укажите используемый по умолчанию тайм-аут для инстанцирования плагина в "
+#~ "десятых долях секунды. Плагины, требующие больше времени для загрузки, "
+#~ "будут блокироваться. Если значение равно нулю, тайм-аут отключается."
+
+#~ msgid "Scan Time Out [deciseconds]"
+#~ msgstr "Тайм-аут сканирования [децисек.]"
+
+#~ msgid "Clear VST Cache"
+#~ msgstr "Очистить кэш VST"
+
+#~ msgid "Clear VST Blacklist"
+#~ msgstr "Очистить чёрный список VST"
+
+#~ msgid "Clear AU Cache"
+#~ msgstr "Очистить кэш AU"
+
+#~ msgid "Clear AU Blacklist"
+#~ msgstr "Очистить чёрный список AU"
+
+#~ msgid "Duplicate Tracks/Busses"
+#~ msgstr "Создать копии дорожек и шин"
+
+#~ msgid "32 bit float"
+#~ msgstr "32 bit float"
+
+#~ msgid "24 bit"
+#~ msgstr "24 бита"
+
+#~ msgid "16 bit"
+#~ msgstr "16 bit"
+
+#~ msgid ""
+#~ "%1%2\n"
+#~ "(built from revision %3)"
+#~ msgstr ""
+#~ "%1%2\n"
+#~ "(собрано из редакции %3)"
+
+#~ msgid ""
+#~ "A snapshot already exists with that name.  Do you want to overwrite it?"
+#~ msgstr "Снимок с таким названием уже есть. Перезаписать его?"
+
+#~ msgid "Could not disconnect from Audio/MIDI engine"
+#~ msgstr "Не удалось отсоединиться от аудио/MIDI-подсистемы."
+
+#~ msgid "Could not reconnect to the Audio/MIDI engine"
+#~ msgstr "Не удалось повторно соединиться с аудио/MIDI-подсистемой."
+
+#~ msgid "Playhead follows Range Selections and Edits"
+#~ msgstr "Указатель воспроизведения следует за выделением областей и правкам"
+
+#~ msgid ""
+#~ "When active, auditioning is taking place\n"
+#~ "Click to stop the audition"
+#~ msgstr ""
+#~ "Включено, если выполняется прослушивание.\n"
+#~ "Щёлкните, чтобы прекратить его."
+
+#~ msgid "Export To Video File"
+#~ msgstr "Видеофайл"
+
+#~ msgid "Export To Audio File(s)..."
+#~ msgstr "В звуковые файлы..."
+
+#~ msgid "Reference"
+#~ msgstr "Справка в Интернете"
+
+#~ msgid "Report A Bug"
+#~ msgstr "Сообщить об ошибке"
+
+#~ msgid "How to report a bug"
+#~ msgstr "Как сообщить об ошибке"
+
+#~ msgid "Transition To Roll"
+#~ msgstr "В обычном направлении"
+
+#~ msgid "Transition To Reverse"
+#~ msgstr "В обратном направлении"
+
+#~ msgid "Set From Playhead"
+#~ msgstr "По указателю воспроизведения"
+
+#~ msgid "Fill Range with Region"
+#~ msgstr "Заполнить диапазон областью"
+
+#~ msgid "Consolidate Range With Processing"
+#~ msgstr "Объединить диапазон с обработкой"
+
+#~ msgid "Bounce Range to Region List With Processing"
+#~ msgstr "Свести выделение в список областей с обработкой"
+
+#~ msgid "Play From Edit Point"
+#~ msgstr "Воспроизвести от курсора редактора"
+
+#~ msgid "Play From Start"
+#~ msgstr "Воспроизвести с начала"
+
+#~ msgid "Smart Mode (add Range functions to Grab mode)"
+#~ msgstr "Универсальный режим (захват + работа с диапазонами)"
+
+#~ msgid "Zoom focus"
+#~ msgstr "Фокус при масштабировании"
+
+#~ msgid "Playhead To Next Grid"
+#~ msgstr "К следующему делению сетки"
+
+#~ msgid "Playhead To Previous Grid"
+#~ msgstr "К предыдущему делению сетки"
+
+#~ msgid "Import From Session"
+#~ msgstr "Импортировать из сессии"
+
+#~ msgid "Snap Position To Grid"
+#~ msgstr "Привязать позицию к сетке"
+
+#~ msgid "Insert Region From Region List"
+#~ msgstr "Вставить область из списка областей"
+
+#~ msgid "File Exists!"
+#~ msgstr "Файл уже существует!"
+
+#~ msgid "Overwrite Existing File"
+#~ msgstr "Перезапись существующего файла"
+
+#~ msgid "End point trim"
+#~ msgstr "Конечная точка отделки"
+
+#~ msgid "Show Tracks With Regions Under Playhead"
+#~ msgstr "Показывать дорожки с областями под указателем воспроизведения"
+
+#~ msgid "Stop (Reconfigure)"
+#~ msgstr "Остановить (для настройки)"
+
+#~ msgid "Click to Add/Edit Comments"
+#~ msgstr "Нажмите для добавления/правки комментариев"
+
+#~ msgid "alsa_pcm"
+#~ msgstr "аlsa_pcm"
+
+#~ msgid ""
+#~ "<b>%1</b>\n"
+#~ "Double-click to show GUI.\n"
+#~ "Alt+double-click to show generic GUI.%2"
+#~ msgstr ""
+#~ "<b>%1</b>\n"
+#~ "Двойной щелчок, чтобы показать общий GUI.\n"
+#~ "Alt+двойной щелчок, чтобы показать общий GUI.%2"
+
+#~ msgid "Double-click on a name to edit settings for an enabled protocol"
+#~ msgstr ""
+#~ "Двойной щелчок по названию открывает редактор параметров включённого "
+#~ "протокола"
+
+#~ msgid "Show zoom toolbar"
+#~ msgstr "Показывать панель для управления масштабом"
+
+#~ msgid "Sound MIDI notes as they are selected"
+#~ msgstr "Воспроизводить ноты MIDI при их выделении"
+
+#~ msgid "update transport clock display at FPS instead of every 100ms"
+#~ msgstr "Обновлять часы транспорта по FPS, а не каждые 100 мс"
+
+#~ msgid "Align With Existing Material"
+#~ msgstr "С записанным материалом"
+
+#~ msgid "Align With Capture Time"
+#~ msgstr "По времени захвата"
+
+#~ msgid "Select From All..."
+#~ msgstr "Выбрать из всех..."
+
+#~ msgid "Disk Format"
+#~ msgstr "Формат диска"
+
+#~ msgid "Broadcast WAVE"
+#~ msgstr "Broadcast WAVE"
+
+#~ msgid "WAVE"
+#~ msgstr "WAVE"
+
+#~ msgid "Press to import selected files and close this window"
+#~ msgstr "Нажмите, чтобы импортировать выбранные файлы и закрыть это окно"
+
+#~ msgid "Press to import selected files and leave this window open"
+#~ msgstr ""
+#~ "Нажмите, чтобы импортировать выбранные файлы и оставить это окно открытым"
+
+#~ msgid "<b>Add files as ...</b>"
+#~ msgstr "<b>Добавить файлы как...</b>"
+
+#~ msgid "Reference From Current Location (Previously Transcoded Files Only)"
+#~ msgstr ""
+#~ "Reference From Current Location (Только ранее перекодированные файлы)"
+
+#~ msgid ""
+#~ "A file with the same name already exists.  Do you want to overwrite it?"
+#~ msgstr "Снимок с таким названием уже есть. Перезаписать его?"
+
+#~ msgid ""
+#~ "Video encoding is a non-trivial task with many details.\n"
+#~ "\n"
+#~ "Please see the manual at %1/video-timeline/operations/#export.\n"
+#~ "\n"
+#~ "Open Manual in Browser? "
+#~ msgstr ""
+#~ "Кодирование видео — нетривиальная задача с множеством нюансов.\n"
+#~ "\n"
+#~ "Рекомендуем прочитать руководство по адресу\n"
+#~ "%1/video-timeline/operations/#export.\n"
+#~ "\n"
+#~ "Открыть руководство в браузере? "
 
 #~ msgid "Inactive"
 #~ msgstr "Неактивно"
@@ -14085,13 +14849,6 @@ msgstr ""
 #~ msgid "only in region gain mode"
 #~ msgstr "Только в режиме правки огибающей"
 
-#~ msgid ""
-#~ "Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.7.7 or "
-#~ "later. http://xjadeo.sf.net/"
-#~ msgstr ""
-#~ "Видеомонитор 'xjadeo' слишком стар. Пожалуйста, установите xjadeo версию "
-#~ "0.7.7 или более позднюю. http://xjadeo.sf.net/"
-
 #~ msgid "After Editor Selection"
 #~ msgstr "После выбранного в редакторе"
 
diff --git a/gtk2_ardour/po/zh.po b/gtk2_ardour/po/zh.po
index 36b58d0..32fb0c3 100644
--- a/gtk2_ardour/po/zh.po
+++ b/gtk2_ardour/po/zh.po
@@ -1,24 +1,24 @@
-# SOME DESCRIPTIVE TITLE.
 # Copyright (C) YEAR Free Software Foundation, Inc.
 # FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+# 一善鱼 YQ-YSY at 163.com 完成翻译于 2015-12-09 在 Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn> 的基础上
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: Ardour 3\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-03-31 20:13-0400\n"
-"PO-Revision-Date: 2013-01-03 08:29-0500\n"
+"PO-Revision-Date: 2016-01-04 23:21+0800\n"
 "Last-Translator: Rui-huai Zhang <zrhzrh>\n"
 "Language-Team: zrhzrh <zrhzrh at mail.ustc.edu.cn>\n"
-"Language: \n"
+"Language: zh_CN\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
-"X-Poedit-Basepath: ../../\n"
-"X-Poedit-Language: Chinese\n"
-"X-Poedit-Country: CHINA\n"
+"X-Poedit-Basepath: ../..\n"
 "X-Poedit-SourceCharset: utf-8\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Poedit 1.8.4\n"
 "X-Poedit-SearchPath-0: gtk2_ardour\n"
 
 #: about.cc:125
@@ -277,6 +277,11 @@ msgid ""
 "\tMartin Blanchard\n"
 "\tRomain Arnaud <roming22 at gmail.com>\n"
 msgstr ""
+"法语:\n"
+"\tAlain Fréhel <alain.frehel at free.fr>\n"
+"\tChristophe Combelles <ccomb at free.fr>\n"
+"\tMartin Blanchard\n"
+"\tRomain Arnaud <roming22 at gmail.com>\n"
 
 #: about.cc:192
 msgid ""
@@ -289,6 +294,14 @@ msgid ""
 "\tRichard Oax <richard at pagliacciempire.de>\n"
 "\tRobin Gloster <robin at loc-com.de>\n"
 msgstr ""
+"德语:\n"
+"\tKarsten Petersen <kapet at kapet.de>\n"
+"\tSebastian Arnold <mail at sebastian-arnold.net>\n"
+"\tRobert Schwede <schwede at ironshark.com>\n"
+"\tBenjamin Scherrer <realhangman at web.de>\n"
+"\tEdgar Aichinger <edogawa at aon.at>\n"
+"\tRichard Oax <richard at pagliacciempire.de>\n"
+"\tRobin Gloster <robin at loc-com.de>\n"
 
 #: about.cc:199
 msgid ""
@@ -296,12 +309,17 @@ msgid ""
 "\tFilippo Pappalardo <filippo at email.it>\n"
 "\tRaffaele Morelli <raffaele.morelli at gmail.com>\n"
 msgstr ""
+"意大利语:\n"
+"\tFilippo Pappalardo <filippo at email.it>\n"
+"\tRaffaele Morelli <raffaele.morelli at gmail.com>\n"
 
 #: about.cc:200
 msgid ""
 "Portuguese:\n"
 "\tRui Nuno Capela <rncbc at rncbc.org>\n"
 msgstr ""
+"葡萄牙语:\n"
+"\tRui Nuno Capela <rncbc at rncbc.org>\n"
 
 #: about.cc:201
 msgid ""
@@ -309,6 +327,9 @@ msgid ""
 "\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
 "\tChris Ross <chris at tebibyte.org>\n"
 msgstr ""
+"巴西葡萄牙语:\n"
+"\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
+"\tChris Ross <chris at tebibyte.org>\n"
 
 #: about.cc:203
 msgid ""
@@ -316,6 +337,9 @@ msgid ""
 "\t Alex Krohn <alexkrohn at fastmail.fm>\n"
 "\tPablo Fernández <pablo.fbus at gmail.com>\n"
 msgstr ""
+"西班牙语:\n"
+"\t Alex Krohn <alexkrohn at fastmail.fm>\n"
+"\tPablo Fernández <pablo.fbus at gmail.com>\n"
 
 #: about.cc:204
 msgid ""
@@ -323,46 +347,61 @@ msgid ""
 "\t Igor Blinov <pitstop at nm.ru>\n"
 "\tAlexandre Prokoudine <alexandre.prokoudine at gmail.com>\n"
 msgstr ""
+"俄语:\n"
+"\t Igor Blinov <pitstop at nm.ru>\n"
+"\tAlexandre Prokoudine <alexandre.prokoudine at gmail.com>\n"
 
 #: about.cc:206
 msgid ""
 "Greek:\n"
 "\t Klearchos Gourgourinis <muadib at in.gr>\n"
 msgstr ""
+"希腊语:\n"
+"\t Klearchos Gourgourinis <muadib at in.gr>\n"
 
 #: about.cc:207
 msgid ""
 "Swedish:\n"
 "\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
 msgstr ""
+"瑞典语:\n"
+"\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
 
 #: about.cc:208
 msgid ""
 "Polish:\n"
 "\t Piotr Zaryk <pzaryk at gmail.com>\n"
 msgstr ""
+"波兰语:\n"
+"\t Piotr Zaryk <pzaryk at gmail.com>\n"
 
 #: about.cc:209
 msgid ""
 "Czech:\n"
 "\t Pavel Fric <pavelfric at seznam.cz>\n"
 msgstr ""
+"捷克语:\n"
+"\t Pavel Fric <pavelfric at seznam.cz>\n"
 
 #: about.cc:210
 msgid ""
 "Norwegian:\n"
 "\t Eivind Ødegård\n"
 msgstr ""
+"挪威语:\n"
+"\t Eivind Ødegård\n"
 
 #: about.cc:211
 msgid ""
 "Chinese:\n"
 "\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
 msgstr ""
+"汉语:\n"
+"\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
 
 #: about.cc:591
 msgid "Copyright (C) 1999-2015 Paul Davis\n"
-msgstr ""
+msgstr "版权所有 (C) 1999-2015 Paul Davis\n"
 
 #: about.cc:595
 msgid "http://ardour.org/"
@@ -373,6 +412,8 @@ msgid ""
 "%1%2\n"
 "(built from revision %3)"
 msgstr ""
+"%1%2\n"
+"(修订自版本 %3)"
 
 #: about.cc:600
 msgid "Config"
@@ -380,11 +421,11 @@ msgstr "配置"
 
 #: actions.cc:85
 msgid "Loading menus from %1"
-msgstr "载入菜单 %1"
+msgstr "正在载入菜单 %1"
 
 #: actions.cc:88 actions.cc:89
 msgid "badly formatted menu definition file: %1"
-msgstr ""
+msgstr "带有错误格式的菜单定义文件: %1"
 
 #: actions.cc:91
 msgid "%1 menu definition file not found"
@@ -392,7 +433,7 @@ msgstr "%1 菜单定义文件未找到"
 
 #: actions.cc:95 actions.cc:96
 msgid "%1 will not work without a valid menu definition file"
-msgstr ""
+msgstr "缺失有效的菜单定义文件将导致 %1 无法工作。"
 
 #: add_route_dialog.cc:54 route_params_ui.cc:524
 msgid "Add Track or Bus"
@@ -404,47 +445,47 @@ msgstr "配置:"
 
 #: add_route_dialog.cc:58
 msgid "Record Mode:"
-msgstr ""
+msgstr "录制模式:"
 
 #: add_route_dialog.cc:59
 msgid "Instrument:"
-msgstr ""
+msgstr "乐器:"
 
 #: add_route_dialog.cc:77
 msgid "Audio Tracks"
-msgstr ""
+msgstr "音频轨道"
 
 #: add_route_dialog.cc:78 add_route_dialog.cc:209
 msgid "MIDI Tracks"
-msgstr ""
+msgstr "MIDI 轨道"
 
 #: add_route_dialog.cc:79 add_route_dialog.cc:211
 msgid "Audio+MIDI Tracks"
-msgstr ""
+msgstr "音频+MIDI 轨道"
 
 #: add_route_dialog.cc:80 add_route_dialog.cc:207
 msgid "Busses"
-msgstr ""
+msgstr "总线"
 
 #: add_route_dialog.cc:83 add_route_dialog.cc:559
 msgid "First"
-msgstr ""
+msgstr "起始点"
 
 #: add_route_dialog.cc:84 add_route_dialog.cc:561
 msgid "After Editor Selection"
-msgstr ""
+msgstr "在编辑器已选择部分之后"
 
 #: add_route_dialog.cc:85 add_route_dialog.cc:563
 msgid "After Mixer Selection"
-msgstr ""
+msgstr "在混音器已选择部分之后"
 
 #: add_route_dialog.cc:86
 msgid "Last"
-msgstr ""
+msgstr "结束点"
 
 #: add_route_dialog.cc:103
 msgid "Add:"
-msgstr "添加:"
+msgstr "添加:"
 
 #: add_route_dialog.cc:116 time_fx_dialog.cc:91 add_video_dialog.cc:135
 #: video_server_dialog.cc:121
@@ -454,15 +495,15 @@ msgstr "<b>选项</b>"
 #: add_route_dialog.cc:126 bundle_manager.cc:193 region_editor.cc:50
 #: route_group_dialog.cc:71
 msgid "Name:"
-msgstr "名称:"
+msgstr "名称:"
 
 #: add_route_dialog.cc:156
 msgid "Group:"
-msgstr "分组:"
+msgstr "分组:"
 
 #: add_route_dialog.cc:162
 msgid "Insert:"
-msgstr ""
+msgstr "插入:"
 
 #: add_route_dialog.cc:223 add_route_dialog.cc:232 add_route_dialog.cc:306
 #: ardour_ui_ed.cc:539 engine_dialog.cc:237 rc_option_editor.cc:1805
@@ -487,7 +528,7 @@ msgstr "MIDI"
 
 #: add_route_dialog.cc:225 add_route_dialog.cc:238 add_route_dialog.cc:308
 msgid "Audio+MIDI"
-msgstr ""
+msgstr "Audio+MIDI"
 
 #: add_route_dialog.cc:226 add_route_dialog.cc:241 add_route_dialog.cc:309
 msgid "Bus"
@@ -495,12 +536,15 @@ msgstr "总线"
 
 #: add_route_dialog.cc:268
 msgid ""
-"Audio+MIDI tracks are intended for use <b>ONLY</b> with plugins that use "
-"both audio and MIDI input data\n"
+"Audio+MIDI tracks are intended for use <b>ONLY</b> with plugins that use both "
+"audio and MIDI input data\n"
 "\n"
-"If you do not plan to use such a plugin, then use a normal audio or MIDI "
-"track instead."
+"If you do not plan to use such a plugin, then use a normal audio or MIDI track "
+"instead."
 msgstr ""
+"音频+MIDI 轨道已经准备就绪 ,<b>但仅限于</b> 使用音频和MIDI输入数据的插件。\n"
+"\n"
+"如果您不打算使用这样一个插件,那么请使用普通的音频或MIDI轨道作为替代。"
 
 #: add_route_dialog.cc:327 add_route_dialog.cc:346 editor_actions.cc:422
 #: editor_rulers.cc:251 time_axis_view.cc:1374
@@ -513,7 +557,7 @@ msgstr "不分层的"
 
 #: add_route_dialog.cc:331 add_route_dialog.cc:350
 msgid "Tape"
-msgstr "带"
+msgstr "磁带"
 
 #: add_route_dialog.cc:431 monitor_section.cc:290
 msgid "Mono"
@@ -521,7 +565,7 @@ msgstr "单声道"
 
 #: add_route_dialog.cc:435
 msgid "Stereo"
-msgstr "双声道"
+msgstr "双声道立体声"
 
 #: add_route_dialog.cc:459
 msgid "3 Channel"
@@ -553,7 +597,7 @@ msgstr "自定义"
 
 #: add_route_dialog.cc:516 add_route_dialog.cc:532 route_group_menu.cc:81
 msgid "New Group..."
-msgstr "新群组"
+msgstr "新建群组…"
 
 #: add_route_dialog.cc:520 route_group_menu.cc:85
 msgid "No Group"
@@ -568,6 +612,8 @@ msgid ""
 "%1 has found the file <i>%2</i> in the following places:\n"
 "\n"
 msgstr ""
+"%1 被发现位于文件 <i>%2</i> 的以下位置:\n"
+"\n"
 
 #: ambiguous_file_dialog.cc:44
 msgid ""
@@ -577,7 +623,7 @@ msgid ""
 msgstr ""
 "\n"
 "\n"
-"请选择文件所在路径"
+"请选择您想获取的文件所在的路径。"
 
 #: ambiguous_file_dialog.cc:46 missing_file_dialog.cc:46
 msgid "Done"
@@ -613,11 +659,11 @@ msgstr "显示频率的功率范围"
 
 #: analysis_window.cc:55
 msgid "Normalize values"
-msgstr "归一化值"
+msgstr "规范化数值"
 
 #: analysis_window.cc:59
 msgid "FFT analysis window"
-msgstr "快速傅立叶变换分析视窗"
+msgstr "FFT 快速傅立叶变换分析视窗"
 
 #: analysis_window.cc:60 editor.cc:1823
 msgid "Spectral Analysis"
@@ -628,8 +674,7 @@ msgstr "频谱分析"
 msgid "Track"
 msgstr "音轨"
 
-#: analysis_window.cc:68 editor_actions.cc:648 mixer_ui.cc:131
-#: mixer_ui.cc:1854
+#: analysis_window.cc:68 editor_actions.cc:648 mixer_ui.cc:131 mixer_ui.cc:1854
 msgid "Show"
 msgstr "显示"
 
@@ -639,21 +684,25 @@ msgstr "重新分析数据"
 
 #: ardour_button.cc:887
 msgid "button cannot watch state of non-existing Controllable\n"
-msgstr ""
+msgstr "按钮无法显示不存在的操控状态\n"
 
 #: ardour_button.cc:1155
 msgid "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-msgstr ""
+msgstr "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
 
 #: ardour_ui.cc:164
 msgid ""
 "%1 %2.x has discovered configuration files from %1 %3.x.\n"
 "\n"
-"Would you like to copy the relevant files before starting to use the "
-"program?\n"
+"Would you like to copy the relevant files before starting to use the program?\n"
 "\n"
 "(This will require you to restart %1.)"
 msgstr ""
+"%1 %2.x 发现配置文件来源于 %1 %3.x.\n"
+"\n"
+"在启用这个程序前,您打算复制关联文件吗?\n"
+"\n"
+"(这将需要你重新启动 %1.)"
 
 #: ardour_ui.cc:211 editor_actions.cc:642 region_editor.cc:51
 msgid "Audition"
@@ -662,7 +711,7 @@ msgstr "监听"
 #: ardour_ui.cc:212 editor_actions.cc:136 mixer_strip.cc:2016
 #: rc_option_editor.cc:1959 route_time_axis.cc:252 route_time_axis.cc:2711
 msgid "Solo"
-msgstr ""
+msgstr "独奏"
 
 #: ardour_ui.cc:213 rc_option_editor.cc:741
 msgid "Feedback"
@@ -682,7 +731,7 @@ msgstr "首选项"
 
 #: ardour_ui.cc:222 ardour_ui.cc:229
 msgid "Add Tracks/Busses"
-msgstr ""
+msgstr "添加音轨/总线"
 
 #: ardour_ui.cc:223
 msgid "About"
@@ -699,11 +748,11 @@ msgstr "音轨和总线"
 
 #: ardour_ui.cc:226 engine_dialog.cc:70
 msgid "Audio/MIDI Setup"
-msgstr ""
+msgstr "音频/MIDI设置"
 
 #: ardour_ui.cc:227
 msgid "Video Export Dialog"
-msgstr ""
+msgstr "视频导出对话框"
 
 #: ardour_ui.cc:228
 msgid "Properties"
@@ -711,23 +760,23 @@ msgstr "属性"
 
 #: ardour_ui.cc:230 bundle_manager.cc:264
 msgid "Bundle Manager"
-msgstr "捆绑管理"
+msgstr "包裹管理器"
 
 #: ardour_ui.cc:231 big_clock_window.cc:37
 msgid "Big Clock"
-msgstr "大时钟"
+msgstr "Big Clock 大计时器"
 
 #: ardour_ui.cc:232
 msgid "Audio Connections"
-msgstr ""
+msgstr "音频连接"
 
 #: ardour_ui.cc:233
 msgid "MIDI Connections"
-msgstr ""
+msgstr "MIDI 连接"
 
 #: ardour_ui.cc:242
 msgid "Your configuration files were copied. You can now restart %1."
-msgstr ""
+msgstr "您的配置文件已经备份完成。现在可以重新启动 %1 。"
 
 #: ardour_ui.cc:481
 msgid ""
@@ -735,6 +784,9 @@ msgid ""
 "\n"
 "%1"
 msgstr ""
+"音频后端已关闭,因为:\n"
+"\n"
+"%1"
 
 #: ardour_ui.cc:483
 msgid ""
@@ -743,44 +795,49 @@ msgid ""
 "was not fast enough. Try to restart\n"
 "the audio backend and save the session."
 msgstr ""
+"音频后端要么已经关闭,\n"
+"要么它与 %1 失去了连接,\n"
+"因为 %1不够快。\n"
+"请尝试重新启动音频后端并保存会话。"
 
 #: ardour_ui.cc:507
 msgid ""
-"Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. "
-"Please see the log window for further details."
-msgstr ""
+"Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see "
+"the log window for further details."
+msgstr "音频单元插件扫描失败。自动 AU 扫描已被禁用。详情请参阅日志窗口。"
 
 #: ardour_ui.cc:508
 msgid "Audio Unit Plugin Scan Failed:"
-msgstr ""
+msgstr "音频单元插件扫描失败:"
 
+# NSM (network service manager)
 #: ardour_ui.cc:827
 msgid "NSM server did not announce itself"
-msgstr ""
+msgstr "NSM服务器没有表明身份"
 
 #: ardour_ui.cc:840
 msgid "NSM: no client ID provided"
-msgstr ""
+msgstr "NSM:没有提供客户机识别号"
 
 #: ardour_ui.cc:847
 msgid "NSM: no session created"
-msgstr ""
+msgstr "NSM:没有已创建的会话"
 
 #: ardour_ui.cc:870
 msgid "NSM: initialization failed"
-msgstr ""
+msgstr "NSM:初始化失败"
 
 #: ardour_ui.cc:900
 msgid "Free/Demo Version Warning"
-msgstr ""
+msgstr "免费/演示版本的警告"
 
 #: ardour_ui.cc:902
 msgid "Subscribe and support development of %1"
-msgstr ""
+msgstr "订阅和支持发展 %1"
 
 #: ardour_ui.cc:903
 msgid "Don't warn me about this again"
-msgstr ""
+msgstr "不再提醒我这个"
 
 #: ardour_ui.cc:905
 msgid ""
@@ -792,34 +849,45 @@ msgid ""
 "\n"
 "%4"
 msgstr ""
+"<span weight=\"bold\" size=\"large\">%1</span>\n"
+"\n"
+"<b>%2</b>\n"
+"\n"
+"<i>%3</i>\n"
+"\n"
+"%4"
 
 #: ardour_ui.cc:906
 msgid "This is a free/demo version of %1"
-msgstr ""
+msgstr "这是一个免费/演示版本 %1"
 
 #: ardour_ui.cc:907
 msgid "It will not restore OR save any plugin settings"
-msgstr ""
+msgstr "它不会恢复或保存任何插件设置"
 
 #: ardour_ui.cc:908
 msgid ""
 "If you load an existing session with plugin settings\n"
 "they will not be used and will be lost."
 msgstr ""
+"如果您载入一个带有插件设置的已存在的会话\n"
+"它们将不会被采用并将会被丢失。"
 
 #: ardour_ui.cc:910 plugin_ui.cc:569
 msgid ""
 "To get full access to updates without this limitation\n"
 "consider becoming a subscriber for a low cost every month."
 msgstr ""
+"为了不受这个限制地升级而得到完整使用权,\n"
+"请考虑以每月极低的成本而成为一个用户。"
 
 #: ardour_ui.cc:920
 msgid "Quit now"
-msgstr ""
+msgstr "立即退出"
 
 #: ardour_ui.cc:921
 msgid "Continue using %1"
-msgstr ""
+msgstr "继续使用 %1"
 
 #: ardour_ui.cc:954 startup.cc:345
 msgid "%1 is ready for use"
@@ -827,12 +895,15 @@ msgstr "%1 准备就绪"
 
 #: ardour_ui.cc:996
 msgid ""
-"WARNING: Your system has a limit for maximum amount of locked memory. This "
-"might cause %1 to run out of memory before your system runs out of memory. \n"
+"WARNING: Your system has a limit for maximum amount of locked memory. This might "
+"cause %1 to run out of memory before your system runs out of memory. \n"
 "\n"
-"You can view the memory limit with 'ulimit -l', and it is normally "
-"controlled by %2"
+"You can view the memory limit with 'ulimit -l', and it is normally controlled by %2"
 msgstr ""
+"警告:您的系统有对于锁定内存的最大数量限制。这可能会在您的系统耗尽内存之前,首先导"
+"致 %1 无内存可用。\n"
+"\n"
+"您可以使用“ulimit -l”命令来查看内存限制,通常它由 %2 来控制。"
 
 #: ardour_ui.cc:1013
 msgid "Do not show this window again"
@@ -858,10 +929,15 @@ msgid ""
 "\n"
 "\"Just quit\" option."
 msgstr ""
+"%1 无法保存您的会话。\n"
+"\n"
+"如果您仍打算退出,\n"
+"\n"
+"请启用“不保存而退出”选项。"
 
 #: ardour_ui.cc:1119
 msgid "Unsaved Session"
-msgstr "未保存的会话"
+msgstr " 尚未保存的会话"
 
 #: ardour_ui.cc:1140
 msgid ""
@@ -873,12 +949,12 @@ msgid ""
 "\n"
 "What do you want to do?"
 msgstr ""
-"此会话 \"%1\" 未保存.\n"
+"此会话 \"%1\" 尚未保存.\n"
 "\n"
 "刚才所作的修改将会丢失\n"
-"除非你保存它.\n"
+"除非您保存它。\n"
 "\n"
-"你想干吗?"
+"您打算如何做?"
 
 #: ardour_ui.cc:1143
 msgid ""
@@ -890,34 +966,34 @@ msgid ""
 "\n"
 "What do you want to do?"
 msgstr ""
-"此快照 \"%1\" 未保存.\n"
+"此快照 \"%1\" 尚未保存。\n"
 "\n"
 "刚才所作的修改将会丢失\n"
-"除非你保存它.\n"
+"除非您保存它。\n"
 "\n"
-"你想干吗?"
+"您打算如何做?"
 
 #: ardour_ui.cc:1157
 msgid "Prompter"
-msgstr ""
+msgstr "提词机"
 
 #: ardour_ui.cc:1269 ardour_ui.cc:1277
 msgid "Audio: <span foreground=\"red\">none</span>"
-msgstr ""
+msgstr "音频:<span foreground=\"red\">无</span>"
 
 #: ardour_ui.cc:1281
 #, c-format
 msgid "Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"
-msgstr ""
+msgstr "音频: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"
 
 #: ardour_ui.cc:1285
 #, c-format
 msgid "Audio: <span foreground=\"green\">%<PRId64> kHz / %4.1f ms</span>"
-msgstr ""
+msgstr "音频:<span foreground=\"green\">%<PRId64> kHz / %4.1f ms</span>"
 
 #: ardour_ui.cc:1303 export_video_dialog.cc:80
 msgid "File:"
-msgstr ""
+msgstr "文件:"
 
 #: ardour_ui.cc:1307
 msgid "BWF"
@@ -933,7 +1009,7 @@ msgstr ""
 
 #: ardour_ui.cc:1316 session_option_editor.cc:185
 msgid "CAF"
-msgstr "CAF"
+msgstr ""
 
 #: ardour_ui.cc:1319
 msgid "AIFF"
@@ -959,43 +1035,46 @@ msgstr ""
 msgid "16-int"
 msgstr ""
 
+# DSP 数字信号处理器(Digital Signal Processor)
 #: ardour_ui.cc:1358
 #, c-format
 msgid "DSP: <span foreground=\"%s\">%5.1f%%</span>"
-msgstr ""
+msgstr "数字信号处理器: <span foreground=\"%s\">%5.1f%%</span>"
 
 #: ardour_ui.cc:1377
 #, c-format
 msgid ""
-"Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">"
-"%<PRIu32>%%</span> <span foreground=\"green\">c:</span><span foreground=\"%s"
-"\">%<PRIu32>%%</span>"
+"Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span> <span foreground=\"green\">c:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span>"
 msgstr ""
+"缓冲区: <span foreground=\"green\">p:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span> <span foreground=\"green\">c:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span>"
 
 #: ardour_ui.cc:1418
 msgid "Disk: <span foreground=\"green\">Unknown</span>"
-msgstr ""
+msgstr "硬盘: <span foreground=\"green\">Unknown</span>"
 
 #: ardour_ui.cc:1420
 msgid "Disk: <span foreground=\"green\">24hrs+</span>"
-msgstr ""
+msgstr "硬盘:<span foreground=\"green\">24hrs+</span>"
 
 #: ardour_ui.cc:1438
 msgid "Disk: <span foreground=\"green\">>24 hrs</span>"
-msgstr ""
+msgstr "硬盘:<span foreground=\"green\">>24 hrs</span>"
 
 #: ardour_ui.cc:1449
 #, c-format
 msgid "Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"
-msgstr ""
+msgstr "硬盘:<span foreground=\"%s\">%02dh:%02dm:%02ds</span>"
 
 #: ardour_ui.cc:1475
 #, c-format
 msgid "Timecode|TC: <span foreground=\"%s\">%s</span>"
-msgstr ""
+msgstr "时间码|TC:<span foreground=\"%s\">%s</span>"
 
-#: ardour_ui.cc:1596 ardour_ui.cc:1605 session_dialog.cc:318
-#: session_dialog.cc:323
+#: ardour_ui.cc:1596 ardour_ui.cc:1605 session_dialog.cc:318 session_dialog.cc:323
 msgid "Recent Sessions"
 msgstr "最近的会话"
 
@@ -1004,6 +1083,8 @@ msgid ""
 "%1 is not connected to any audio backend.\n"
 "You cannot open or close sessions in this condition"
 msgstr ""
+"%1 没有连接到任何音频后端。\n"
+"在这种情况下您不能打开或关闭会话"
 
 #: ardour_ui.cc:1708
 msgid "Open Session"
@@ -1016,13 +1097,12 @@ msgstr "%1 会话"
 
 #: ardour_ui.cc:1770
 msgid "You cannot add a track without a session already loaded."
-msgstr "您只能在已载入的会话中添加音轨"
+msgstr "在没有任何一个会话被载入之前,您不能添加音轨。"
 
 #: ardour_ui.cc:1778
 msgid "could not create %1 new mixed track"
 msgid_plural "could not create %1 new mixed tracks"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "无法创建 %1 新的混音轨道"
 
 #: ardour_ui.cc:1784 ardour_ui.cc:1845
 msgid ""
@@ -1031,32 +1111,36 @@ msgid ""
 "You should save %1, exit and\n"
 "restart with more ports."
 msgstr ""
+"没有足够可用的端口\n"
+"去创建一个新的音轨或总线。\n"
+"您应当保存 %1,\n"
+"退出并且带着更多的端口重新启动。"
 
 #: ardour_ui.cc:1819
 msgid "You cannot add a track or bus without a session already loaded."
-msgstr "您只能在已载入的会话或总线中添加音轨和总线"
+msgstr "在没有任何一个会话被载入之前,您不能添加音轨或总线。"
 
 #: ardour_ui.cc:1828
 msgid "could not create %1 new audio track"
 msgid_plural "could not create %1 new audio tracks"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "无法创建 %1 新的音频轨道"
 
 #: ardour_ui.cc:1837
 msgid "could not create %1 new audio bus"
 msgid_plural "could not create %1 new audio busses"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "无法创建 %1 新的音频总线"
 
 #: ardour_ui.cc:1990
 msgid ""
 "Please create one or more tracks before trying to record.\n"
 "You can do this with the \"Add Track or Bus\" option in the Session menu."
 msgstr ""
+"在录制之前请先创建一条或多条音轨。\n"
+"您可以使用会话菜单中的“添加音轨或总线”选项来实现。"
 
 #: ardour_ui.cc:2376
 msgid "Save as..."
-msgstr ""
+msgstr "另存为…"
 
 #: ardour_ui.cc:2377 ardour_ui.cc:2456
 msgid "New session name"
@@ -1064,7 +1148,7 @@ msgstr "新建快照的名称"
 
 #: ardour_ui.cc:2379
 msgid "Take Snapshot"
-msgstr "å¿«ç…§"
+msgstr "生成快照"
 
 #: ardour_ui.cc:2380
 msgid "Name of new snapshot"
@@ -1075,6 +1159,8 @@ msgid ""
 "To ensure compatibility with various systems\n"
 "snapshot names may not contain a '%1' character"
 msgstr ""
+"为了确保在不同系统间的兼容性\n"
+"快照名称不能包含' % 1 '字符"
 
 #: ardour_ui.cc:2417
 msgid "Confirm Snapshot Overwrite"
@@ -1082,7 +1168,7 @@ msgstr "确定覆盖快照"
 
 #: ardour_ui.cc:2418
 msgid "A snapshot already exists with that name.  Do you want to overwrite it?"
-msgstr "已存在同名快照. 覆盖之?"
+msgstr "已存在相同名称的快照。您打算覆盖它?"
 
 #: ardour_ui.cc:2421 utils_videotl.cc:74
 msgid "Overwrite"
@@ -1097,11 +1183,12 @@ msgid ""
 "To ensure compatibility with various systems\n"
 "session names may not contain a '%1' character"
 msgstr ""
+"为了确保在不同系统间的兼容性\n"
+"会话名称不能包含' % 1 '字符"
 
 #: ardour_ui.cc:2478
-msgid ""
-"That name is already in use by another directory/folder. Please try again."
-msgstr "此名称已被另一个文件夹使用. 请再尝试一遍."
+msgid "That name is already in use by another directory/folder. Please try again."
+msgstr "此名称已被另一个目录/文件夹使用。 请再尝试另一个。"
 
 #: ardour_ui.cc:2487
 msgid ""
@@ -1109,7 +1196,7 @@ msgid ""
 "Things could be seriously messed up at this point"
 msgstr ""
 "重命名会话失败.\n"
-"从现在开始事情将会变得乱七八糟"
+"从现在开始事情真的将会变得很麻烦。"
 
 #: ardour_ui.cc:2602
 msgid "Save Template"
@@ -1131,7 +1218,7 @@ msgid ""
 msgstr ""
 "会话\n"
 "%1\n"
-"已存在. 打开它?"
+"已存在。是否 打开它?"
 
 #: ardour_ui.cc:2653
 msgid "Open Existing Session"
@@ -1139,27 +1226,27 @@ msgstr "打开已存在的会话"
 
 #: ardour_ui.cc:2914
 msgid "There is no existing session at \"%1\""
-msgstr " \"%1\" 没有会话文件"
+msgstr "在 \"%1\" 没有会话文件"
 
 #: ardour_ui.cc:3006
 msgid "Please wait while %1 loads your session"
-msgstr "请等待 %1 载入会话"
+msgstr "请等待 %1 载入您的会话"
 
 #: ardour_ui.cc:3021
 msgid "Port Registration Error"
-msgstr "端口(port)注册错误"
+msgstr "端口注册错误"
 
 #: ardour_ui.cc:3022
 msgid "Click the Close button to try again."
-msgstr "单击关闭按钮,再尝试一遍"
+msgstr "请单击关闭按钮,再尝试一遍"
 
 #: ardour_ui.cc:3043
 msgid "Session \"%1 (snapshot %2)\" did not load successfully"
-msgstr "会话  \"%1 (快照 %2)\" 装载失败."
+msgstr "会话  \"%1 (快照 %2)\" 载入失败"
 
 #: ardour_ui.cc:3049
 msgid "Loading Error"
-msgstr "装载错误"
+msgstr "载入错误"
 
 #: ardour_ui.cc:3068
 msgid ""
@@ -1167,10 +1254,13 @@ msgid ""
 "\n"
 "You will not be able to record or save."
 msgstr ""
+"本次会话已经以只读模式打开。\n"
+"\n"
+"您不能录制或者保存。"
 
 #: ardour_ui.cc:3073
 msgid "Read-only Session"
-msgstr ""
+msgstr "只读会话"
 
 #: ardour_ui.cc:3139
 msgid "Could not create session in \"%1\""
@@ -1192,18 +1282,22 @@ msgid ""
 "These may still include regions that\n"
 "require some unused files to continue to exist."
 msgstr ""
+"如果这情况看起来有点异常,\n"
+"请检查任何已存在的快照。\n"
+"它们也许仍包括有某些范围\n"
+" 需要继续保留某些未使用的文件。"
 
 #: ardour_ui.cc:3352
 msgid "kilo"
-msgstr ""
+msgstr "千"
 
 #: ardour_ui.cc:3355
 msgid "mega"
-msgstr ""
+msgstr "兆(百万)"
 
 #: ardour_ui.cc:3358
 msgid "giga"
-msgstr ""
+msgstr "十亿(千兆)"
 
 #: ardour_ui.cc:3363
 msgid ""
@@ -1213,7 +1307,8 @@ msgid_plural ""
 "The following %1 files were deleted from %2,\n"
 "releasing %3 %4bytes of disk space"
 msgstr[0] ""
-msgstr[1] ""
+"以下 %1 文件被从 %2 删除,\n"
+"释放 %3 %4 字节的磁盘空间"
 
 #: ardour_ui.cc:3370
 msgid ""
@@ -1235,11 +1330,13 @@ msgid_plural ""
 "\n"
 "will release an additional %3 %4bytes of disk space.\n"
 msgstr[0] ""
-msgstr[1] ""
+"以下 %1 文件未被使用\n"
+"并且被移动到: %2  \n"
+"\n"
 
 #: ardour_ui.cc:3430
 msgid "Are you sure you want to clean-up?"
-msgstr "您确认要删除这些文件吗"
+msgstr "您确认要清空?"
 
 #: ardour_ui.cc:3437
 msgid ""
@@ -1247,9 +1344,9 @@ msgid ""
 "ALL undo/redo information will be lost if you clean-up.\n"
 "Clean-up will move all unused files to a \"dead\" location."
 msgstr ""
-"清空是毁灭性的操作.\n"
-"如果你清空了, 所有的撤销/重复信息将会丢失.\n"
-"清空将会把所有未使用过的文件弄到 \"死亡\" 位置"
+"清空是毁灭性的操作。\n"
+"如果你清空了, 所有的撤销/重做信息将会丢失。\n"
+"清空将会把所有未使用过的文件移动到 \"死亡\" 位置。"
 
 #: ardour_ui.cc:3445
 msgid "CleanupDialog"
@@ -1265,51 +1362,51 @@ msgstr "删除文件"
 
 #: ardour_ui.cc:3637
 msgid "Video-Server was not launched by %1. The request to stop it is ignored."
-msgstr ""
+msgstr "视频服务器未被 %1 触发。请求停止视频服务器的要求被忽略。"
 
 #: ardour_ui.cc:3641
 msgid "Stop Video-Server"
-msgstr ""
+msgstr "停止视频服务器"
 
 #: ardour_ui.cc:3642
 msgid "Do you really want to stop the Video Server?"
-msgstr ""
+msgstr "您真的打算停止视频服务器?"
 
 #: ardour_ui.cc:3645
 msgid "Yes, Stop It"
-msgstr ""
+msgstr "是的,停止它"
 
 #: ardour_ui.cc:3671
 msgid "The Video Server is already started."
-msgstr ""
+msgstr "视频服务器已经启动。"
 
 #: ardour_ui.cc:3673
 msgid ""
-"An external Video Server is configured and can be reached. Not starting a "
-"new instance."
-msgstr ""
+"An external Video Server is configured and can be reached. Not starting a new "
+"instance."
+msgstr "一个外部视频服务器已经配置且可以实现。尚未启动一个新的实例。"
 
 #: ardour_ui.cc:3681 ardour_ui.cc:3786
 msgid ""
-"Could not connect to the Video Server. Start it or configure its access URL "
-"in Preferences."
-msgstr ""
+"Could not connect to the Video Server. Start it or configure its access URL in "
+"Preferences."
+msgstr "无法连接到视频服务器。请启动或者配置视频服务器的访问URL网址首选项。"
 
 #: ardour_ui.cc:3711
 msgid "Specified docroot is not an existing directory."
-msgstr ""
+msgstr "指定的文档根目录不存在。"
 
 #: ardour_ui.cc:3717 ardour_ui.cc:3723
 msgid "Given Video Server is not an executable file."
-msgstr ""
+msgstr "给定的视频服务器不是一个可执行文件。"
 
 #: ardour_ui.cc:3757
 msgid "Cannot launch the video-server"
-msgstr ""
+msgstr "无法启动视频服务器"
 
 #: ardour_ui.cc:3767
 msgid "Video-server was started but does not respond to requests..."
-msgstr ""
+msgstr "视频服务器已经启动但没有响应请求……"
 
 #: ardour_ui.cc:3812 editor_audio_import.cc:641
 msgid "could not open %1"
@@ -1317,11 +1414,11 @@ msgstr "无法打开%1"
 
 #: ardour_ui.cc:3816
 msgid "no video-file selected"
-msgstr ""
+msgstr "尚未选择视频文件"
 
 #: ardour_ui.cc:4014
 msgid "Recording was stopped because your system could not keep up."
-msgstr "您的系统无法继续, 录音停止."
+msgstr "由于您的系统无法继续工作导致录制停止。"
 
 #: ardour_ui.cc:4043
 msgid ""
@@ -1331,26 +1428,27 @@ msgid ""
 "Specifically, it failed to write data to disk\n"
 "quickly enough to keep up with recording.\n"
 msgstr ""
-"您电脑的磁盘系统,\n"
-"无法跟上 %1.\n"
+"您电脑的硬盘系统\n"
+"无法持续跟进 %1 。\n"
 "\n"
-"确切地说, 磁盘的读写速度无法跟上录音速度\n"
+"确切地说,失败的原因是硬盘的写入速度\n"
+"不足以持续跟上录制的速度。\n"
 
 #: ardour_ui.cc:4113
 msgid "Scanning for plugins"
-msgstr ""
+msgstr "正在扫描插件"
 
 #: ardour_ui.cc:4115
 msgid "Cancel plugin scan"
-msgstr ""
+msgstr "取消插件扫描"
 
 #: ardour_ui.cc:4124
 msgid "Stop Timeout"
-msgstr ""
+msgstr "停止超时"
 
 #: ardour_ui.cc:4131
 msgid "Scan Timeout"
-msgstr ""
+msgstr "扫描超时"
 
 #: ardour_ui.cc:4174
 msgid ""
@@ -1360,10 +1458,11 @@ msgid ""
 "Specifically, it failed to read data from disk\n"
 "quickly enough to keep up with playback.\n"
 msgstr ""
-"您电脑的磁盘系统,\n"
-"无法跟上 %1.\n"
+"您电脑的硬盘系统\n"
+"无法持续跟进 %1 。\n"
 "\n"
-"确切地说, 磁盘的读写速度无法跟上播放速度\n"
+"确切地说,失败的原因是硬盘的读取速度\n"
+"不足以持续跟上回放的速度。\n"
 
 #: ardour_ui.cc:4214
 msgid "Crash Recovery"
@@ -1379,10 +1478,17 @@ msgid ""
 "you, or it can ignore it. Please decide\n"
 "what you would like to do.\n"
 msgstr ""
+"本会话似乎是一直处在\n"
+"录制的中段,当 %1 时\n"
+"或者在计算机关闭时。\n"
+"\n"
+" %1 可以为您恢复任何已捕获的音频,\n"
+"或者忽略它。\n"
+"请确认您的决定。\n"
 
 #: ardour_ui.cc:4227
 msgid "Ignore crash data"
-msgstr "忽略崩毁的数据"
+msgstr "忽略崩溃的数据"
 
 #: ardour_ui.cc:4228
 msgid "Recover from crash"
@@ -1398,22 +1504,25 @@ msgid ""
 "%2 is currently running at %3 Hz.  If you load this session,\n"
 "audio may be played at the wrong sample rate.\n"
 msgstr ""
+"本会话已经创建 %1 Hz 的采样率,\n"
+"但是 %2 目前运行在 %3 Hz。如果您加载这个会话,\n"
+"音频可能会处在错误的采样率上播放。\n"
 
 #: ardour_ui.cc:4258
 msgid "Do not load session"
-msgstr "不要装载会话"
+msgstr "不要载入会话"
 
 #: ardour_ui.cc:4259
 msgid "Load session anyway"
-msgstr "转载会话"
+msgstr "只管载入会话"
 
 #: ardour_ui.cc:4286
 msgid "Could not disconnect from Audio/MIDI engine"
-msgstr ""
+msgstr "无法从音频/MIDI引擎上取消连接"
 
 #: ardour_ui.cc:4303 ardour_ui.cc:4306
 msgid "Could not reconnect to the Audio/MIDI engine"
-msgstr ""
+msgstr "无法重新连接到音频/MIDI引擎"
 
 #: ardour_ui.cc:4590
 msgid ""
@@ -1429,22 +1538,33 @@ msgid ""
 "\n"
 "From now on, use the -2000 version with older versions of %3"
 msgstr ""
+"%4 这是一个来源于 %3%5 旧版本的会话\n"
+"\n"
+"%3 已经被复制到旧的会话文件\n"
+"\n"
+"%6%1%7\n"
+"\n"
+"to\n"
+"\n"
+"%6%2%7\n"
+"\n"
+"从现在开始,使用连带旧版 %3 的 -2000 版本"
 
 #: ardour_ui2.cc:73
 msgid "UI: cannot setup editor"
-msgstr "用户界面: 无法设置编辑器."
+msgstr "用户界面:无法设置编辑器"
 
 #: ardour_ui2.cc:78
 msgid "UI: cannot setup mixer"
-msgstr "用户界面: 无法设置混音器."
+msgstr "用户界面:无法设置混音器"
 
 #: ardour_ui2.cc:83
 msgid "UI: cannot setup meterbridge"
-msgstr ""
+msgstr "用户界面:无法设置节拍桥接"
 
 #: ardour_ui2.cc:128
 msgid "Play from playhead"
-msgstr "从播放头播放"
+msgstr "从指针开始播放"
 
 #: ardour_ui2.cc:129
 msgid "Stop playback"
@@ -1452,11 +1572,11 @@ msgstr "停止回放"
 
 #: ardour_ui2.cc:130
 msgid "Toggle record"
-msgstr "出发录音"
+msgstr "切换录制"
 
 #: ardour_ui2.cc:131
 msgid "Play range/selection"
-msgstr "播放范围/选区"
+msgstr "播放范围/已选择部分"
 
 #: ardour_ui2.cc:132
 msgid "Go to start of session"
@@ -1475,28 +1595,32 @@ msgid ""
 "MIDI Panic\n"
 "Send note off and reset controller messages on all MIDI channels"
 msgstr ""
+"MIDI 终止\n"
+"发送音符关闭和复位控制器信息到所有 MIDI 通道"
 
 #: ardour_ui2.cc:136
 msgid "Return to last playback start when stopped"
-msgstr "当停止时返回至最后一次回放起点"
+msgstr "当停止时返回至最后一次回放的起点"
 
 #: ardour_ui2.cc:137
 msgid "Playhead follows Range Selections and Edits"
-msgstr ""
+msgstr "指针跟随范围已选择部分并编辑"
 
 #: ardour_ui2.cc:138
 msgid "Be sensible about input monitoring"
-msgstr ""
+msgstr "确保清晰的输入监控"
 
 #: ardour_ui2.cc:139
 msgid "Enable/Disable audio click"
-msgstr ""
+msgstr "启用/禁用音频识别声(节拍器) "
 
 #: ardour_ui2.cc:140 monitor_section.cc:111
 msgid ""
 "When active, something is soloed.\n"
 "Click to de-solo everything"
 msgstr ""
+"启用时,仅独奏某部分。\n"
+"Click to de-solo everything 点击全部不独奏"
 
 #: ardour_ui2.cc:141
 msgid ""
@@ -1508,43 +1632,51 @@ msgstr ""
 
 #: ardour_ui2.cc:142
 msgid "When active, there is a feedback loop."
-msgstr ""
+msgstr "启用时,有一个反馈回路。"
 
 #: ardour_ui2.cc:143
 msgid ""
-"<b>Primary Clock</b> right-click to set display mode. Click to edit, click"
-"+drag a digit or mouse-over+scroll wheel to modify.\n"
-"Text edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: "
-"confirm; postfix the edit with '+' or '-' to enter delta times.\n"
+"<b>Primary Clock</b> right-click to set display mode. Click to edit, click+drag a "
+"digit or mouse-over+scroll wheel to modify.\n"
+"Text edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: confirm; "
+"postfix the edit with '+' or '-' to enter delta times.\n"
 msgstr ""
+"<b>主计时器</b>右键点击设置显示模式。点击即可编辑,点击+拖动数字或者鼠标放在数字上"
+"面滚动滚轮即可修改数字。\n"
+"文本编辑:从右到左覆盖 <tt>Esc 键</tt>:取消; <tt>回车键</tt>:确认;编辑后加"
+"上“+”号或者“-”号即可进入下一级时间\n"
 
 #: ardour_ui2.cc:144
 msgid ""
-"<b>Secondary Clock</b> right-click to set display mode. Click to edit, click"
-"+drag a digit or mouse-over+scroll wheel to modify.\n"
-"Text edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: "
-"confirm; postfix the edit with '+' or '-' to enter delta times.\n"
+"<b>Secondary Clock</b> right-click to set display mode. Click to edit, click+drag "
+"a digit or mouse-over+scroll wheel to modify.\n"
+"Text edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: confirm; "
+"postfix the edit with '+' or '-' to enter delta times.\n"
 msgstr ""
+"<b>第二计时器</b>右键点击设置显示模式。点击即可编辑,点击+拖动数字或者鼠标放在数字"
+"上面滚动滚轮即可修改数字。\n"
+"文本编辑:从右到左覆盖 <tt>Esc 键</tt>:取消; <tt>回车键</tt>:确认;编辑后加"
+"上“+”号或者“-”号即可进入下一级时间\n"
 
 #: ardour_ui2.cc:145
 msgid "Reset All Peak Indicators"
-msgstr ""
+msgstr "重置所有峰值指标"
 
 #: ardour_ui2.cc:146
 msgid "Show Error Log and acknowledge warnings"
-msgstr ""
+msgstr "显示错误日志并确认警报"
 
 #: ardour_ui2.cc:179
 msgid "[ERROR]: "
-msgstr "[错误]:"
+msgstr "【错误】:"
 
 #: ardour_ui2.cc:182
 msgid "[WARNING]: "
-msgstr "[警告]:"
+msgstr "【警告】:"
 
 #: ardour_ui2.cc:185
 msgid "[INFO]: "
-msgstr "[信息]: "
+msgstr "【信息】:"
 
 #: ardour_ui2.cc:253 ardour_ui_ed.cc:403
 msgid "Auto Return"
@@ -1552,22 +1684,23 @@ msgstr "自动返回"
 
 #: ardour_ui2.cc:255 ardour_ui_ed.cc:406
 msgid "Follow Edits"
-msgstr ""
+msgstr "跟随编辑"
 
+# GUI - Graphical User Interface
 #: ardour_ui2.cc:716 rc_option_editor.cc:2300
 msgid "GUI"
-msgstr ""
+msgstr "图形用户界面"
 
 #: ardour_ui2.cc:733 rc_option_editor.cc:1309 rc_option_editor.cc:1327
 #: rc_option_editor.cc:1330 rc_option_editor.cc:1332 rc_option_editor.cc:1334
 #: rc_option_editor.cc:1342 rc_option_editor.cc:1350 rc_option_editor.cc:1352
 #: rc_option_editor.cc:1360 rc_option_editor.cc:1367 rc_option_editor.cc:1376
 #: rc_option_editor.cc:1378 rc_option_editor.cc:1380 rc_option_editor.cc:1388
-#: rc_option_editor.cc:1390 rc_option_editor.cc:1399
-#: session_option_editor.cc:321 session_option_editor.cc:323
-#: session_option_editor.cc:344 session_option_editor.cc:346
-#: session_option_editor.cc:348 session_option_editor.cc:355
-#: session_option_editor.cc:362 session_option_editor.cc:366
+#: rc_option_editor.cc:1390 rc_option_editor.cc:1399 session_option_editor.cc:321
+#: session_option_editor.cc:323 session_option_editor.cc:344
+#: session_option_editor.cc:346 session_option_editor.cc:348
+#: session_option_editor.cc:355 session_option_editor.cc:362
+#: session_option_editor.cc:366
 msgid "Misc"
 msgstr "杂项"
 
@@ -1585,11 +1718,11 @@ msgstr "重新装摘会话历史"
 
 #: ardour_ui_dialogs.cc:250
 msgid "Don't close"
-msgstr "别关闭"
+msgstr "请勿关闭"
 
 #: ardour_ui_dialogs.cc:251
 msgid "Just close"
-msgstr "不保存而关闭"
+msgstr "只管关闭"
 
 #: ardour_ui_dialogs.cc:252
 msgid "Save and close"
@@ -1597,14 +1730,14 @@ msgstr "保存并关闭"
 
 #: ardour_ui_dialogs.cc:362
 msgid "This screen is not tall enough to display the mixer window"
-msgstr ""
+msgstr "这个屏幕的高度不足以显示混音器窗口"
 
 #: ardour_ui_ed.cc:102
 msgid "Session"
 msgstr "会话"
 
-#: ardour_ui_ed.cc:105 editor_actions.cc:138 editor_regions.cc:116
-#: port_group.cc:458 session_option_editor.cc:82 session_option_editor.cc:89
+#: ardour_ui_ed.cc:105 editor_actions.cc:138 editor_regions.cc:116 port_group.cc:458
+#: session_option_editor.cc:82 session_option_editor.cc:89
 msgid "Sync"
 msgstr "同步"
 
@@ -1622,7 +1755,7 @@ msgstr "帮助"
 
 #: ardour_ui_ed.cc:109
 msgid "Misc. Shortcuts"
-msgstr "杂项. 快捷键"
+msgstr "杂项、 快捷键"
 
 #: ardour_ui_ed.cc:110
 msgid "Audio File Format"
@@ -1638,7 +1771,7 @@ msgstr "采样格式"
 
 #: ardour_ui_ed.cc:113 rc_option_editor.cc:2245 rc_option_editor.cc:2257
 msgid "Control Surfaces"
-msgstr "控制表面"
+msgstr "控制面"
 
 #: ardour_ui_ed.cc:114 rc_option_editor.cc:1921 rc_option_editor.cc:2264
 msgid "Plugins"
@@ -1646,31 +1779,31 @@ msgstr "插件"
 
 #: ardour_ui_ed.cc:115 rc_option_editor.cc:2351
 msgid "Metering"
-msgstr ""
+msgstr "节拍"
 
 #: ardour_ui_ed.cc:116
 msgid "Fall Off Rate"
-msgstr ""
+msgstr "衰减率"
 
 #: ardour_ui_ed.cc:117
 msgid "Hold Time"
-msgstr ""
+msgstr "持续时间"
 
 #: ardour_ui_ed.cc:118
 msgid "Denormal Handling"
-msgstr ""
+msgstr "非常规处理"
 
 #: ardour_ui_ed.cc:122 route_time_axis.cc:1677
 msgid "New..."
-msgstr "新建..."
+msgstr "新建…"
 
 #: ardour_ui_ed.cc:124
 msgid "Open..."
-msgstr "打开..."
+msgstr "打开…"
 
 #: ardour_ui_ed.cc:125
 msgid "Recent..."
-msgstr "最近..."
+msgstr "最近的…"
 
 #: ardour_ui_ed.cc:126 panner_editor.cc:29 playlist_selector.cc:64
 msgid "Close"
@@ -1678,36 +1811,36 @@ msgstr "关闭"
 
 #: ardour_ui_ed.cc:129
 msgid "Add Track or Bus..."
-msgstr "添加音轨或总线..."
+msgstr "添加音轨或总线…"
 
 #: ardour_ui_ed.cc:134
 msgid "Open Video"
-msgstr ""
+msgstr "打开视频"
 
 #: ardour_ui_ed.cc:137
 msgid "Remove Video"
-msgstr ""
+msgstr "移除视频"
 
 #: ardour_ui_ed.cc:140
 msgid "Export To Video File"
-msgstr ""
+msgstr "导出为视频文件"
 
 #: ardour_ui_ed.cc:144
 msgid "Snapshot..."
-msgstr "å¿«ç…§..."
+msgstr "快照…"
 
 #: ardour_ui_ed.cc:148
 msgid "Save As..."
-msgstr "另存为..."
+msgstr "另存为…"
 
 #: ardour_ui_ed.cc:152 editor_actions.cc:1771 editor_markers.cc:903
 #: editor_snapshots.cc:124 mixer_strip.cc:1518 route_time_axis.cc:1673
 msgid "Rename..."
-msgstr "重命名..."
+msgstr "重命名…"
 
 #: ardour_ui_ed.cc:156
 msgid "Save Template..."
-msgstr "保存模板..."
+msgstr "保存模板…"
 
 #: ardour_ui_ed.cc:159
 msgid "Metadata"
@@ -1715,19 +1848,19 @@ msgstr "元数据"
 
 #: ardour_ui_ed.cc:162
 msgid "Edit Metadata..."
-msgstr "编辑元数据..."
+msgstr "编辑元数据…"
 
 #: ardour_ui_ed.cc:165
 msgid "Import Metadata..."
-msgstr "导入元数据..."
+msgstr "导入元数据…"
 
 #: ardour_ui_ed.cc:168
 msgid "Export To Audio File(s)..."
-msgstr "导出为音频文件..."
+msgstr "导出为音频文件…"
 
 #: ardour_ui_ed.cc:171
 msgid "Stem export..."
-msgstr ""
+msgstr "主体导出…"
 
 #: ardour_ui_ed.cc:174 editor_export_audio.cc:65 export_dialog.cc:129
 #: export_video_dialog.cc:84
@@ -1736,7 +1869,7 @@ msgstr "导出"
 
 #: ardour_ui_ed.cc:177
 msgid "Clean-up Unused Sources..."
-msgstr "清空未使用的源..."
+msgstr "清空未使用的源…"
 
 #: ardour_ui_ed.cc:181
 msgid "Flush Wastebasket"
@@ -1748,39 +1881,39 @@ msgstr "退出"
 
 #: ardour_ui_ed.cc:192
 msgid "Maximise Editor Space"
-msgstr "最大化编辑空间"
+msgstr "最大化编辑器空间"
 
 #: ardour_ui_ed.cc:193
 msgid "Maximise Mixer Space"
-msgstr ""
+msgstr "最大化混音器空间"
 
 #: ardour_ui_ed.cc:194
 msgid "Show Toolbars"
-msgstr ""
+msgstr "显示工具栏"
 
 #: ardour_ui_ed.cc:198
 msgid "Show more UI preferences"
-msgstr ""
+msgstr "显示更多用户界面首选项"
 
 #: ardour_ui_ed.cc:200 mixer_ui.cc:1924 mixer_ui.cc:1930
 msgid "Window|Mixer"
-msgstr ""
+msgstr "窗口|混音器"
 
 #: ardour_ui_ed.cc:201
 msgid "Toggle Editor+Mixer"
-msgstr ""
+msgstr "切换编辑器+混音器"
 
 #: ardour_ui_ed.cc:202 meterbridge.cc:218 meterbridge.cc:224
 msgid "Window|Meterbridge"
-msgstr ""
+msgstr "窗口|节拍桥接"
 
 #: ardour_ui_ed.cc:204
 msgid "Reattach All Tearoffs"
-msgstr ""
+msgstr "重新附加所有的片段"
 
 #: ardour_ui_ed.cc:206 midi_tracer.cc:45
 msgid "MIDI Tracer"
-msgstr "MIDI示踪"
+msgstr "MIDI 音轨"
 
 #: ardour_ui_ed.cc:208
 msgid "Chat"
@@ -1788,7 +1921,7 @@ msgstr "聊天"
 
 #: ardour_ui_ed.cc:210
 msgid "Help|Manual"
-msgstr ""
+msgstr "帮助|手册"
 
 #: ardour_ui_ed.cc:211
 msgid "Reference"
@@ -1796,27 +1929,27 @@ msgstr "参考"
 
 #: ardour_ui_ed.cc:212
 msgid "Report A Bug"
-msgstr ""
+msgstr "报告故障"
 
 #: ardour_ui_ed.cc:213
 msgid "Cheat Sheet"
-msgstr ""
+msgstr "备忘录"
 
 #: ardour_ui_ed.cc:214
 msgid "Ardour Website"
-msgstr ""
+msgstr "Ardour 官网"
 
 #: ardour_ui_ed.cc:215
 msgid "Ardour Development"
-msgstr ""
+msgstr "Ardour 开发 "
 
 #: ardour_ui_ed.cc:216
 msgid "User Forums"
-msgstr ""
+msgstr "用户论坛"
 
 #: ardour_ui_ed.cc:217
 msgid "How to report a bug"
-msgstr ""
+msgstr "如何报告故障"
 
 #: ardour_ui_ed.cc:219 plugin_ui.cc:419
 msgid "Save"
@@ -1830,35 +1963,35 @@ msgstr "保存"
 #: rc_option_editor.cc:1579 rc_option_editor.cc:1582 rc_option_editor.cc:1584
 #: rc_option_editor.cc:1601 rc_option_editor.cc:1612
 msgid "Transport"
-msgstr ""
+msgstr "播送"
 
 #: ardour_ui_ed.cc:233
 msgid "Stop"
-msgstr "暂停"
+msgstr "停止"
 
 #: ardour_ui_ed.cc:236
 msgid "Roll"
-msgstr ""
+msgstr "滚动"
 
 #: ardour_ui_ed.cc:240 ardour_ui_ed.cc:243
 msgid "Start/Stop"
-msgstr "开始/暂停"
+msgstr "开始/停止"
 
 #: ardour_ui_ed.cc:246
 msgid "Start/Continue/Stop"
-msgstr "开始/继续/暂停"
+msgstr "开始/继续/停止"
 
 #: ardour_ui_ed.cc:249
 msgid "Stop and Forget Capture"
-msgstr "暂停并废弃录音"
+msgstr "暂停并且废弃已捕获内容"
 
 #: ardour_ui_ed.cc:259
 msgid "Transition To Roll"
-msgstr ""
+msgstr "过渡到滚动"
 
 #: ardour_ui_ed.cc:263
 msgid "Transition To Reverse"
-msgstr ""
+msgstr "过渡到反向"
 
 #: ardour_ui_ed.cc:267
 msgid "Play Loop Range"
@@ -1866,19 +1999,19 @@ msgstr "循环播放范围"
 
 #: ardour_ui_ed.cc:270
 msgid "Play Selection"
-msgstr ""
+msgstr "播放已选择部分"
 
 #: ardour_ui_ed.cc:273
 msgid "Play Selection w/Preroll"
-msgstr ""
+msgstr "播放已选择部分预滚"
 
 #: ardour_ui_ed.cc:277
 msgid "Enable Record"
-msgstr "启用录音"
+msgstr "启用录制"
 
 #: ardour_ui_ed.cc:280 ardour_ui_ed.cc:284
 msgid "Start Recording"
-msgstr "开始录音"
+msgstr "开始录制"
 
 #: ardour_ui_ed.cc:288
 msgid "Rewind"
@@ -1886,11 +2019,11 @@ msgstr "倒带"
 
 #: ardour_ui_ed.cc:291
 msgid "Rewind (Slow)"
-msgstr "倒带(慢速)"
+msgstr "倒带(慢速)"
 
 #: ardour_ui_ed.cc:294
 msgid "Rewind (Fast)"
-msgstr "倒带(快速)"
+msgstr "倒带(快速)"
 
 #: ardour_ui_ed.cc:297
 msgid "Forward"
@@ -1898,11 +2031,11 @@ msgstr "å¿«è¿›"
 
 #: ardour_ui_ed.cc:300
 msgid "Forward (Slow)"
-msgstr "快进(慢速)"
+msgstr "快进(慢速)"
 
 #: ardour_ui_ed.cc:303
 msgid "Forward (Fast)"
-msgstr "倒带(快速)"
+msgstr "快进(快速)"
 
 #: ardour_ui_ed.cc:306
 msgid "Go to Zero"
@@ -1918,55 +2051,55 @@ msgstr "转到末尾位置"
 
 #: ardour_ui_ed.cc:318
 msgid "Go to Wall Clock"
-msgstr "转到确切的本地时间"
+msgstr "转到计时点"
 
 #: ardour_ui_ed.cc:323 ardour_ui_ed.cc:326
 msgid "Numpad Decimal"
-msgstr ""
+msgstr "数字键盘十进制"
 
 #: ardour_ui_ed.cc:329
 msgid "Numpad 0"
-msgstr ""
+msgstr "数字键盘 0"
 
 #: ardour_ui_ed.cc:332
 msgid "Numpad 1"
-msgstr ""
+msgstr "数字键盘 1"
 
 #: ardour_ui_ed.cc:335
 msgid "Numpad 2"
-msgstr ""
+msgstr "数字键盘 2"
 
 #: ardour_ui_ed.cc:338
 msgid "Numpad 3"
-msgstr ""
+msgstr "数字键盘 3"
 
 #: ardour_ui_ed.cc:341
 msgid "Numpad 4"
-msgstr ""
+msgstr "数字键盘 4"
 
 #: ardour_ui_ed.cc:344
 msgid "Numpad 5"
-msgstr ""
+msgstr "数字键盘 5"
 
 #: ardour_ui_ed.cc:347
 msgid "Numpad 6"
-msgstr ""
+msgstr "数字键盘 6"
 
 #: ardour_ui_ed.cc:350
 msgid "Numpad 7"
-msgstr ""
+msgstr "数字键盘 7"
 
 #: ardour_ui_ed.cc:353
 msgid "Numpad 8"
-msgstr ""
+msgstr "数字键盘 8"
 
 #: ardour_ui_ed.cc:356
 msgid "Numpad 9"
-msgstr ""
+msgstr "数字键盘 9"
 
 #: ardour_ui_ed.cc:360
 msgid "Focus On Clock"
-msgstr "锁定时间指针"
+msgstr "聚焦于计时器"
 
 #: ardour_ui_ed.cc:364 ardour_ui_ed.cc:373 audio_clock.cc:2091 editor.cc:258
 #: editor_actions.cc:569 editor_actions.cc:578 export_timespan_selector.cc:88
@@ -1994,10 +2127,10 @@ msgstr "采样"
 msgid "Punch In"
 msgstr "切入"
 
-#: ardour_ui_ed.cc:383 mixer_strip.cc:1819 mixer_strip.cc:1843
-#: mixer_strip.cc:2007 route_ui.cc:162 time_info_box.cc:116
+#: ardour_ui_ed.cc:383 mixer_strip.cc:1819 mixer_strip.cc:1843 mixer_strip.cc:2007
+#: route_ui.cc:162 time_info_box.cc:116
 msgid "In"
-msgstr ""
+msgstr "å…¥"
 
 #: ardour_ui_ed.cc:386
 msgid "Punch Out"
@@ -2005,7 +2138,7 @@ msgstr "切出"
 
 #: ardour_ui_ed.cc:387 mixer_strip.cc:1831 time_info_box.cc:117
 msgid "Out"
-msgstr "ýstup"
+msgstr "出"
 
 #: ardour_ui_ed.cc:390
 msgid "Punch In/Out"
@@ -2033,11 +2166,11 @@ msgstr "同步启动到视频"
 
 #: ardour_ui_ed.cc:413
 msgid "Time Master"
-msgstr "时间主控"
+msgstr "计时器主控"
 
 #: ardour_ui_ed.cc:420
 msgid "Toggle Record Enable Track %1"
-msgstr ""
+msgstr "切换录制可用音轨 %1"
 
 #: ardour_ui_ed.cc:427
 msgid "Percentage"
@@ -2061,7 +2194,7 @@ msgstr "使用MMC"
 
 #: ardour_ui_ed.cc:438 rc_option_editor.cc:2097
 msgid "Send MIDI Clock"
-msgstr "发送MIDI时钟"
+msgstr "发送MIDI计时器"
 
 #: ardour_ui_ed.cc:440
 msgid "Send MIDI Feedback"
@@ -2069,15 +2202,15 @@ msgstr "发送MIDI反馈"
 
 #: ardour_ui_ed.cc:446
 msgid "Panic"
-msgstr ""
+msgstr "终止"
 
 #: ardour_ui_ed.cc:534
 msgid "Wall Clock"
-msgstr "本地时间"
+msgstr "计时点"
 
 #: ardour_ui_ed.cc:536
 msgid "Disk Space"
-msgstr "盘空间"
+msgstr "硬盘空间"
 
 #: ardour_ui_ed.cc:537
 msgid "DSP"
@@ -2089,7 +2222,7 @@ msgstr "缓冲"
 
 #: ardour_ui_ed.cc:540
 msgid "Timecode Format"
-msgstr ""
+msgstr " 时间码格式"
 
 #: ardour_ui_ed.cc:541
 msgid "File Format"
@@ -2100,6 +2233,8 @@ msgid ""
 "It is not possible to use JACK as the the sync source\n"
 "when the pull up/down setting is non-zero."
 msgstr ""
+"当拖动上/下的设置为非零时,\n"
+"不可能使用JACK作为同步源。"
 
 #: ardour_ui_options.cc:317
 msgid "Internal"
@@ -2111,11 +2246,11 @@ msgstr "启用/禁用外部位置同步"
 
 #: ardour_ui_options.cc:500
 msgid "Sync to JACK is not possible: video pull up/down is set"
-msgstr ""
+msgstr "不可能同步JACK:视频拖动上/下当前设置"
 
 #: audio_clock.cc:1047 audio_clock.cc:1066
 msgid "--pending--"
-msgstr ""
+msgstr "—搁置—"
 
 #: audio_clock.cc:1118
 msgid "SR"
@@ -2123,32 +2258,30 @@ msgstr ""
 
 #: audio_clock.cc:1124 audio_clock.cc:1128
 msgid "Pull"
-msgstr ""
+msgstr "拖动"
 
 #: audio_clock.cc:1126
 #, c-format
 msgid "%+.4f%%"
-msgstr ""
+msgstr "%+.4f%%"
 
-#: audio_clock.cc:1282 editor.cc:260 editor_actions.cc:139
-#: editor_actions.cc:561
+#: audio_clock.cc:1282 editor.cc:260 editor_actions.cc:139 editor_actions.cc:561
 msgid "Tempo"
 msgstr "节奏"
 
 #: audio_clock.cc:1286 editor.cc:261 editor_actions.cc:562
 msgid "Meter"
-msgstr "标尺"
+msgstr "节拍"
 
 #: audio_clock.cc:1864 audio_streamview.cc:115 editor_actions.cc:1089
 #: session_metadata_dialog.cc:452 session_metadata_dialog.cc:500
-#: session_metadata_dialog.cc:556 session_metadata_dialog.cc:845
-#: streamview.cc:470
+#: session_metadata_dialog.cc:556 session_metadata_dialog.cc:845 streamview.cc:470
 msgid "programming error: %1"
 msgstr "程序错误: %1"
 
 #: audio_clock.cc:1997 audio_clock.cc:2025
 msgid "programming error: %1 %2"
-msgstr ""
+msgstr "程序错误:%1 %2"
 
 #: audio_clock.cc:2093 editor.cc:257 export_timespan_selector.cc:98
 msgid "Bars:Beats"
@@ -2160,7 +2293,7 @@ msgstr "分:秒"
 
 #: audio_clock.cc:2099
 msgid "Set From Playhead"
-msgstr "从播放头设置"
+msgstr "从指针设置"
 
 #: audio_clock.cc:2100
 msgid "Locate to This Time"
@@ -2185,7 +2318,7 @@ msgstr "峰值幅度:"
 
 #: audio_region_editor.cc:91
 msgid "Calculating..."
-msgstr "计算中..."
+msgstr "计算中…"
 
 #: audio_region_view.cc:1243
 msgid "add gain control point"
@@ -2193,19 +2326,19 @@ msgstr "添加增益控制点"
 
 #: automation_controller.cc:286 automation_controller.cc:302
 msgid "Select Note..."
-msgstr ""
+msgstr "选择音符…"
 
 #: automation_controller.cc:293
 msgid "Halve"
-msgstr ""
+msgstr "减半"
 
 #: automation_controller.cc:296
 msgid "Double"
-msgstr ""
+msgstr "加倍"
 
 #: automation_controller.cc:307
 msgid "Set to %1 beat(s)"
-msgstr ""
+msgstr "设为 %1 拍"
 
 #: automation_line.cc:286 automation_line.cc:462
 msgid "automation event move"
@@ -2221,7 +2354,7 @@ msgstr "移除控制点"
 
 #: automation_line.cc:1003
 msgid "Ignoring illegal points on AutomationLine \"%1\""
-msgstr "忽略非法位置在AutomationLine: \"%1\""
+msgstr "忽略自动化线路上的非法点:“ %1 ”"
 
 #: automation_region_view.cc:190 automation_time_axis.cc:644
 msgid "add automation event"
@@ -2229,7 +2362,7 @@ msgstr "添加自动化事件"
 
 #: automation_streamview.cc:95
 msgid "unable to display automation region for control without list"
-msgstr ""
+msgstr "无法显示没有列表的自动化区域控制"
 
 #: automation_time_axis.cc:163
 msgid "automation state"
@@ -2243,14 +2376,13 @@ msgstr "隐藏音轨"
 #: automation_time_axis.cc:554 gain_meter.cc:220 generic_pluginui.cc:523
 #: generic_pluginui.cc:817 panner_ui.cc:151
 msgid "Automation|Manual"
-msgstr ""
+msgstr "自动化 | 手册"
 
 #: automation_time_axis.cc:310 automation_time_axis.cc:371
-#: automation_time_axis.cc:559 editor.cc:1904 editor.cc:1981
-#: editor_actions.cc:122 editor_actions.cc:1920 gain_meter.cc:223
-#: generic_pluginui.cc:99 generic_pluginui.cc:526 generic_pluginui.cc:819
-#: midi_time_axis.cc:1606 midi_time_axis.cc:1609 midi_time_axis.cc:1612
-#: panner_ui.cc:154
+#: automation_time_axis.cc:559 editor.cc:1904 editor.cc:1981 editor_actions.cc:122
+#: editor_actions.cc:1920 gain_meter.cc:223 generic_pluginui.cc:99
+#: generic_pluginui.cc:526 generic_pluginui.cc:819 midi_time_axis.cc:1606
+#: midi_time_axis.cc:1609 midi_time_axis.cc:1612 panner_ui.cc:154
 msgid "Play"
 msgstr "播放"
 
@@ -2258,13 +2390,13 @@ msgstr "播放"
 #: automation_time_axis.cc:564 gain_meter.cc:226 generic_pluginui.cc:101
 #: generic_pluginui.cc:529 generic_pluginui.cc:821 panner_ui.cc:157
 msgid "Write"
-msgstr ""
+msgstr "写入"
 
 #: automation_time_axis.cc:314 automation_time_axis.cc:393
 #: automation_time_axis.cc:569 gain_meter.cc:229 generic_pluginui.cc:103
 #: generic_pluginui.cc:532 generic_pluginui.cc:823 panner_ui.cc:160
 msgid "Touch"
-msgstr ""
+msgstr "触碰"
 
 #: automation_time_axis.cc:404 generic_pluginui.cc:535 meter_patterns.cc:112
 msgid "???"
@@ -2293,7 +2425,7 @@ msgstr "离散"
 
 #: automation_time_axis.cc:598 export_format_dialog.cc:485
 msgid "Linear"
-msgstr "先行"
+msgstr "线性"
 
 #: automation_time_axis.cc:604 rhythm_ferret.cc:109 shuttle_control.cc:197
 msgid "Mode"
@@ -2301,15 +2433,15 @@ msgstr "模式"
 
 #: bundle_manager.cc:182
 msgid "Disassociate"
-msgstr "使分离"
+msgstr "分隔"
 
 #: bundle_manager.cc:186
 msgid "Edit Bundle"
-msgstr "编辑捆绑"
+msgstr "编辑包裹"
 
 #: bundle_manager.cc:201
 msgid "Direction:"
-msgstr "方向:"
+msgstr "方向:"
 
 #: bundle_manager.cc:206 bundle_manager.cc:210 engine_dialog.cc:662
 #: mixer_strip.cc:162 mixer_strip.cc:367 mixer_strip.cc:2240
@@ -2318,13 +2450,13 @@ msgid "Input"
 msgstr "输入"
 
 #: bundle_manager.cc:207 bundle_manager.cc:212 bundle_manager.cc:246
-#: engine_dialog.cc:664 mixer_strip.cc:166 mixer_strip.cc:371
-#: mixer_strip.cc:2243 rc_option_editor.cc:2330
+#: engine_dialog.cc:664 mixer_strip.cc:166 mixer_strip.cc:371 mixer_strip.cc:2243
+#: rc_option_editor.cc:2330
 msgid "Output"
 msgstr "输出"
 
-#: bundle_manager.cc:265 editor.cc:1945 editor_actions.cc:94
-#: editor_actions.cc:104 rc_option_editor.cc:1087 rc_option_editor.cc:1094
+#: bundle_manager.cc:265 editor.cc:1945 editor_actions.cc:94 editor_actions.cc:104
+#: rc_option_editor.cc:1087 rc_option_editor.cc:1094
 msgid "Edit"
 msgstr "编辑"
 
@@ -2345,7 +2477,7 @@ msgstr "新建"
 
 #: bundle_manager.cc:333
 msgid "Bundle"
-msgstr "捆绑"
+msgstr "包裹"
 
 #: bundle_manager.cc:418
 msgid "Add Channel"
@@ -2373,23 +2505,23 @@ msgstr "音符"
 
 #: edit_note_dialog.cc:45
 msgid "Set selected notes to this channel"
-msgstr ""
+msgstr "设置已选中的音符为本声道"
 
 #: edit_note_dialog.cc:46
 msgid "Set selected notes to this pitch"
-msgstr ""
+msgstr "设置已选中的音符为本音高"
 
 #: edit_note_dialog.cc:47
 msgid "Set selected notes to this velocity"
-msgstr ""
+msgstr "设置已选中的音符为本力度"
 
 #: edit_note_dialog.cc:49
 msgid "Set selected notes to this time"
-msgstr ""
+msgstr "设置已选中的音符为本时间"
 
 #: edit_note_dialog.cc:51
 msgid "Set selected notes to this length"
-msgstr ""
+msgstr "设置已选中的音符为本长度"
 
 #: edit_note_dialog.cc:58 midi_list_editor.cc:105 patch_change_dialog.cc:90
 #: step_entry.cc:394
@@ -2398,7 +2530,7 @@ msgstr "音轨"
 
 #: edit_note_dialog.cc:68
 msgid "Pitch"
-msgstr "调子"
+msgstr "音高"
 
 #: edit_note_dialog.cc:78 step_entry.cc:408
 msgid "Velocity"
@@ -2408,9 +2540,9 @@ msgstr "力度"
 msgid "Time"
 msgstr "时间"
 
-#: edit_note_dialog.cc:98 editor_regions.cc:115
-#: export_timespan_selector.cc:378 export_timespan_selector.cc:440
-#: location_ui.cc:320 midi_list_editor.cc:115 time_info_box.cc:108
+#: edit_note_dialog.cc:98 editor_regions.cc:115 export_timespan_selector.cc:378
+#: export_timespan_selector.cc:440 location_ui.cc:320 midi_list_editor.cc:115
+#: time_info_box.cc:108
 msgid "Length"
 msgstr "长度"
 
@@ -2420,19 +2552,19 @@ msgstr "编辑音符"
 
 #: editor.cc:147
 msgid "CD Frames"
-msgstr "CD框架"
+msgstr "CD 框架"
 
 #: editor.cc:148
 msgid "TC Frames"
-msgstr ""
+msgstr "TC 框架"
 
 #: editor.cc:149
 msgid "TC Seconds"
-msgstr ""
+msgstr "TC 秒"
 
 #: editor.cc:150
 msgid "TC Minutes"
-msgstr ""
+msgstr "TC 分"
 
 #: editor.cc:151
 msgid "Seconds"
@@ -2444,75 +2576,75 @@ msgstr "分"
 
 #: editor.cc:153 quantize_dialog.cc:37 quantize_dialog.cc:141
 msgid "Beats/128"
-msgstr "节拍/128"
+msgstr "128拍"
 
 #: editor.cc:154 quantize_dialog.cc:38 quantize_dialog.cc:143
 msgid "Beats/64"
-msgstr "节拍/64"
+msgstr "64拍"
 
 #: editor.cc:155 quantize_dialog.cc:39 quantize_dialog.cc:145
 msgid "Beats/32"
-msgstr "节拍/32"
+msgstr "32拍"
 
 #: editor.cc:156
 msgid "Beats/28"
-msgstr "节拍/28"
+msgstr "28拍"
 
 #: editor.cc:157
 msgid "Beats/24"
-msgstr "节拍/24"
+msgstr "24拍"
 
 #: editor.cc:158
 msgid "Beats/20"
-msgstr "节拍/20"
+msgstr "20拍"
 
 #: editor.cc:159 quantize_dialog.cc:40 quantize_dialog.cc:147
 msgid "Beats/16"
-msgstr "节拍/16"
+msgstr "16拍"
 
 #: editor.cc:160
 msgid "Beats/14"
-msgstr "节拍/14"
+msgstr "14拍"
 
 #: editor.cc:161
 msgid "Beats/12"
-msgstr "节拍/12"
+msgstr "12拍"
 
 #: editor.cc:162
 msgid "Beats/10"
-msgstr "节拍/10"
+msgstr "10拍"
 
 #: editor.cc:163 quantize_dialog.cc:41 quantize_dialog.cc:149
 msgid "Beats/8"
-msgstr "节拍/8"
+msgstr "8拍"
 
 #: editor.cc:164
 msgid "Beats/7"
-msgstr "节拍/7"
+msgstr "7拍"
 
 #: editor.cc:165
 msgid "Beats/6"
-msgstr "节拍/6"
+msgstr "6拍"
 
 #: editor.cc:166
 msgid "Beats/5"
-msgstr "节拍/5"
+msgstr "5拍"
 
 #: editor.cc:167 quantize_dialog.cc:42 quantize_dialog.cc:151
 msgid "Beats/4"
-msgstr "节拍/4"
+msgstr "4拍"
 
 #: editor.cc:168 quantize_dialog.cc:43 quantize_dialog.cc:153
 msgid "Beats/3"
-msgstr "节拍/3"
+msgstr "3拍"
 
 #: editor.cc:169 quantize_dialog.cc:44 quantize_dialog.cc:155
 msgid "Beats/2"
-msgstr "节拍/2"
+msgstr "2拍"
 
 #: editor.cc:170 quantize_dialog.cc:45 quantize_dialog.cc:157
 msgid "Beats"
-msgstr "节拍"
+msgstr "1拍"
 
 #: editor.cc:171
 msgid "Bars"
@@ -2536,7 +2668,7 @@ msgstr "区域同步"
 
 #: editor.cc:176
 msgid "Region bounds"
-msgstr "区域界限"
+msgstr "区域边界"
 
 #: editor.cc:181 editor_actions.cc:510
 msgid "No Grid"
@@ -2548,11 +2680,11 @@ msgstr "网格"
 
 #: editor.cc:183 editor_actions.cc:512
 msgid "Magnetic"
-msgstr "磁性"
+msgstr "磁性吸附"
 
 #: editor.cc:188 editor.cc:206 editor_actions.cc:121 editor_actions.cc:493
 msgid "Playhead"
-msgstr "播放头"
+msgstr "指针"
 
 #: editor.cc:189 editor_actions.cc:495
 msgid "Marker"
@@ -2560,25 +2692,25 @@ msgstr "标记"
 
 #: editor.cc:190 editor.cc:207 editor_actions.cc:494
 msgid "Mouse"
-msgstr "é¼ "
+msgstr "é¼ æ ‡"
 
 #: editor.cc:195 editor_actions.cc:502
 msgid "Slide"
-msgstr ""
+msgstr "滑行"
 
 #: editor.cc:196
 msgid "Splice"
-msgstr ""
+msgstr "拼接"
 
 #: editor.cc:197 editor_actions.cc:501
 msgid "Ripple"
-msgstr ""
+msgstr "波纹"
 
-#: editor.cc:198 editor_actions.cc:157 editor_actions.cc:503
-#: editor_actions.cc:1789 editor_markers.cc:905 editor_rulers.cc:260
-#: location_ui.cc:58 mixer_strip.cc:195 mixer_strip.cc:2028
+#: editor.cc:198 editor_actions.cc:157 editor_actions.cc:503 editor_actions.cc:1789
+#: editor_markers.cc:905 editor_rulers.cc:260 location_ui.cc:58 mixer_strip.cc:195
+#: mixer_strip.cc:2028
 msgid "Lock"
-msgstr ""
+msgstr "锁定"
 
 #: editor.cc:203 mono_panner_editor.cc:42
 msgid "Left"
@@ -2598,31 +2730,31 @@ msgstr "编辑点"
 
 #: editor.cc:214
 msgid "Mushy"
-msgstr ""
+msgstr "模糊"
 
 #: editor.cc:215
 msgid "Smooth"
-msgstr ""
+msgstr "平滑"
 
 #: editor.cc:216
 msgid "Balanced multitimbral mixture"
-msgstr ""
+msgstr "平衡的多重音色混响乐"
 
 #: editor.cc:217
 msgid "Unpitched percussion with stable notes"
-msgstr ""
+msgstr "带有稳定音符的未定音高打击乐"
 
 #: editor.cc:218
 msgid "Crisp monophonic instrumental"
-msgstr ""
+msgstr "欢快的单声调乐器"
 
 #: editor.cc:219
 msgid "Unpitched solo percussion"
-msgstr ""
+msgstr "未定音高的独奏打击乐"
 
 #: editor.cc:220
 msgid "Resample without preserving pitch"
-msgstr ""
+msgstr "不保持音高的重新采样"
 
 #: editor.cc:256
 msgid "Mins:Secs"
@@ -2638,7 +2770,7 @@ msgstr "范围标记"
 
 #: editor.cc:264
 msgid "Loop/Punch Ranges"
-msgstr "循环/Punch 范围"
+msgstr "循环 / 切换范围"
 
 #: editor.cc:265 editor_actions.cc:565
 msgid "CD Markers"
@@ -2646,11 +2778,11 @@ msgstr "CD标记"
 
 #: editor.cc:266
 msgid "Video Timeline"
-msgstr ""
+msgstr "视频时间线"
 
 #: editor.cc:283
 msgid "mode"
-msgstr ""
+msgstr "模式"
 
 #: editor.cc:459 editor_actions.cc:114 editor_actions.cc:564
 msgid "Markers"
@@ -2658,31 +2790,31 @@ msgstr "标记"
 
 #: editor.cc:577 rc_option_editor.cc:1939
 msgid "Regions"
-msgstr ""
+msgstr "区域"
 
 #: editor.cc:578
 msgid "Tracks & Busses"
-msgstr "音轨&总线"
+msgstr "音轨 & 总线"
 
 #: editor.cc:579
 msgid "Snapshots"
-msgstr ""
+msgstr "å¿«ç…§"
 
 #: editor.cc:580
 msgid "Track & Bus Groups"
-msgstr ""
+msgstr "音轨 & 总线分组"
 
 #: editor.cc:581
 msgid "Ranges & Marks"
-msgstr ""
-
-#: editor.cc:728 editor.cc:5754 rc_option_editor.cc:1619
-#: rc_option_editor.cc:1627 rc_option_editor.cc:1635 rc_option_editor.cc:1643
-#: rc_option_editor.cc:1667 rc_option_editor.cc:1679 rc_option_editor.cc:1681
-#: rc_option_editor.cc:1689 rc_option_editor.cc:1697 rc_option_editor.cc:1717
-#: rc_option_editor.cc:1729 rc_option_editor.cc:1731 rc_option_editor.cc:1733
-#: rc_option_editor.cc:1741 rc_option_editor.cc:1749 rc_option_editor.cc:1757
-#: rc_option_editor.cc:1772 rc_option_editor.cc:1776 rc_option_editor.cc:1800
+msgstr "范围 & 标记"
+
+#: editor.cc:728 editor.cc:5754 rc_option_editor.cc:1619 rc_option_editor.cc:1627
+#: rc_option_editor.cc:1635 rc_option_editor.cc:1643 rc_option_editor.cc:1667
+#: rc_option_editor.cc:1679 rc_option_editor.cc:1681 rc_option_editor.cc:1689
+#: rc_option_editor.cc:1697 rc_option_editor.cc:1717 rc_option_editor.cc:1729
+#: rc_option_editor.cc:1731 rc_option_editor.cc:1733 rc_option_editor.cc:1741
+#: rc_option_editor.cc:1749 rc_option_editor.cc:1757 rc_option_editor.cc:1772
+#: rc_option_editor.cc:1776 rc_option_editor.cc:1800
 msgid "Editor"
 msgstr "编辑器"
 
@@ -2692,19 +2824,19 @@ msgstr "循环"
 
 #: editor.cc:1337 editor.cc:4762 editor_actions.cc:135 time_info_box.cc:68
 msgid "Punch"
-msgstr ""
+msgstr "切换"
 
 #: editor.cc:1449 rc_option_editor.cc:1661
 msgid "Linear (for highly correlated material)"
-msgstr ""
+msgstr "线性(高度相关的材料)"
 
 #: editor.cc:1459 rc_option_editor.cc:1662
 msgid "Constant power"
-msgstr ""
+msgstr "恒定功率"
 
 #: editor.cc:1468 rc_option_editor.cc:1663
 msgid "Symmetric"
-msgstr ""
+msgstr "对称"
 
 #: editor.cc:1478 rc_option_editor.cc:1664
 msgid "Slow"
@@ -2744,23 +2876,23 @@ msgstr "循环范围"
 
 #: editor.cc:1820 editor_markers.cc:950
 msgid "Zoom to Range"
-msgstr ""
+msgstr "缩放至整个范围"
 
 #: editor.cc:1829 editor_actions.cc:369
 msgid "Move Range Start to Previous Region Boundary"
-msgstr ""
+msgstr "移动范围起点到上一个区域边界"
 
 #: editor.cc:1836 editor_actions.cc:376
 msgid "Move Range Start to Next Region Boundary"
-msgstr ""
+msgstr "移动范围起点到下一个区域边界"
 
 #: editor.cc:1843 editor_actions.cc:383
 msgid "Move Range End to Previous Region Boundary"
-msgstr ""
+msgstr "移动范围终点到上一个区域边界"
 
 #: editor.cc:1850 editor_actions.cc:390
 msgid "Move Range End to Next Region Boundary"
-msgstr ""
+msgstr "移动范围终点到下一个区域边界"
 
 #: editor.cc:1856 editor_actions.cc:133 editor_actions.cc:325
 msgid "Separate"
@@ -2772,19 +2904,19 @@ msgstr "在区域列表转换至区域"
 
 #: editor.cc:1860 editor_markers.cc:970
 msgid "Select All in Range"
-msgstr "在范围选择所有"
+msgstr "在范围内全选"
 
 #: editor.cc:1863 editor_actions.cc:297
 msgid "Set Loop from Selection"
-msgstr ""
+msgstr "从已选择部分设置循环"
 
 #: editor.cc:1864 editor_actions.cc:298
 msgid "Set Punch from Selection"
-msgstr ""
+msgstr "从已选择部分设置切换"
 
 #: editor.cc:1865 editor_actions.cc:299
 msgid "Set Session Start/End from Selection"
-msgstr ""
+msgstr "从已选择部分设置会话起点/终点"
 
 #: editor.cc:1868
 msgid "Add Range Markers"
@@ -2808,23 +2940,23 @@ msgstr "合并范围"
 
 #: editor.cc:1877
 msgid "Consolidate Range With Processing"
-msgstr ""
+msgstr "合并范围并处理"
 
 #: editor.cc:1878
 msgid "Bounce Range to Region List"
-msgstr ""
+msgstr "欢跳弹奏范围到区域列表"
 
 #: editor.cc:1879
 msgid "Bounce Range to Region List With Processing"
-msgstr ""
+msgstr "欢跳弹奏范围到区域列表并处理"
 
 #: editor.cc:1880 editor_markers.cc:953
 msgid "Export Range..."
-msgstr "导出范围"
+msgstr "导出范围…"
 
 #: editor.cc:1882
 msgid "Export Video Range..."
-msgstr ""
+msgstr "导出视频范围…"
 
 #: editor.cc:1898 editor.cc:1979 editor_actions.cc:303
 msgid "Play From Edit Point"
@@ -2832,7 +2964,7 @@ msgstr "从编辑点播放"
 
 #: editor.cc:1899 editor.cc:1980
 msgid "Play From Start"
-msgstr "从开始播放"
+msgstr "从起点播放"
 
 #: editor.cc:1900
 msgid "Play Region"
@@ -2844,19 +2976,19 @@ msgstr "循环区域"
 
 #: editor.cc:1912 editor.cc:1989
 msgid "Select All in Track"
-msgstr "在音轨选择所有"
+msgstr "在音轨上全选所有"
 
 #: editor.cc:1913 editor.cc:1990 editor_actions.cc:194
 msgid "Select All Objects"
-msgstr ""
+msgstr "全选所有对象物体"
 
 #: editor.cc:1914 editor.cc:1991
 msgid "Invert Selection in Track"
-msgstr "在音轨反转选区"
+msgstr "在音轨反选"
 
 #: editor.cc:1915 editor.cc:1992 editor_actions.cc:197
 msgid "Invert Selection"
-msgstr "反转选区"
+msgstr "反选"
 
 #: editor.cc:1917
 msgid "Set Range to Loop Range"
@@ -2864,35 +2996,35 @@ msgstr "设置范围到循环范围"
 
 #: editor.cc:1918
 msgid "Set Range to Punch Range"
-msgstr "设置范围到Punch区间"
+msgstr "设置范围到切换区间"
 
 #: editor.cc:1920 editor.cc:1994 editor_actions.cc:199 editor_actions.cc:200
 msgid "Select All After Edit Point"
-msgstr "在编辑点后选择所有"
+msgstr "全选编辑点后所有"
 
 #: editor.cc:1921 editor.cc:1995 editor_actions.cc:201 editor_actions.cc:202
 msgid "Select All Before Edit Point"
-msgstr "在编辑点前选择所有"
+msgstr "全选编辑前所有"
 
 #: editor.cc:1922 editor.cc:1996
 msgid "Select All After Playhead"
-msgstr "播放头后选择所有"
+msgstr "全选指针后所有"
 
 #: editor.cc:1923 editor.cc:1997
 msgid "Select All Before Playhead"
-msgstr "播放头前选择所有"
+msgstr "全选指针前所有"
 
 #: editor.cc:1924
 msgid "Select All Between Playhead and Edit Point"
-msgstr "播放头和编辑点间选择所有"
+msgstr "全选指针和编辑点之间所有"
 
 #: editor.cc:1925
 msgid "Select All Within Playhead and Edit Point"
-msgstr "播放头和编辑点内选择所有"
+msgstr "全选指针和编辑点内部所有"
 
 #: editor.cc:1926
 msgid "Select Range Between Playhead and Edit Point"
-msgstr "播放头和编辑点间选择范围"
+msgstr "选择指针和编辑点之间范围"
 
 #: editor.cc:1928 editor.cc:1999 editor_actions.cc:131 editor_actions.cc:132
 msgid "Select"
@@ -2916,7 +3048,7 @@ msgstr "对齐"
 
 #: editor.cc:1943
 msgid "Align Relative"
-msgstr "相对对齐"
+msgstr "对齐相关"
 
 #: editor.cc:1950
 msgid "Insert Selected Region"
@@ -2928,28 +3060,27 @@ msgstr "插入已存在的媒体"
 
 #: editor.cc:1960 editor.cc:2016
 msgid "Nudge Entire Track Later"
-msgstr ""
+msgstr "向后微调整个音轨"
 
 #: editor.cc:1961 editor.cc:2017
 msgid "Nudge Track After Edit Point Later"
-msgstr ""
+msgstr "向后微调编辑点以后的音轨"
 
 #: editor.cc:1962 editor.cc:2018
 msgid "Nudge Entire Track Earlier"
-msgstr ""
+msgstr "向前微调整个音轨"
 
 #: editor.cc:1963 editor.cc:2019
 msgid "Nudge Track After Edit Point Earlier"
-msgstr ""
+msgstr "向前微调编辑点以后的音轨"
 
 #: editor.cc:1965 editor.cc:2021
 msgid "Nudge"
-msgstr ""
+msgstr "微调"
 
 #: editor.cc:2235
-msgid ""
-"Playhead position stored with a negative value - ignored (use zero instead)"
-msgstr ""
+msgid "Playhead position stored with a negative value - ignored (use zero instead)"
+msgstr "指针位置存储为一个负值——忽略(用零代替)"
 
 #: editor.cc:3006 editor.cc:3707 editor.cc:3778 midi_channel_selector.cc:157
 #: midi_channel_selector.cc:395 midi_channel_selector.cc:431
@@ -2958,49 +3089,51 @@ msgstr "所有"
 
 #: editor.cc:3210
 msgid "Smart Mode (add Range functions to Grab mode)"
-msgstr ""
+msgstr "智能模式(添加范围功能到抓取模式)"
 
 #: editor.cc:3211
 msgid "Grab Mode (select/move objects)"
-msgstr ""
+msgstr "抓取模式(选择/移动对象物体)"
 
 #: editor.cc:3212
 msgid "Cut Mode (split regions)"
-msgstr ""
+msgstr "切割模式(拆分区域)"
 
 #: editor.cc:3213
 msgid "Range Mode (select time ranges)"
-msgstr ""
+msgstr "范围模式(选择时间范围)"
 
 #: editor.cc:3214
 msgid "Draw Mode (draw and edit gain/notes/automation)"
-msgstr ""
+msgstr "描绘模式(描绘和编辑增益/音符/自动化)"
 
 #: editor.cc:3215
 msgid "Stretch Mode (time-stretch audio and midi regions, preserving pitch)"
-msgstr ""
+msgstr "延伸模式(时间延伸音频和MIDI区域,保持音高)"
 
 #: editor.cc:3216
 msgid "Audition Mode (listen to regions)"
-msgstr ""
+msgstr "监听模式(试听区域)"
 
 #: editor.cc:3217
 msgid "Internal Edit Mode (edit notes and gain curves inside regions)"
-msgstr ""
+msgstr "内部编辑模式(在区域内编辑音符和增益曲线)"
 
 #: editor.cc:3218
 msgid ""
 "Groups: click to (de)activate\n"
 "Context-click for other operations"
 msgstr ""
+"分组:点击(不)启用\n"
+"右键点击其它操作"
 
 #: editor.cc:3219
 msgid "Nudge Region/Selection Later"
-msgstr ""
+msgstr "向后微调区域/已选择部分"
 
 #: editor.cc:3220
 msgid "Nudge Region/Selection Earlier"
-msgstr ""
+msgstr "向前微调区域/已选择部分"
 
 #: editor.cc:3221 editor_actions.cc:262
 msgid "Zoom In"
@@ -3012,15 +3145,15 @@ msgstr "缩小"
 
 #: editor.cc:3223
 msgid "Zoom to Time Scale"
-msgstr ""
+msgstr "缩放至时间比例"
 
 #: editor.cc:3224 editor.cc:3729 editor_actions.cc:263
 msgid "Zoom to Session"
-msgstr "缩放到会话"
+msgstr "缩放至整个会话"
 
 #: editor.cc:3225
 msgid "Zoom focus"
-msgstr "缩放到焦点"
+msgstr "缩放焦点"
 
 #: editor.cc:3226
 msgid "Expand Tracks"
@@ -3032,15 +3165,15 @@ msgstr "收缩音轨"
 
 #: editor.cc:3228
 msgid "Number of visible tracks"
-msgstr ""
+msgstr "可见音轨数量"
 
 #: editor.cc:3229
 msgid "Snap/Grid Units"
-msgstr ""
+msgstr "吸附/网格单位"
 
 #: editor.cc:3230
 msgid "Snap/Grid Mode"
-msgstr ""
+msgstr "吸附/网格模式"
 
 #: editor.cc:3232
 msgid "Edit Mode"
@@ -3051,23 +3184,24 @@ msgid ""
 "Nudge Clock\n"
 "(controls distance used to nudge regions and selections)"
 msgstr ""
+"微调计时器\n"
+"(使用微调区域和已选择部分来控制距离)"
 
 #: editor.cc:3501 editor_actions.cc:313
 msgid "Command|Undo"
-msgstr ""
+msgstr "命令|撤销"
 
 #: editor.cc:3503
 msgid "Command|Undo (%1)"
-msgstr ""
+msgstr "命令|撤销(%1)"
 
-#: editor.cc:3510 editor_actions.cc:315 editor_actions.cc:316
-#: editor_actions.cc:317
+#: editor.cc:3510 editor_actions.cc:315 editor_actions.cc:316 editor_actions.cc:317
 msgid "Redo"
 msgstr "重做"
 
 #: editor.cc:3512
 msgid "Redo (%1)"
-msgstr "重做 (%1)"
+msgstr "重做(%1)"
 
 #: editor.cc:3531 editor.cc:3555 editor_actions.cc:110 editor_actions.cc:1846
 msgid "Duplicate"
@@ -3075,91 +3209,91 @@ msgstr "复制"
 
 #: editor.cc:3532
 msgid "Number of duplications:"
-msgstr "复制的数量:"
+msgstr "复制数量:"
 
 #: editor.cc:3706 route_group_dialog.cc:51 time_info_box.cc:67
 msgid "Selection"
-msgstr ""
+msgstr "已选择部分"
 
 #: editor.cc:3709
 msgid "Fit 1 track"
-msgstr ""
+msgstr "匹配音轨"
 
 #: editor.cc:3710
 msgid "Fit 2 tracks"
-msgstr ""
+msgstr "匹配2音轨"
 
 #: editor.cc:3711
 msgid "Fit 4 tracks"
-msgstr ""
+msgstr "匹配4音轨"
 
 #: editor.cc:3712
 msgid "Fit 8 tracks"
-msgstr ""
+msgstr "匹配8音轨"
 
 #: editor.cc:3713
 msgid "Fit 16 tracks"
-msgstr ""
+msgstr "匹配16音轨"
 
 #: editor.cc:3714
 msgid "Fit 24 tracks"
-msgstr ""
+msgstr "匹配24音轨"
 
 #: editor.cc:3715
 msgid "Fit 32 tracks"
-msgstr ""
+msgstr "匹配32音轨"
 
 #: editor.cc:3716
 msgid "Fit 48 tracks"
-msgstr ""
+msgstr "匹配48音轨"
 
 #: editor.cc:3717
 msgid "Fit All tracks"
-msgstr ""
+msgstr "匹配所有音轨"
 
 #: editor.cc:3718
 msgid "Fit Selection"
-msgstr ""
+msgstr "匹配已选择部分"
 
 #: editor.cc:3720
 msgid "Zoom to 10 ms"
-msgstr ""
+msgstr "缩放至 10 毫秒"
 
 #: editor.cc:3721
 msgid "Zoom to 100 ms"
-msgstr ""
+msgstr "缩放至 100 毫秒"
 
 #: editor.cc:3722
 msgid "Zoom to 1 sec"
-msgstr ""
+msgstr "缩放至 1 秒"
 
 #: editor.cc:3723
 msgid "Zoom to 10 sec"
-msgstr ""
+msgstr "缩放至 10 秒"
 
 #: editor.cc:3724
 msgid "Zoom to 1 min"
-msgstr ""
+msgstr "缩放至 1 分钟"
 
 #: editor.cc:3725
 msgid "Zoom to 10 min"
-msgstr ""
+msgstr "缩放至 10 分钟"
 
 #: editor.cc:3726
 msgid "Zoom to 1 hour"
-msgstr ""
+msgstr "缩放至 1 小时"
 
 #: editor.cc:3727
 msgid "Zoom to 8 hours"
-msgstr ""
+msgstr "缩放至 8 小时"
 
 #: editor.cc:3728
 msgid "Zoom to 24 hours"
-msgstr ""
+msgstr "缩放至 24 小时"
 
 #: editor.cc:3730
 msgid "Zoom to Range/Region Selection"
-msgstr ""
+msgstr "缩放至范围/区域已选择部分"
 
 #: editor.cc:3800
 msgid "*"
@@ -3167,7 +3301,7 @@ msgstr ""
 
 #: editor.cc:4120
 msgid "Playlist Deletion"
-msgstr "播放列表删除"
+msgstr "播放列表删除部分"
 
 #: editor.cc:4121
 msgid ""
@@ -3175,6 +3309,9 @@ msgid ""
 "If it is kept, its audio files will not be cleaned.\n"
 "If it is deleted, audio files used by it alone will be cleaned."
 msgstr ""
+"播放列表 %1 当前未被使用。\n"
+"如果保留它,它的音频文件将不会被清除。\n"
+"如果删除它,它单独使用过的音频文件将会被清除。"
 
 #: editor.cc:4131
 msgid "Delete Playlist"
@@ -3182,7 +3319,7 @@ msgstr "删除播放列表"
 
 #: editor.cc:4132
 msgid "Keep Playlist"
-msgstr "保持播放列表"
+msgstr "保留播放列表"
 
 #: editor.cc:4133 editor_audio_import.cc:594 editor_ops.cc:6174
 #: engine_dialog.cc:2083 sfdb_freesound_mootcher.cc:69 processor_box.cc:2219
@@ -3192,7 +3329,7 @@ msgstr "取消"
 
 #: editor.cc:4275
 msgid "new playlists"
-msgstr "新播放列表"
+msgstr "新建播放列表"
 
 #: editor.cc:4291
 msgid "copy playlists"
@@ -3204,28 +3341,28 @@ msgstr "清除播放列表"
 
 #: editor.cc:5046
 msgid "Please wait while %1 loads visual data."
-msgstr ""
+msgstr "请等候 %1 载入可见数据。"
 
 #: editor.cc:5901 editor.cc:5932 editor_markers.cc:985 panner_ui.cc:410
 #: processor_box.cc:2482
 msgid "Edit..."
-msgstr "编辑..."
+msgstr "编辑…"
 
 #: editor.cc:5934 editor_actions.cc:1941
 msgid "Legatize"
-msgstr ""
+msgstr " 合法化"
 
 #: editor.cc:5936 editor_actions.cc:1940
 msgid "Quantize..."
-msgstr ""
+msgstr "量化…"
 
 #: editor.cc:5938 editor_actions.cc:1943
 msgid "Remove Overlap"
-msgstr ""
+msgstr "移除重叠"
 
 #: editor.cc:5940 editor_actions.cc:1942
 msgid "Transform..."
-msgstr ""
+msgstr "变换…"
 
 #: editor_actions.cc:92
 msgid "Autoconnect"
@@ -3233,11 +3370,11 @@ msgstr "自动连接"
 
 #: editor_actions.cc:93
 msgid "Crossfades"
-msgstr "淡入淡出"
+msgstr "淡入淡出(交叉淡化)"
 
 #: editor_actions.cc:95
 msgid "Move Selected Marker"
-msgstr "移动选择的标记"
+msgstr "移动已选择的标记"
 
 #: editor_actions.cc:96
 msgid "Select Range Operations"
@@ -3253,11 +3390,11 @@ msgstr "编辑点"
 
 #: editor_actions.cc:99
 msgid "Fade"
-msgstr ""
+msgstr "淡化"
 
 #: editor_actions.cc:100
 msgid "Latch"
-msgstr ""
+msgstr "短锁"
 
 #: editor_actions.cc:101 editor_regions.cc:112 region_editor.cc:46
 msgid "Region"
@@ -3265,7 +3402,7 @@ msgstr "区域"
 
 #: editor_actions.cc:102
 msgid "Layering"
-msgstr ""
+msgstr "分层"
 
 #: editor_actions.cc:103 editor_regions.cc:113 stereo_panner_editor.cc:44
 msgid "Position"
@@ -3274,7 +3411,7 @@ msgstr "位置"
 #: editor_actions.cc:105 gain_meter.cc:156 gain_meter.cc:825 panner_ui.cc:178
 #: panner_ui.cc:635
 msgid "Trim"
-msgstr ""
+msgstr "修剪"
 
 #: editor_actions.cc:106 editor_actions.cc:126 route_group_dialog.cc:46
 msgid "Gain"
@@ -3287,15 +3424,15 @@ msgstr "范围"
 #: editor_actions.cc:108 editor_actions.cc:1842 session_option_editor.cc:135
 #: session_option_editor.cc:144 session_option_editor.cc:151
 msgid "Fades"
-msgstr ""
+msgstr "淡化"
 
 #: editor_actions.cc:111
 msgid "Link"
-msgstr ""
+msgstr "链接"
 
 #: editor_actions.cc:112 editor_actions.cc:145
 msgid "Zoom Focus"
-msgstr ""
+msgstr "缩放焦点"
 
 #: editor_actions.cc:113
 msgid "Locate to Markers"
@@ -3303,11 +3440,11 @@ msgstr "定位到标记"
 
 #: editor_actions.cc:115
 msgid "Meter falloff"
-msgstr "标尺衰减"
+msgstr "节拍衰减"
 
 #: editor_actions.cc:116
 msgid "Meter hold"
-msgstr "标尺保持"
+msgstr "节拍保持"
 
 #: editor_actions.cc:117 session_option_editor.cc:321
 msgid "MIDI Options"
@@ -3315,7 +3452,7 @@ msgstr "MIDI选项"
 
 #: editor_actions.cc:118
 msgid "Misc Options"
-msgstr "其他选项"
+msgstr "其它选项"
 
 #: editor_actions.cc:119 rc_option_editor.cc:1809 route_group_dialog.cc:54
 #: session_option_editor.cc:243 session_option_editor.cc:250
@@ -3328,11 +3465,11 @@ msgstr "启用标记"
 
 #: editor_actions.cc:123
 msgid "Primary Clock"
-msgstr "主时钟"
+msgstr "主计时器"
 
 #: editor_actions.cc:124
 msgid "Pullup / Pulldown"
-msgstr "上拉/下拉"
+msgstr "向上拖动/向下拖动"
 
 #: editor_actions.cc:125
 msgid "Region operations"
@@ -3344,7 +3481,7 @@ msgstr "标尺"
 
 #: editor_actions.cc:128
 msgid "Views"
-msgstr ""
+msgstr "视图"
 
 #: editor_actions.cc:129
 msgid "Scroll"
@@ -3352,7 +3489,7 @@ msgstr "滚动"
 
 #: editor_actions.cc:130
 msgid "Secondary Clock"
-msgstr "第二时钟"
+msgstr "第二计时器"
 
 #: editor_actions.cc:137
 msgid "Subframes"
@@ -3376,7 +3513,7 @@ msgstr "视图"
 
 #: editor_actions.cc:146
 msgid "Zoom"
-msgstr "放大"
+msgstr "缩放"
 
 #: editor_actions.cc:152
 msgid "Break drag or deselect all"
@@ -3392,27 +3529,27 @@ msgstr "显示编辑器列表"
 
 #: editor_actions.cc:162
 msgid "Playhead to Next Region Boundary"
-msgstr "播放头到下一个区域边界"
+msgstr "指针到下一个区域边界"
 
 #: editor_actions.cc:163
 msgid "Playhead to Next Region Boundary (No Track Selection)"
-msgstr "播放头到下一个区域边界 (没有音轨选区)"
+msgstr "指针到下一个区域边界(无音轨已选择部分)"
 
 #: editor_actions.cc:164
 msgid "Playhead to Previous Region Boundary"
-msgstr "播放头到上一个区域边界"
+msgstr "指针到上一个区域边界"
 
 #: editor_actions.cc:165
 msgid "Playhead to Previous Region Boundary (No Track Selection)"
-msgstr "播放头到上一个区域边界 (没有音轨选区)"
+msgstr "指针到上一个区域边界(无音轨已选择部分)"
 
 #: editor_actions.cc:167
 msgid "Playhead to Next Region Start"
-msgstr "播放头到下一个区域开始"
+msgstr "指针到下一个区域起点"
 
 #: editor_actions.cc:168
 msgid "Playhead to Next Region End"
-msgstr "播放头到下一个区域结束"
+msgstr "指针到下一个区域终点"
 
 #: editor_actions.cc:169
 msgid "Playhead to Next Region Sync"
@@ -3420,15 +3557,15 @@ msgstr "播放头到下一个区域同步"
 
 #: editor_actions.cc:171
 msgid "Playhead to Previous Region Start"
-msgstr "播放头到上一个区域开始"
+msgstr "指针到上一个区域起点"
 
 #: editor_actions.cc:172
 msgid "Playhead to Previous Region End"
-msgstr "播放头到上一个区域结束"
+msgstr "指针到上一个区域终点"
 
 #: editor_actions.cc:173
 msgid "Playhead to Previous Region Sync"
-msgstr "播放头到上一个区域同步"
+msgstr "指针到下一个区域同步"
 
 #: editor_actions.cc:175
 msgid "To Next Region Boundary"
@@ -3436,7 +3573,7 @@ msgstr "到下一个区域边界"
 
 #: editor_actions.cc:176
 msgid "To Next Region Boundary (No Track Selection)"
-msgstr "到下一个区域边界 (没有音轨选区)"
+msgstr "到下一个区域边界(无音轨已选择部分)"
 
 #: editor_actions.cc:177
 msgid "To Previous Region Boundary"
@@ -3444,15 +3581,15 @@ msgstr "到上一个区域边界"
 
 #: editor_actions.cc:178
 msgid "To Previous Region Boundary (No Track Selection)"
-msgstr ""
+msgstr "到上一个区域边界(无音轨已选择部分)"
 
 #: editor_actions.cc:180
 msgid "To Next Region Start"
-msgstr "到下一个区域开始"
+msgstr "到下一个区域起点"
 
 #: editor_actions.cc:181
 msgid "To Next Region End"
-msgstr "到下一个区域结束"
+msgstr "到下一个区域终点"
 
 #: editor_actions.cc:182
 msgid "To Next Region Sync"
@@ -3460,11 +3597,11 @@ msgstr "到下一个区域同步"
 
 #: editor_actions.cc:184
 msgid "To Previous Region Start"
-msgstr "到上一个区域开始"
+msgstr "到上一个区域起点"
 
 #: editor_actions.cc:185
 msgid "To Previous Region End"
-msgstr "到上一个区域结束"
+msgstr "到上一个区域终点"
 
 #: editor_actions.cc:186
 msgid "To Previous Region Sync"
@@ -3472,23 +3609,23 @@ msgstr "到上一个区域同步"
 
 #: editor_actions.cc:188
 msgid "To Range Start"
-msgstr "到范围开始"
+msgstr "到范围起点"
 
 #: editor_actions.cc:189
 msgid "To Range End"
-msgstr "到范围结束"
+msgstr "到范围终点"
 
 #: editor_actions.cc:191
 msgid "Playhead to Range Start"
-msgstr "播放头到范围开始"
+msgstr "指针到范围起点"
 
 #: editor_actions.cc:192
 msgid "Playhead to Range End"
-msgstr "播放头到范围结束"
+msgstr "指针到范围终点"
 
 #: editor_actions.cc:195
 msgid "Select All Tracks"
-msgstr ""
+msgstr "选择所有音轨"
 
 #: editor_actions.cc:196 export_timespan_selector.cc:61 processor_box.cc:2468
 msgid "Deselect All"
@@ -3508,11 +3645,11 @@ msgstr "选择编辑范围"
 
 #: editor_actions.cc:209
 msgid "Select All in Punch Range"
-msgstr "在Punch范围选择所有"
+msgstr "选择所有在切换范围内的"
 
 #: editor_actions.cc:210
 msgid "Select All in Loop Range"
-msgstr "在循环范围内选择所有"
+msgstr "选择所有在循环范围内的"
 
 #: editor_actions.cc:212
 msgid "Select Next Track or Bus"
@@ -3524,11 +3661,11 @@ msgstr "选择上一个音轨或总线"
 
 #: editor_actions.cc:215
 msgid "Toggle Record Enable"
-msgstr "切换录音启用"
+msgstr "切换录制启用"
 
 #: editor_actions.cc:217
 msgid "Toggle Solo"
-msgstr "切换Solo"
+msgstr "切独奏"
 
 #: editor_actions.cc:219
 msgid "Toggle Mute"
@@ -3536,7 +3673,7 @@ msgstr "切换静音"
 
 #: editor_actions.cc:221
 msgid "Toggle Solo Isolate"
-msgstr "切换Solo隔离"
+msgstr "切换独奏隔离"
 
 #: editor_actions.cc:226
 msgid "Save View %1"
@@ -3552,51 +3689,51 @@ msgstr "定位到标记 %1"
 
 #: editor_actions.cc:242 editor_actions.cc:243
 msgid "Jump to Next Mark"
-msgstr ""
+msgstr "跳到下一个标记"
 
 #: editor_actions.cc:244 editor_actions.cc:245
 msgid "Jump to Previous Mark"
-msgstr ""
+msgstr "跳到上一个标记"
 
 #: editor_actions.cc:247 editor_actions.cc:248
 msgid "Add Mark from Playhead"
-msgstr "从播放头添加编辑"
+msgstr "从指针起添加标记"
 
 #: editor_actions.cc:250 editor_actions.cc:251
 msgid "Remove Mark at Playhead"
-msgstr ""
+msgstr "移除指针处的标记"
 
 #: editor_actions.cc:253
 msgid "Nudge Next Later"
-msgstr ""
+msgstr "向后微调下一个"
 
 #: editor_actions.cc:254
 msgid "Nudge Next Earlier"
-msgstr ""
+msgstr "向前微调下一个"
 
 #: editor_actions.cc:256
 msgid "Nudge Playhead Forward"
-msgstr ""
+msgstr "微调指针前进"
 
 #: editor_actions.cc:257
 msgid "Nudge Playhead Backward"
-msgstr ""
+msgstr "微调指针后退"
 
 #: editor_actions.cc:258
 msgid "Playhead To Next Grid"
-msgstr ""
+msgstr "指针转到下一个网格"
 
 #: editor_actions.cc:259
 msgid "Playhead To Previous Grid"
-msgstr ""
+msgstr "指针转到上一个网格"
 
 #: editor_actions.cc:264
 msgid "Zoom to Selection"
-msgstr ""
+msgstr "缩放至已选择部分"
 
 #: editor_actions.cc:265
 msgid "Toggle Zoom State"
-msgstr ""
+msgstr "切换缩放状态"
 
 #: editor_actions.cc:267
 msgid "Expand Track Height"
@@ -3608,11 +3745,11 @@ msgstr "收缩扩展音轨高度"
 
 #: editor_actions.cc:270
 msgid "Move Selected Tracks Up"
-msgstr ""
+msgstr "向上移动已选中音轨"
 
 #: editor_actions.cc:272
 msgid "Move Selected Tracks Down"
-msgstr ""
+msgstr "向下移动已选中音轨"
 
 #: editor_actions.cc:275
 msgid "Scroll Tracks Up"
@@ -3624,51 +3761,51 @@ msgstr "向下滚动音轨"
 
 #: editor_actions.cc:279
 msgid "Step Tracks Up"
-msgstr ""
+msgstr "向上步进音轨"
 
 #: editor_actions.cc:281
 msgid "Step Tracks Down"
-msgstr ""
+msgstr "向下步进音轨"
 
 #: editor_actions.cc:284
 msgid "Scroll Backward"
-msgstr "向后滚动音轨"
+msgstr "向后滚动"
 
 #: editor_actions.cc:285
 msgid "Scroll Forward"
-msgstr "向前滚动音轨"
+msgstr "向前滚动"
 
 #: editor_actions.cc:286
 msgid "Center Playhead"
-msgstr ""
+msgstr "指针置中"
 
 #: editor_actions.cc:287
 msgid "Center Edit Point"
-msgstr ""
+msgstr "编辑点置中"
 
 #: editor_actions.cc:289
 msgid "Playhead Forward"
-msgstr "播放头前进"
+msgstr "指针前进"
 
 #: editor_actions.cc:290
 msgid "Playhead Backward"
-msgstr "播放头后退"
+msgstr "指针后退"
 
 #: editor_actions.cc:292
 msgid "Playhead to Active Mark"
-msgstr ""
+msgstr "指针跳转到激活的标记处"
 
 #: editor_actions.cc:293
 msgid "Active Mark to Playhead"
-msgstr ""
+msgstr "激活的标记跳转到指针处"
 
 #: editor_actions.cc:295
 msgid "Use Skip Ranges"
-msgstr ""
+msgstr "使用不连续的范围"
 
 #: editor_actions.cc:302
 msgid "Play Selected Regions"
-msgstr "播放被选区域"
+msgstr "播放已选中的区域"
 
 #: editor_actions.cc:304
 msgid "Play from Edit Point and Return"
@@ -3680,19 +3817,19 @@ msgstr "播放编辑范围"
 
 #: editor_actions.cc:308
 msgid "Playhead to Mouse"
-msgstr "播放头移至鼠标指针位置"
+msgstr "指针跳转到鼠标处"
 
 #: editor_actions.cc:309
 msgid "Active Marker to Mouse"
-msgstr ""
+msgstr "激活的标记跳转到鼠标处"
 
 #: editor_actions.cc:319
 msgid "Undo Selection Change"
-msgstr ""
+msgstr "撤销已选中部分的改动"
 
 #: editor_actions.cc:320
 msgid "Redo Selection Change"
-msgstr ""
+msgstr "重做已选中部分的改动"
 
 #: editor_actions.cc:322
 msgid "Export Audio"
@@ -3704,19 +3841,19 @@ msgstr "导出范围"
 
 #: editor_actions.cc:328
 msgid "Separate Using Punch Range"
-msgstr "用Punch范围分离"
+msgstr "使用切换范围分离"
 
 #: editor_actions.cc:331
 msgid "Separate Using Loop Range"
-msgstr ""
+msgstr "使用循环范围分离"
 
 #: editor_actions.cc:334 editor_actions.cc:356
 msgid "Crop"
-msgstr ""
+msgstr "剪裁"
 
 #: editor_actions.cc:344
 msgid "Fade Range Selection"
-msgstr ""
+msgstr "淡化范围已选中部分"
 
 #: editor_actions.cc:346
 msgid "Set Tempo from Edit Range = Bar"
@@ -3724,43 +3861,43 @@ msgstr "从编辑范围设置节奏 = 小节"
 
 #: editor_actions.cc:348
 msgid "Log"
-msgstr ""
+msgstr "日志"
 
 #: editor_actions.cc:351 editor_actions.cc:353
 msgid "Move to Next Transient"
-msgstr ""
+msgstr "移动到下一个过渡"
 
 #: editor_actions.cc:352 editor_actions.cc:354
 msgid "Move to Previous Transient"
-msgstr ""
+msgstr "移动到上一个过渡"
 
 #: editor_actions.cc:358 editor_actions.cc:361
 msgid "Start Range"
-msgstr ""
+msgstr "开始范围"
 
 #: editor_actions.cc:359 editor_actions.cc:362
 msgid "Finish Range"
-msgstr ""
+msgstr "结束范围"
 
 #: editor_actions.cc:394
 msgid "Follow Playhead"
-msgstr ""
+msgstr "跟随指针"
 
 #: editor_actions.cc:395
 msgid "Remove Last Capture"
-msgstr ""
+msgstr "移除已捕获内容"
 
 #: editor_actions.cc:397
 msgid "Stationary Playhead"
-msgstr ""
+msgstr "固定指针"
 
 #: editor_actions.cc:399 insert_time_dialog.cc:32
 msgid "Insert Time"
-msgstr ""
+msgstr "插入时间"
 
 #: editor_actions.cc:402
 msgid "Toggle Active"
-msgstr ""
+msgstr "切换激活"
 
 #: editor_actions.cc:407 editor_actions.cc:1768 editor_markers.cc:921
 #: editor_markers.cc:986 editor_snapshots.cc:122 mixer_strip.cc:1543
@@ -3770,7 +3907,7 @@ msgstr "移除"
 
 #: editor_actions.cc:411
 msgid "Fit Selection (Vertical)"
-msgstr ""
+msgstr " 匹配已选择部分(垂直)"
 
 #: editor_actions.cc:413 time_axis_view.cc:1371
 msgid "Largest"
@@ -3790,55 +3927,55 @@ msgstr "小"
 
 #: editor_actions.cc:429
 msgid "Sound Selected MIDI Notes"
-msgstr ""
+msgstr "声音已选择部分MIDI音符"
 
 #: editor_actions.cc:434
 msgid "Zoom Focus Left"
-msgstr ""
+msgstr "以左侧为焦点缩放"
 
 #: editor_actions.cc:435
 msgid "Zoom Focus Right"
-msgstr ""
+msgstr "以右侧为焦点缩放"
 
 #: editor_actions.cc:436
 msgid "Zoom Focus Center"
-msgstr ""
+msgstr "以中央为焦点缩放"
 
 #: editor_actions.cc:437
 msgid "Zoom Focus Playhead"
-msgstr ""
+msgstr "以指针为焦点缩放"
 
 #: editor_actions.cc:438
 msgid "Zoom Focus Mouse"
-msgstr ""
+msgstr "以鼠标为焦点缩放"
 
 #: editor_actions.cc:439
 msgid "Zoom Focus Edit Point"
-msgstr ""
+msgstr "以编辑点为焦点缩放"
 
 #: editor_actions.cc:441
 msgid "Next Zoom Focus"
-msgstr ""
+msgstr "下一个缩放焦点"
 
 #: editor_actions.cc:447
 msgid "Smart Object Mode"
-msgstr ""
+msgstr "智能对象物体模式"
 
 #: editor_actions.cc:450
 msgid "Smart"
-msgstr ""
+msgstr "智能"
 
 #: editor_actions.cc:453
 msgid "Object Tool"
-msgstr ""
+msgstr "对象物体工具"
 
 #: editor_actions.cc:458
 msgid "Range Tool"
-msgstr ""
+msgstr "范围工具"
 
 #: editor_actions.cc:463
 msgid "Note Drawing Tool"
-msgstr ""
+msgstr "音符描绘工具"
 
 #: editor_actions.cc:468
 msgid "Audition Tool"
@@ -3846,19 +3983,19 @@ msgstr "监听工具"
 
 #: editor_actions.cc:473
 msgid "Time FX Tool"
-msgstr ""
+msgstr "时间特效工具"
 
 #: editor_actions.cc:478
 msgid "Content Tool"
-msgstr ""
+msgstr "内容工具"
 
 #: editor_actions.cc:484
 msgid "Cut Tool"
-msgstr ""
+msgstr " 切割工具"
 
 #: editor_actions.cc:490
 msgid "Step Mouse Mode"
-msgstr ""
+msgstr "步进鼠标模式"
 
 #: editor_actions.cc:497
 msgid "Change Edit Point"
@@ -3866,159 +4003,159 @@ msgstr "改变编辑点"
 
 #: editor_actions.cc:498
 msgid "Change Edit Point Including Marker"
-msgstr ""
+msgstr "改变编辑点包括标记"
 
 #: editor_actions.cc:504
 msgid "Cycle Edit Mode"
-msgstr ""
+msgstr "循环编辑模式"
 
 #: editor_actions.cc:506
 msgid "Snap to"
-msgstr ""
+msgstr "吸附到"
 
 #: editor_actions.cc:507
 msgid "Snap Mode"
-msgstr ""
+msgstr "吸附模式"
 
 #: editor_actions.cc:514
 msgid "Next Snap Mode"
-msgstr ""
+msgstr "下一个吸附模式"
 
 #: editor_actions.cc:515
 msgid "Next Snap Choice"
-msgstr ""
+msgstr "下一个吸附选择"
 
 #: editor_actions.cc:516
 msgid "Next Musical Snap Choice"
-msgstr ""
+msgstr "下一个配乐的吸附选择"
 
 #: editor_actions.cc:517
 msgid "Previous Snap Choice"
-msgstr ""
+msgstr "上一个吸附选择"
 
 #: editor_actions.cc:518
 msgid "Previous Musical Snap Choice"
-msgstr ""
+msgstr "上一个配乐的吸附选择"
 
 #: editor_actions.cc:523
 msgid "Snap to CD Frame"
-msgstr "对齐到CD框架"
+msgstr "吸附到CD框架"
 
 #: editor_actions.cc:524
 msgid "Snap to Timecode Frame"
-msgstr "对齐到时间码框架"
+msgstr "吸附到时间码框架"
 
 #: editor_actions.cc:525
 msgid "Snap to Timecode Seconds"
-msgstr "对齐到时间码秒"
+msgstr "吸附到时间码秒"
 
 #: editor_actions.cc:526
 msgid "Snap to Timecode Minutes"
-msgstr "对齐到时间码分"
+msgstr "吸附到时间码分"
 
 #: editor_actions.cc:527
 msgid "Snap to Seconds"
-msgstr "对齐到秒"
+msgstr "吸附到秒"
 
 #: editor_actions.cc:528
 msgid "Snap to Minutes"
-msgstr "对齐到分"
+msgstr "吸附到分"
 
 #: editor_actions.cc:530
 msgid "Snap to One Twenty Eighths"
-msgstr ""
+msgstr "吸附到一百二十八分之一"
 
 #: editor_actions.cc:531
 msgid "Snap to Sixty Fourths"
-msgstr ""
+msgstr "吸附到六十四分之一"
 
 #: editor_actions.cc:532
 msgid "Snap to Thirty Seconds"
-msgstr "对齐到30秒"
+msgstr "吸附到三十二分之一"
 
 #: editor_actions.cc:533
 msgid "Snap to Twenty Eighths"
-msgstr "对齐到第28"
+msgstr "吸附到二十八分之一"
 
 #: editor_actions.cc:534
 msgid "Snap to Twenty Fourths"
-msgstr "对齐到第24"
+msgstr "吸附到二十四分之一"
 
 #: editor_actions.cc:535
 msgid "Snap to Twentieths"
-msgstr "对齐到第20"
+msgstr "吸附到二十分之一"
 
 #: editor_actions.cc:536
 msgid "Snap to Sixteenths"
-msgstr "对齐到第16"
+msgstr "吸附到十六分之一"
 
 #: editor_actions.cc:537
 msgid "Snap to Fourteenths"
-msgstr "对齐到第14"
+msgstr "吸附到十四分之一"
 
 #: editor_actions.cc:538
 msgid "Snap to Twelfths"
-msgstr "对齐到第12"
+msgstr "吸附到十二分之一"
 
 #: editor_actions.cc:539
 msgid "Snap to Tenths"
-msgstr "对齐到第10"
+msgstr "吸附到十分之一"
 
 #: editor_actions.cc:540
 msgid "Snap to Eighths"
-msgstr "对齐到第8"
+msgstr "吸附到八分之一"
 
 #: editor_actions.cc:541
 msgid "Snap to Sevenths"
-msgstr "对齐到第7"
+msgstr "吸附到七分之一"
 
 #: editor_actions.cc:542
 msgid "Snap to Sixths"
-msgstr "对齐到第6"
+msgstr "吸附到六分之一"
 
 #: editor_actions.cc:543
 msgid "Snap to Fifths"
-msgstr "对齐到第5"
+msgstr "吸附到五分之一"
 
 #: editor_actions.cc:544
 msgid "Snap to Quarters"
-msgstr "对齐到1/4"
+msgstr "吸附到四分之一"
 
 #: editor_actions.cc:545
 msgid "Snap to Thirds"
-msgstr "对齐到1/3"
+msgstr "吸附到三分之一"
 
 #: editor_actions.cc:546
 msgid "Snap to Halves"
-msgstr "对齐到1/2"
+msgstr "吸附到二分之一"
 
 #: editor_actions.cc:548
 msgid "Snap to Beat"
-msgstr "对齐到节拍"
+msgstr "吸附到拍子"
 
 #: editor_actions.cc:549
 msgid "Snap to Bar"
-msgstr "对齐到小节"
+msgstr "吸附到小节"
 
 #: editor_actions.cc:550
 msgid "Snap to Mark"
-msgstr "对齐到标记"
+msgstr "吸附到标记"
 
 #: editor_actions.cc:551
 msgid "Snap to Region Start"
-msgstr "对齐到区域开始"
+msgstr "吸附到区域起点"
 
 #: editor_actions.cc:552
 msgid "Snap to Region End"
-msgstr "对齐到区域结束"
+msgstr "吸附到区域终点"
 
 #: editor_actions.cc:553
 msgid "Snap to Region Sync"
-msgstr "对齐到区域同步"
+msgstr "吸附到区域同步"
 
 #: editor_actions.cc:554
 msgid "Snap to Region Boundary"
-msgstr "对齐到区域边界"
+msgstr "吸附到区域边界"
 
 #: editor_actions.cc:556
 msgid "Show Marker Lines"
@@ -4026,47 +4163,47 @@ msgstr "显示标记线条"
 
 #: editor_actions.cc:566
 msgid "Loop/Punch"
-msgstr "循环/Punch"
+msgstr "循环/切换"
 
 #: editor_actions.cc:570
 msgid "Min:Sec"
-msgstr "分:秒"
+msgstr "分:秒"
 
 #: editor_actions.cc:572 editor_actions.cc:575 editor_rulers.cc:271
 msgid "Video Monitor"
-msgstr ""
+msgstr "视频监控"
 
 #: editor_actions.cc:574 rc_option_editor.cc:2260
 msgid "Video"
-msgstr ""
+msgstr "视频"
 
 #: editor_actions.cc:577
 msgid "Always on Top"
-msgstr ""
+msgstr "总是置顶"
 
 #: editor_actions.cc:579
 msgid "Frame number"
-msgstr ""
+msgstr "帧号码"
 
 #: editor_actions.cc:580
 msgid "Timecode Background"
-msgstr ""
+msgstr "时间码背景"
 
 #: editor_actions.cc:581
 msgid "Fullscreen"
-msgstr ""
+msgstr "全屏"
 
 #: editor_actions.cc:582
 msgid "Letterbox"
-msgstr ""
+msgstr "宽银幕式"
 
 #: editor_actions.cc:583
 msgid "Original Size"
-msgstr ""
+msgstr "原始尺寸"
 
 #: editor_actions.cc:640
 msgid "Sort"
-msgstr "整理"
+msgstr "排序"
 
 #: editor_actions.cc:651 editor_routes.cc:476 mixer_ui.cc:1196
 msgid "Show All"
@@ -4078,65 +4215,65 @@ msgstr "显示自动的区域"
 
 #: editor_actions.cc:654
 msgid "Ascending"
-msgstr "上升"
+msgstr "升序"
 
 #: editor_actions.cc:656
 msgid "Descending"
-msgstr "下降"
+msgstr "降序"
 
 #: editor_actions.cc:659
 msgid "By Region Name"
-msgstr "由区域名"
+msgstr "以区域名称"
 
 #: editor_actions.cc:661
 msgid "By Region Length"
-msgstr "由区域长度"
+msgstr "以区域长度"
 
 #: editor_actions.cc:663
 msgid "By Region Position"
-msgstr "由区域位置"
+msgstr "以区域位置"
 
 #: editor_actions.cc:665
 msgid "By Region Timestamp"
-msgstr "由区域时间戳"
+msgstr "以区域时间戳"
 
 #: editor_actions.cc:667
 msgid "By Region Start in File"
-msgstr "由文件的区域开始"
+msgstr "以文件内的区域起点"
 
 #: editor_actions.cc:669
 msgid "By Region End in File"
-msgstr "由文件的区域结束"
+msgstr "以文件内的区域终点"
 
 #: editor_actions.cc:671
 msgid "By Source File Name"
-msgstr "由源文件名"
+msgstr "以源文件名称"
 
 #: editor_actions.cc:673
 msgid "By Source File Length"
-msgstr "由源文件长度"
+msgstr "以源文件长度"
 
 #: editor_actions.cc:675
 msgid "By Source File Creation Date"
-msgstr "由源文件创建日期"
+msgstr "以源文件创建日期"
 
 #: editor_actions.cc:677
 msgid "By Source Filesystem"
-msgstr "由源文件系统"
+msgstr "以源文件系统"
 
 #: editor_actions.cc:680
 msgid "Remove Unused"
-msgstr ""
+msgstr "移除未使用的"
 
-#: editor_actions.cc:684 editor_audio_import.cc:282
-#: session_import_dialog.cc:75 session_import_dialog.cc:95
-#: session_metadata_dialog.cc:418 editor_videotimeline.cc:91
+#: editor_actions.cc:684 editor_audio_import.cc:282 session_import_dialog.cc:75
+#: session_import_dialog.cc:95 session_metadata_dialog.cc:418
+#: editor_videotimeline.cc:91
 msgid "Import"
 msgstr "导入"
 
 #: editor_actions.cc:687
 msgid "Import to Region List..."
-msgstr "导入到区域列表..."
+msgstr "导入到区域列表…"
 
 #: editor_actions.cc:690 session_import_dialog.cc:44
 msgid "Import From Session"
@@ -4144,69 +4281,69 @@ msgstr "从会话导入"
 
 #: editor_actions.cc:694
 msgid "Bring all media into session folder"
-msgstr ""
+msgstr "将所有媒体引入会话文件夹"
 
 #: editor_actions.cc:697
 msgid "Show Summary"
-msgstr "显示总结"
+msgstr "显示摘要"
 
 #: editor_actions.cc:699
 msgid "Show Group Tabs"
-msgstr "显示群组标签"
+msgstr "显示群组标签页"
 
 #: editor_actions.cc:701
 msgid "Show Measure Lines"
-msgstr ""
+msgstr "显示测量线"
 
 #: editor_actions.cc:705
 msgid "Show Logo"
-msgstr "显示Logo"
+msgstr "显示商标"
 
 #: editor_actions.cc:709
 msgid "Toggle MIDI Input Active for Editor-Selected Tracks/Busses"
-msgstr ""
+msgstr "切换是否为编辑器中已选择的音轨/总线激活MIDI输入"
 
 #: editor_actions.cc:732
 msgid "Loaded editor bindings from %1"
-msgstr ""
+msgstr "已从 %1 载入编辑器绑定"
 
 #: editor_actions.cc:734
 msgid "Could not find editor.bindings in search path %1"
-msgstr ""
+msgstr "在搜索路径 %1 找不到编辑器绑定"
 
 #: editor_actions.cc:1078 editor_actions.cc:1474 editor_actions.cc:1485
 #: editor_actions.cc:1538 editor_actions.cc:1549 editor_actions.cc:1596
 #: editor_actions.cc:1606 editor_regions.cc:1563
 msgid "programming error: %1: %2"
-msgstr "程序错误: %1: %2"
+msgstr "程序错误: %1: %2"
 
 #: editor_actions.cc:1774
 msgid "Raise"
-msgstr "上升"
+msgstr "提升"
 
 #: editor_actions.cc:1777
 msgid "Raise to Top"
-msgstr "上升到顶"
+msgstr "提升到顶部"
 
 #: editor_actions.cc:1780
 msgid "Lower"
-msgstr ""
+msgstr "沉降"
 
 #: editor_actions.cc:1783
 msgid "Lower to Bottom"
-msgstr ""
+msgstr "沉降到底部"
 
 #: editor_actions.cc:1786
 msgid "Move to Original Position"
-msgstr ""
+msgstr "移动到原始位置"
 
 #: editor_actions.cc:1791
 msgid "Lock to Video"
-msgstr ""
+msgstr "锁定到视频"
 
 #: editor_actions.cc:1796 editor_markers.cc:912
 msgid "Glue to Bars and Beats"
-msgstr ""
+msgstr "粘连到小节和拍子"
 
 #: editor_actions.cc:1801
 msgid "Remove Sync"
@@ -4219,7 +4356,7 @@ msgstr "静音"
 
 #: editor_actions.cc:1807
 msgid "Normalize..."
-msgstr "标准化..."
+msgstr "规范化…"
 
 #: editor_actions.cc:1810
 msgid "Reverse"
@@ -4227,27 +4364,27 @@ msgstr "反转"
 
 #: editor_actions.cc:1813
 msgid "Make Mono Regions"
-msgstr ""
+msgstr "设为单声道区域"
 
 #: editor_actions.cc:1816
 msgid "Boost Gain"
-msgstr "提高增益"
+msgstr "放大增益"
 
 #: editor_actions.cc:1819
 msgid "Cut Gain"
-msgstr ""
+msgstr "减小增益"
 
 #: editor_actions.cc:1822
 msgid "Pitch Shift..."
-msgstr "基音转移"
+msgstr "音高替换…"
 
 #: editor_actions.cc:1825
 msgid "Transpose..."
-msgstr ""
+msgstr "变调…"
 
 #: editor_actions.cc:1828
 msgid "Opaque"
-msgstr "不透明度"
+msgstr "模糊度"
 
 #: editor_actions.cc:1832 editor_regions.cc:117
 msgid "Fade In"
@@ -4259,7 +4396,7 @@ msgstr "淡出"
 
 #: editor_actions.cc:1852
 msgid "Multi-Duplicate..."
-msgstr "多复制..."
+msgstr "多个副本…"
 
 #: editor_actions.cc:1857
 msgid "Fill Track"
@@ -4271,27 +4408,28 @@ msgstr "设置循环范围"
 
 #: editor_actions.cc:1868
 msgid "Set Punch"
-msgstr "设置Punch"
+msgstr "设置切换"
 
 #: editor_actions.cc:1872
 msgid "Add Single Range Marker"
-msgstr ""
+msgstr "添加单个范围标记"
 
 #: editor_actions.cc:1877
 msgid "Add Range Marker Per Region"
-msgstr ""
+msgstr "为每个区域添加范围标记"
 
 #: editor_actions.cc:1881
 msgid "Snap Position To Grid"
-msgstr ""
+msgstr "吸附位置到网格"
 
 #: editor_actions.cc:1884
 msgid "Close Gaps"
-msgstr ""
+msgstr "封闭间隙"
 
+# 使用方法 http://linuxaudioblog.com/?tag=rhythm-ferret
 #: editor_actions.cc:1887
 msgid "Rhythm Ferret..."
-msgstr ""
+msgstr "节奏探测…"
 
 #: editor_actions.cc:1890
 msgid "Export..."
@@ -4299,7 +4437,7 @@ msgstr "导出..."
 
 #: editor_actions.cc:1896
 msgid "Separate Under"
-msgstr ""
+msgstr "分离位于"
 
 #: editor_actions.cc:1900 editor_actions.cc:1901
 msgid "Set Fade In Length"
@@ -4315,103 +4453,103 @@ msgstr "从区域设置节奏=小节"
 
 #: editor_actions.cc:1910
 msgid "Split at Percussion Onsets"
-msgstr ""
+msgstr "在打击乐击发处拆分"
 
 #: editor_actions.cc:1915
 msgid "List Editor..."
-msgstr "编辑列表"
+msgstr "列表编辑器…"
 
 #: editor_actions.cc:1918
 msgid "Properties..."
-msgstr "属性..."
+msgstr "属性…"
 
 #: editor_actions.cc:1922
 msgid "Bounce (with processing)"
-msgstr ""
+msgstr "欢跳弹奏(并处理)"
 
 #: editor_actions.cc:1923
 msgid "Bounce (without processing)"
-msgstr ""
+msgstr "欢跳弹奏(不处理)"
 
 #: editor_actions.cc:1924
 msgid "Combine"
-msgstr ""
+msgstr "整合"
 
 #: editor_actions.cc:1925
 msgid "Uncombine"
-msgstr ""
+msgstr "不整合"
 
 #: editor_actions.cc:1927
 msgid "Spectral Analysis..."
-msgstr "频谱分析..."
+msgstr "频谱分析…"
 
 #: editor_actions.cc:1929
 msgid "Reset Envelope"
-msgstr "重置包络线"
+msgstr "重置封装"
 
 #: editor_actions.cc:1931
 msgid "Reset Gain"
-msgstr "预设增益"
+msgstr "重置增益"
 
 #: editor_actions.cc:1936
 msgid "Envelope Active"
-msgstr "激活包络线"
+msgstr "封装激活"
 
 #: editor_actions.cc:1944 editor_actions.cc:1945
 msgid "Insert Patch Change..."
-msgstr ""
+msgstr "插入切变音色…"
 
 #: editor_actions.cc:1946
 msgid "Unlink from other copies"
-msgstr ""
+msgstr "解除链接其它拷贝"
 
 #: editor_actions.cc:1947
 msgid "Strip Silence..."
-msgstr ""
+msgstr "片段无声…"
 
 #: editor_actions.cc:1948
 msgid "Set Range Selection"
-msgstr ""
+msgstr "设置范围已选择部分"
 
 #: editor_actions.cc:1950 editor_actions.cc:1951
 msgid "Nudge Later"
-msgstr ""
+msgstr "向后微调"
 
 #: editor_actions.cc:1952 editor_actions.cc:1953
 msgid "Nudge Earlier"
-msgstr ""
+msgstr "向前微调"
 
 #: editor_actions.cc:1955
 msgid "Sequence Regions"
-msgstr ""
+msgstr "序列区域"
 
 #: editor_actions.cc:1960
 msgid "Nudge Later by Capture Offset"
-msgstr ""
+msgstr "以捕获部分偏移向后微调"
 
 #: editor_actions.cc:1967
 msgid "Nudge Earlier by Capture Offset"
-msgstr ""
+msgstr "以捕获部分偏移向前微调"
 
 #: editor_actions.cc:1971
 msgid "Trim to Loop"
-msgstr ""
+msgstr "修剪到循环"
 
 #: editor_actions.cc:1972
 msgid "Trim to Punch"
-msgstr ""
+msgstr "修剪到切换"
 
 #: editor_actions.cc:1974
 msgid "Trim to Previous"
-msgstr ""
+msgstr "修剪到上一个"
 
 #: editor_actions.cc:1975
 msgid "Trim to Next"
-msgstr ""
+msgstr "修剪到下一个"
 
 #: editor_actions.cc:1982
 msgid "Insert Region From Region List"
-msgstr ""
+msgstr "从区域列表插入区域"
 
 #: editor_actions.cc:1988
 msgid "Set Sync Position"
@@ -4419,51 +4557,51 @@ msgstr "设置同步位置"
 
 #: editor_actions.cc:1989
 msgid "Place Transient"
-msgstr ""
+msgstr "放置过渡"
 
 #: editor_actions.cc:1990
 msgid "Split/Separate"
-msgstr ""
+msgstr "拆分/分离"
 
 #: editor_actions.cc:1991
 msgid "Trim Start at Edit Point"
-msgstr ""
+msgstr "在编辑点修剪起点"
 
 #: editor_actions.cc:1992
 msgid "Trim End at Edit Point"
-msgstr ""
+msgstr "在编辑点修剪终点"
 
 #: editor_actions.cc:1997
 msgid "Align Start"
-msgstr ""
+msgstr "对齐起点"
 
 #: editor_actions.cc:2004
 msgid "Align Start Relative"
-msgstr ""
+msgstr "对齐起点相关"
 
 #: editor_actions.cc:2008
 msgid "Align End"
-msgstr ""
+msgstr "对齐终点"
 
 #: editor_actions.cc:2013
 msgid "Align End Relative"
-msgstr ""
+msgstr "对齐终点相关"
 
 #: editor_actions.cc:2020
 msgid "Align Sync"
-msgstr ""
+msgstr "对齐同步"
 
 #: editor_actions.cc:2027
 msgid "Align Sync Relative"
-msgstr ""
+msgstr "对齐同步相关"
 
 #: editor_actions.cc:2031 editor_actions.cc:2034
 msgid "Choose Top..."
-msgstr ""
+msgstr "选择顶部…"
 
 #: editor_audio_import.cc:77 editor_audio_import.cc:99
 msgid "You can't import or embed an audiofile until you have a session loaded."
-msgstr "无法导入嵌入的的音频文件, 除非你已经载入一个会话文件."
+msgstr "无法导入嵌入的的音频文件,,除非您已经载入一个会话文件。"
 
 #: editor_audio_import.cc:83 editor_audio_import.cc:127
 msgid "Add Existing Media"
@@ -4471,19 +4609,17 @@ msgstr "添加已存在的媒体"
 
 #: editor_audio_import.cc:175
 msgid ""
-"The session already contains a source file named %1.  Do you want to import "
-"%1 as a new file, or skip it?"
+"The session already contains a source file named %1.  Do you want to import %1 as "
+"a new file, or skip it?"
 msgstr ""
-"此会话已经存在一个名为 %1 的源文件. 你想把 %1 作为一个新文件导入进来, 或跳过"
-"它?"
+"此会话已经存在一个名为 %1 的源文件。您想把 %1 作为一个新文件导入进来,,或者跳过它?"
 
 #: editor_audio_import.cc:177
 msgid ""
-"The session already contains a source file named %1.  Do you want to import "
-"%2 as a new source, or skip it?"
+"The session already contains a source file named %1.  Do you want to import %2 as "
+"a new source, or skip it?"
 msgstr ""
-"此会话已经存在一个名为 %1 的源文件. 你想把 %2 作为一个新的源导入进来, 或跳过"
-"它?"
+"此会话已经存在一个名为 %1 的源文件。您想把 %2 作为一个新的源导入进来,,或者跳过它?"
 
 #: editor_audio_import.cc:282 editor_videotimeline.cc:91
 msgid "Cancel Import"
@@ -4495,18 +4631,17 @@ msgstr "编辑器: 无法打开文件 \"%1\", (%2)"
 
 #: editor_audio_import.cc:567
 msgid "Cancel entire import"
-msgstr "取消全部导入"
+msgstr "取消整体导入"
 
 #: editor_audio_import.cc:568
 msgid "Don't embed it"
-msgstr "不嵌入之"
+msgstr "不嵌入它"
 
 #: editor_audio_import.cc:569
 msgid "Embed all without questions"
-msgstr "嵌入所有, 不提问"
+msgstr "嵌入所有,不必询问"
 
-#: editor_audio_import.cc:572 editor_audio_import.cc:598
-#: export_format_dialog.cc:60
+#: editor_audio_import.cc:572 editor_audio_import.cc:598 export_format_dialog.cc:60
 msgid "Sample rate"
 msgstr "采样率"
 
@@ -4516,23 +4651,23 @@ msgid ""
 "This audiofile's sample rate doesn't match the session sample rate!"
 msgstr ""
 "%1\n"
-"此音频文件的采样率与会话的采样率不匹配!"
+"此音频文件的采样率与会话的采样率不匹配!"
 
 #: editor_audio_import.cc:595
 msgid "Embed it anyway"
-msgstr "嵌入之, 不管了"
+msgstr "只管嵌入它"
 
 #: editor_canvas_events.cc:1306 editor_drag.cc:1381
 msgid "Could not create new track after region placed in the drop zone"
-msgstr ""
+msgstr "区域被放置在落选区后,无法创建新音轨"
 
 #: editor_drag.cc:1266
 msgid "fixed time region drag"
-msgstr "固定时间区域拖拽"
+msgstr "已定型的时间区域拖拽"
 
 #: editor_drag.cc:2214
 msgid "Ripple drag"
-msgstr ""
+msgstr "波纹拖拽"
 
 #: editor_drag.cc:2365 midi_region_view.cc:2813
 msgid "resize notes"
@@ -4540,23 +4675,23 @@ msgstr "重设音符大小"
 
 #: editor_drag.cc:2517
 msgid "Video Start:"
-msgstr ""
+msgstr "视频起点:"
 
 #: editor_drag.cc:2519
 msgid "Diff:"
-msgstr ""
+msgstr "差别:"
 
 #: editor_drag.cc:2538
 msgid "Move Video"
-msgstr ""
+msgstr "移动视频"
 
 #: editor_drag.cc:3046
 msgid "copy meter mark"
-msgstr "复制标尺标记"
+msgstr "复制节拍标记"
 
 #: editor_drag.cc:3054
 msgid "move meter mark"
-msgstr "移动标尺标记"
+msgstr "移动节拍标记"
 
 #: editor_drag.cc:3177
 msgid "copy tempo mark"
@@ -4584,23 +4719,23 @@ msgstr "当执行时间延伸操作时出现错误"
 
 #: editor_drag.cc:4947
 msgid "programming_error: %1"
-msgstr ""
+msgstr "程序错误:%1"
 
 #: editor_drag.cc:5016 editor_drag.cc:5026
 msgid "new skip marker"
-msgstr ""
+msgstr "新建跳跃标记"
 
 #: editor_drag.cc:5017
 msgid "skip"
-msgstr ""
+msgstr "跳跃"
 
 #: editor_drag.cc:5021 location_ui.cc:56
 msgid "CD"
-msgstr "CD"
+msgstr ""
 
 #: editor_drag.cc:5022
 msgid "new CD marker"
-msgstr ""
+msgstr "新建CD标记"
 
 #: editor_drag.cc:5027 editor_route_groups.cc:437 mixer_ui.cc:1493
 msgid "unnamed"
@@ -4608,19 +4743,19 @@ msgstr "未命名的"
 
 #: editor_drag.cc:5309
 msgid "Automation range drag created for invalid region type"
-msgstr ""
+msgstr "为无效的区域类型已创建自动范围拖拽"
 
 #: editor_route_groups.cc:96
 msgid "Col"
-msgstr ""
+msgstr "列"
 
 #: editor_route_groups.cc:96
 msgid "Group Tab Color"
-msgstr ""
+msgstr "分组标签页颜色"
 
 #: editor_route_groups.cc:97
 msgid "Name of Group"
-msgstr ""
+msgstr "分组名称"
 
 #: editor_route_groups.cc:98 editor_routes.cc:207
 msgid "V"
@@ -4628,80 +4763,80 @@ msgstr ""
 
 #: editor_route_groups.cc:98
 msgid "Group is visible?"
-msgstr ""
+msgstr "分组是否可见?"
 
 #: editor_route_groups.cc:99
 msgid "On"
-msgstr ""
+msgstr "开启"
 
 #: editor_route_groups.cc:99
 msgid "Group is enabled?"
-msgstr ""
+msgstr "分组是否可用?"
 
 #: editor_route_groups.cc:100
 msgid "group|G"
-msgstr ""
+msgstr "分组|G"
 
 #: editor_route_groups.cc:100
 msgid "Sharing Gain?"
-msgstr ""
+msgstr "分享增益?"
 
 #: editor_route_groups.cc:101
 msgid "relative|Rel"
-msgstr ""
+msgstr "相关|Rel"
 
 #: editor_route_groups.cc:101
 msgid "Relative Gain Changes?"
-msgstr ""
+msgstr "相关增益改变?"
 
 #: editor_route_groups.cc:102
 msgid "mute|M"
-msgstr ""
+msgstr "静音|M"
 
 #: editor_route_groups.cc:102
 msgid "Sharing Mute?"
-msgstr ""
+msgstr "分享静音?"
 
 #: editor_route_groups.cc:103
 msgid "solo|S"
-msgstr ""
+msgstr "独奏|S"
 
 #: editor_route_groups.cc:103
 msgid "Sharing Solo?"
-msgstr ""
+msgstr "分享独奏?"
 
 #: editor_route_groups.cc:104 midi_time_axis.cc:1622 midi_time_axis.cc:1625
 #: midi_time_axis.cc:1628
 msgid "Rec"
-msgstr ""
+msgstr "录制"
 
 #: editor_route_groups.cc:104
 msgid "Sharing Record-enable Status?"
-msgstr ""
+msgstr "分享静音?"
 
 #: editor_route_groups.cc:105
 msgid "monitoring|Mon"
-msgstr ""
+msgstr "监控|Mon"
 
 #: editor_route_groups.cc:105
 msgid "Sharing Monitoring Choice?"
-msgstr ""
+msgstr "分享监控选择?"
 
 #: editor_route_groups.cc:106
 msgid "selection|Sel"
-msgstr ""
+msgstr "已选择部分|Sel"
 
 #: editor_route_groups.cc:106
 msgid "Sharing Selected/Editing Status?"
-msgstr ""
+msgstr "分享已选择/编辑状态?"
 
 #: editor_route_groups.cc:107
 msgid "active|A"
-msgstr ""
+msgstr "激活"
 
 #: editor_route_groups.cc:107
 msgid "Sharing Active Status?"
-msgstr ""
+msgstr "分享激活状态?"
 
 #: editor_export_audio.cc:92 editor_markers.cc:740 editor_markers.cc:827
 #: editor_markers.cc:1012 editor_markers.cc:1030 editor_markers.cc:1048
@@ -4711,48 +4846,48 @@ msgstr ""
 #: editor_markers.cc:1356 editor_markers.cc:1382 editor_markers.cc:1576
 #: editor_mouse.cc:2120
 msgid "programming error: marker canvas item has no marker object pointer!"
-msgstr ""
+msgstr "程序错误:标记版面条目没有标记对象物体指示!"
 
 #: editor_export_audio.cc:145 editor_export_audio.cc:150
 msgid "File Exists!"
-msgstr ""
+msgstr "文件已存在!"
 
 #: editor_export_audio.cc:153
 msgid "Overwrite Existing File"
-msgstr ""
+msgstr "覆盖已存在文件"
 
 #: editor_group_tabs.cc:176
 msgid "Fit to Window"
-msgstr "放置窗口"
+msgstr "匹配适合窗口"
 
 #: editor_markers.cc:139
 msgid "start"
-msgstr "开始"
+msgstr "start"
 
 #: editor_markers.cc:140
 msgid "end"
-msgstr "结束"
+msgstr "终点"
 
-#: editor_markers.cc:657 editor_ops.cc:2085 editor_ops.cc:2107
-#: editor_ops.cc:2164 editor_ops.cc:2193 location_ui.cc:1023
+#: editor_markers.cc:657 editor_ops.cc:2085 editor_ops.cc:2107 editor_ops.cc:2164
+#: editor_ops.cc:2193 location_ui.cc:1023
 msgid "add marker"
 msgstr "添加标记"
 
 #: editor_markers.cc:689 editor_markers.cc:1456
 msgid "set loop range"
-msgstr "设置循环范围"
+msgstr "设置切换范围"
 
 #: editor_markers.cc:705 editor_markers.cc:1462
 msgid "set punch range"
-msgstr "设置冲击范围"
+msgstr "设置切换范围"
 
 #: editor_markers.cc:722 editor_ops.cc:4055
 msgid "range"
-msgstr ""
+msgstr "范围"
 
 #: editor_markers.cc:725
 msgid "new range marker"
-msgstr "新范围标记"
+msgstr "新建范围标记"
 
 #: editor_markers.cc:758 editor_ops.cc:2129 location_ui.cc:859
 msgid "remove marker"
@@ -4764,11 +4899,11 @@ msgstr "定位到此处"
 
 #: editor_markers.cc:895
 msgid "Play from Here"
-msgstr "从这儿播放"
+msgstr "从此处开始播放"
 
 #: editor_markers.cc:896
 msgid "Move Mark to Playhead"
-msgstr "移动标记到播放头"
+msgstr "移动标记到指针"
 
 #: editor_markers.cc:900
 msgid "Create Range to Next Marker"
@@ -4776,19 +4911,19 @@ msgstr "创建范围到下一个标记"
 
 #: editor_markers.cc:941
 msgid "Locate to Marker"
-msgstr ""
+msgstr "定位到标记"
 
 #: editor_markers.cc:942
 msgid "Play from Marker"
-msgstr ""
+msgstr "从标记开始播放"
 
 #: editor_markers.cc:945
 msgid "Set Marker from Playhead"
-msgstr ""
+msgstr "从指针起设置标记"
 
 #: editor_markers.cc:947
 msgid "Set Range from Selection"
-msgstr ""
+msgstr "从已选择部分起设置范围"
 
 #: editor_markers.cc:957
 msgid "Hide Range"
@@ -4796,7 +4931,7 @@ msgstr "隐藏范围"
 
 #: editor_markers.cc:958
 msgid "Rename Range..."
-msgstr "重命名范围..."
+msgstr "重命名范围…"
 
 #: editor_markers.cc:962
 msgid "Remove Range"
@@ -4812,7 +4947,7 @@ msgstr "选择范围"
 
 #: editor_markers.cc:1001
 msgid "Set Punch Range"
-msgstr "设置Punch范围"
+msgstr "设置切换范围"
 
 #: editor_markers.cc:1407 editor_ops.cc:2040
 msgid "New Name:"
@@ -4837,34 +4972,32 @@ msgstr "重命名标记"
 
 #: editor_mixer.cc:90
 msgid "This screen is not tall enough to display the editor mixer"
-msgstr ""
+msgstr "屏幕高度不足以显示编辑器或混音器"
 
 #: editor_mouse.cc:1223 editor_mouse.cc:1241 editor_tempodisplay.cc:270
-msgid ""
-"programming error: tempo marker canvas item has no marker object pointer!"
-msgstr ""
+msgid "programming error: tempo marker canvas item has no marker object pointer!"
+msgstr "程序错误:节奏标记版面条目没有标记对象物体指示!"
 
 #: editor_mouse.cc:1228 editor_tempodisplay.cc:275
 msgid "programming error: marker for tempo is not a tempo marker!"
-msgstr ""
+msgstr "程序错误:节奏上的标记不是一个节奏标记!"
 
 #: editor_mouse.cc:1246 editor_tempodisplay.cc:375
 msgid "programming error: marker for meter is not a meter marker!"
-msgstr ""
+msgstr "程序错误:节拍上的标记不是一个节拍标记!"
 
 #: editor_mouse.cc:1885 editor_mouse.cc:1910 editor_mouse.cc:1923
 msgid ""
-"programming error: control point canvas item has no control point object "
-"pointer!"
-msgstr ""
+"programming error: control point canvas item has no control point object pointer!"
+msgstr "程序错误:控制点版面条目没有控制点对象物体指示!"
 
 #: editor_mouse.cc:2058
 msgid "start point trim"
-msgstr "起始点修剪"
+msgstr "起点修剪"
 
 #: editor_mouse.cc:2083
 msgid "End point trim"
-msgstr "终止点修剪"
+msgstr "终点修剪"
 
 #: editor_mouse.cc:2135
 msgid "Name for region:"
@@ -4872,47 +5005,47 @@ msgstr "区域名:"
 
 #: editor_ops.cc:165
 msgid "split"
-msgstr "分离"
+msgstr "拆分"
 
 #: editor_ops.cc:339
 msgid "alter selection"
-msgstr "转换选区"
+msgstr "更改已选择部分"
 
 #: editor_ops.cc:381
 msgid "nudge regions forward"
-msgstr ""
+msgstr "向前微调区域"
 
 #: editor_ops.cc:404 editor_ops.cc:489
 msgid "nudge location forward"
-msgstr ""
+msgstr "向前微调位置"
 
 #: editor_ops.cc:462
 msgid "nudge regions backward"
-msgstr ""
+msgstr "向后微调区域"
 
 #: editor_ops.cc:551
 msgid "nudge forward"
-msgstr ""
+msgstr "向前微调"
 
 #: editor_ops.cc:575
 msgid "nudge backward"
-msgstr ""
+msgstr "向后微调"
 
 #: editor_ops.cc:618
 msgid "sequence regions"
-msgstr ""
+msgstr "序列区域"
 
 #: editor_ops.cc:694
 msgid "build_region_boundary_cache called with snap_type = %1"
-msgstr ""
+msgstr "构建区域边界缓存调用吸附类型 = %1"
 
 #: editor_ops.cc:2042
 msgid "New Location Marker"
-msgstr "新位置标记"
+msgstr "新建位置标记"
 
 #: editor_ops.cc:2164
 msgid "add markers"
-msgstr "添加一些标记"
+msgstr "添加标记"
 
 #: editor_ops.cc:2274
 msgid "clear markers"
@@ -4928,35 +5061,35 @@ msgstr "清除位置"
 
 #: editor_ops.cc:2368
 msgid "insert region"
-msgstr "摄入区域"
+msgstr "插入区域"
 
 #: editor_ops.cc:2559
 msgid "raise regions"
-msgstr ""
+msgstr "提升区域"
 
 #: editor_ops.cc:2561
 msgid "raise region"
-msgstr ""
+msgstr "提升区域"
 
 #: editor_ops.cc:2567
 msgid "raise regions to top"
-msgstr ""
+msgstr "提升区域到顶部"
 
 #: editor_ops.cc:2569
 msgid "raise region to top"
-msgstr ""
+msgstr "提升区域到顶部"
 
 #: editor_ops.cc:2575
 msgid "lower regions"
-msgstr ""
+msgstr "沉降区域"
 
 #: editor_ops.cc:2577 editor_ops.cc:2585
 msgid "lower region"
-msgstr ""
+msgstr "沉降区域"
 
 #: editor_ops.cc:2583
 msgid "lower regions to bottom"
-msgstr ""
+msgstr "沉降区域到底部"
 
 #: editor_ops.cc:2668
 msgid "Rename Region"
@@ -4964,7 +5097,7 @@ msgstr "重命名区域"
 
 #: editor_ops.cc:2670 processor_box.cc:1992 route_ui.cc:1626
 msgid "New name:"
-msgstr "新名字:"
+msgstr "新名称:"
 
 #: editor_ops.cc:2987
 msgid "separate"
@@ -4972,11 +5105,11 @@ msgstr "分离"
 
 #: editor_ops.cc:3099
 msgid "separate region under"
-msgstr "分离区域于"
+msgstr "分离区域位于"
 
 #: editor_ops.cc:3220
 msgid "trim to selection"
-msgstr "修剪选取"
+msgstr "修剪到已选中部分"
 
 #: editor_ops.cc:3356
 msgid "set sync point"
@@ -4996,43 +5129,45 @@ msgstr "移动区域到原始位置"
 
 #: editor_ops.cc:3425
 msgid "align selection"
-msgstr "对齐选择"
+msgstr "对齐已选中部分"
 
 #: editor_ops.cc:3499
 msgid "align selection (relative)"
-msgstr "对其选择(相关的)"
+msgstr "对齐已选中部分(相关)"
 
 #: editor_ops.cc:3533
 msgid "align region"
-msgstr "对其区域"
+msgstr "对齐区域"
 
 #: editor_ops.cc:3584
 msgid "trim front"
-msgstr ""
+msgstr "修剪前部"
 
 #: editor_ops.cc:3584
 msgid "trim back"
-msgstr ""
+msgstr "修剪后部"
 
 #: editor_ops.cc:3614
 msgid "trim to loop"
-msgstr ""
+msgstr "修剪到循环"
 
 #: editor_ops.cc:3624
 msgid "trim to punch"
-msgstr ""
+msgstr "修剪到切换"
 
 #: editor_ops.cc:3686
 msgid "trim to region"
-msgstr ""
+msgstr "修剪到区域"
 
 #: editor_ops.cc:3794
 msgid ""
-"This track/bus cannot be frozen because the signal adds or loses channels "
-"before reaching the outputs.\n"
-"This is typically caused by plugins that generate stereo output from mono "
-"input or vice versa."
+"This track/bus cannot be frozen because the signal adds or loses channels before "
+"reaching the outputs.\n"
+"This is typically caused by plugins that generate stereo output from mono input or "
+"vice versa."
 msgstr ""
+"这个音轨/总线不能被冻结,因为在信号到达输出前添加或丢失了声道。\n"
+"这通常是由于从单声道输入生成立体声输出(反之亦然)的插件引起的。"
 
 #: editor_ops.cc:3797
 msgid "Cannot freeze"
@@ -5046,18 +5181,23 @@ msgid ""
 "\n"
 "Freezing will only process the signal as far as the first send/insert/return."
 msgstr ""
+"<b>%1</b>\n"
+"\n"
+"这个音轨至少有一个发送/插入/返回作为它的信号流的一部分。\n"
+"\n"
+"冻结将只会处理到信号的第一个发送/插入/返回为止。"
 
 #: editor_ops.cc:3807
 msgid "Freeze anyway"
-msgstr ""
+msgstr "只管冻结"
 
 #: editor_ops.cc:3808
 msgid "Don't freeze"
-msgstr ""
+msgstr "不要冻结"
 
 #: editor_ops.cc:3809
 msgid "Freeze Limits"
-msgstr ""
+msgstr "冻结限制"
 
 #: editor_ops.cc:3824
 msgid "Cancel Freeze"
@@ -5065,20 +5205,24 @@ msgstr "取消冻结"
 
 #: editor_ops.cc:3854
 msgid ""
-"You can't perform this operation because the processing of the signal will "
-"cause one or more of the tracks to end up with a region with more channels "
-"than this track has inputs.\n"
+"You can't perform this operation because the processing of the signal will cause "
+"one or more of the tracks to end up with a region with more channels than this "
+"track has inputs.\n"
 "\n"
 "You can do this without processing, which is a different operation."
 msgstr ""
+"您不能执行此操作,因为信号的处理将导致一个或多个音轨以带着多个声道的区域结束,而不"
+"是以这个音轨拥有的输入声道结束。\n"
+"\n"
+"您可以不做任何处理,这是一个不同的操作。"
 
 #: editor_ops.cc:3858
 msgid "Cannot bounce"
-msgstr ""
+msgstr "不能欢跳弹奏"
 
 #: editor_ops.cc:3869
 msgid "bounce range"
-msgstr ""
+msgstr "欢跳弹奏范围"
 
 #: editor_ops.cc:3971
 msgid "delete"
@@ -5098,7 +5242,7 @@ msgstr "清除"
 
 #: editor_ops.cc:4028
 msgid "objects"
-msgstr ""
+msgstr "对象物体"
 
 #: editor_ops.cc:4238 editor_ops.cc:4270
 msgid "remove region"
@@ -5106,52 +5250,52 @@ msgstr "删除区间"
 
 #: editor_ops.cc:4719
 msgid "duplicate selection"
-msgstr "重复选择"
+msgstr "复制已选择部分"
 
 #: editor_ops.cc:4803
 msgid "nudge track"
-msgstr ""
+msgstr "微调音轨"
 
 #: editor_ops.cc:4840
 msgid ""
 "Do you really want to destroy the last capture?\n"
 "(This is destructive and cannot be undone)"
 msgstr ""
-"你确定销毁最后的录音?\n"
-"(这个操作有毁灭性, 不能撤销!)"
+"您是否确定要销毁最后已捕获内容?\n"
+"(这个操作有破坏性且不能撤销!)"
 
 #: editor_ops.cc:4843 editor_ops.cc:6838 editor_regions.cc:462
 #: editor_snapshots.cc:159 route_ui.cc:1569
 msgid "No, do nothing."
-msgstr "不, 什么都不做."
+msgstr "否, 什么都不做。"
 
 #: editor_ops.cc:4844
 msgid "Yes, destroy it."
-msgstr "是, 销毁它."
+msgstr "是,销毁它。"
 
 #: editor_ops.cc:4846
 msgid "Destroy last capture"
-msgstr "销毁最后的录音"
+msgstr "销毁最后捕获的部分"
 
 #: editor_ops.cc:4906
 msgid "normalize"
-msgstr "标准化"
+msgstr "规范化"
 
 #: editor_ops.cc:5000
 msgid "reverse regions"
-msgstr "倒置区域"
+msgstr "反转区域"
 
 #: editor_ops.cc:5034
 msgid "strip silence"
-msgstr ""
+msgstr "片段无声"
 
 #: editor_ops.cc:5091
 msgid "Fork Region(s)"
-msgstr ""
+msgstr "分解区域"
 
 #: editor_ops.cc:5112
 msgid "Could not unlink %1"
-msgstr ""
+msgstr "无法解除链接 %1"
 
 #: editor_ops.cc:5326
 msgid "reset region gain"
@@ -5159,7 +5303,7 @@ msgstr "重设区域增益"
 
 #: editor_ops.cc:5379
 msgid "region gain envelope active"
-msgstr "区域增益包络启用"
+msgstr "区域增益封装激活"
 
 #: editor_ops.cc:5406
 msgid "toggle region lock"
@@ -5167,7 +5311,7 @@ msgstr "切换区域锁定"
 
 #: editor_ops.cc:5430
 msgid "Toggle Video Lock"
-msgstr ""
+msgstr "切换视频锁定"
 
 #: editor_ops.cc:5454
 msgid "region lock style"
@@ -5175,11 +5319,11 @@ msgstr "区域锁定风格"
 
 #: editor_ops.cc:5479
 msgid "change region opacity"
-msgstr "改变区域的不透明度"
+msgstr "改变区域的模糊度"
 
 #: editor_ops.cc:5572
 msgid "fade range"
-msgstr ""
+msgstr "淡化范围"
 
 #: editor_ops.cc:5610
 msgid "set fade in length"
@@ -5207,23 +5351,23 @@ msgstr "设置淡出长度"
 
 #: editor_ops.cc:5994
 msgid "set loop range from selection"
-msgstr "从选择设置循环范围"
+msgstr "从已选择部分设置循环范围"
 
 #: editor_ops.cc:6008
 msgid "set loop range from region"
-msgstr "从范围设置循环范围"
+msgstr "从区域设置循环范围"
 
 #: editor_ops.cc:6027
 msgid "set punch range from selection"
-msgstr "从选择设置punch范围"
+msgstr "从已选择部分设置切换范围"
 
 #: editor_ops.cc:6041
 msgid "set session start/end from selection"
-msgstr ""
+msgstr "从已选择部分设置会话起点/终点"
 
 #: editor_ops.cc:6066
 msgid "set punch range from region"
-msgstr "从区域设置punch范围"
+msgstr "从区域设置切换范围"
 
 #: editor_ops.cc:6175
 msgid "Add new marker"
@@ -5231,23 +5375,23 @@ msgstr "添加新标记"
 
 #: editor_ops.cc:6176
 msgid "Set global tempo"
-msgstr "设置全局速度"
+msgstr "设置全局节奏"
 
 #: editor_ops.cc:6179
 msgid "Define one bar"
-msgstr "定义一个bar"
+msgstr "定义一个小节"
 
 #: editor_ops.cc:6180
 msgid "Do you want to set the global tempo or add a new tempo marker?"
-msgstr "你是否想要设置全局速度或添加一个新的速度标签?"
+msgstr "您是否要设置全局节奏或者添加一个新的节奏标签?"
 
 #: editor_ops.cc:6206
 msgid "set tempo from region"
-msgstr "从区域设置速度"
+msgstr "从区域设置节奏"
 
 #: editor_ops.cc:6236
 msgid "split regions"
-msgstr "分离区域"
+msgstr "拆分区域"
 
 #: editor_ops.cc:6278
 msgid ""
@@ -5256,46 +5400,46 @@ msgid ""
 "into %2 pieces.\n"
 "This could take a long time."
 msgstr ""
-"你试图分离\n"
+"您试图拆分\n"
 " %1\n"
-" %2 æ–­.\n"
-"这需要一些时间."
+" 成为 %2 部分。\n"
+"这需要一些时间。"
 
 #: editor_ops.cc:6285
 msgid "Call for the Ferret!"
-msgstr ""
+msgstr "调用探测!"
 
 #: editor_ops.cc:6286
 msgid ""
 "Press OK to continue with this split operation\n"
 "or ask the Ferret dialog to tune the analysis"
 msgstr ""
-"按OK来继续分离操作\n"
-"or ask the Ferret dialog to tune the analysis"
+"按OK继续拆分操作\n"
+"或者请求探测对话框进行优化分析"
 
 #: editor_ops.cc:6288
 msgid "Press OK to continue with this split operation"
-msgstr "按OK来继续分离操作"
+msgstr "按OK继续拆分操作"
 
 #: editor_ops.cc:6291
 msgid "Excessive split?"
-msgstr "过多的分离?"
+msgstr "过多的拆分?"
 
 #: editor_ops.cc:6443
 msgid "place transient"
-msgstr ""
+msgstr "放置过渡"
 
 #: editor_ops.cc:6478
 msgid "snap regions to grid"
-msgstr ""
+msgstr "吸附区域到网格"
 
 #: editor_ops.cc:6517
 msgid "Close Region Gaps"
-msgstr "关闭区域空白"
+msgstr "关闭区域空缺"
 
 #: editor_ops.cc:6522
 msgid "Crossfade length"
-msgstr "交叉淡入淡出长度"
+msgstr "交叉淡化长度"
 
 #: editor_ops.cc:6531 editor_ops.cc:6542 rhythm_ferret.cc:119
 #: session_option_editor.cc:141
@@ -5304,7 +5448,7 @@ msgstr ""
 
 #: editor_ops.cc:6533
 msgid "Pull-back length"
-msgstr ""
+msgstr "撤回长度"
 
 #: editor_ops.cc:6546
 msgid "Ok"
@@ -5312,11 +5456,11 @@ msgstr ""
 
 #: editor_ops.cc:6561
 msgid "close region gaps"
-msgstr "关闭区间空白"
+msgstr "关闭区域空缺"
 
 #: editor_ops.cc:6786 route_ui.cc:1543
 msgid "That would be bad news ...."
-msgstr ""
+msgstr "这将是个坏消息…"
 
 #: editor_ops.cc:6791 route_ui.cc:1548
 msgid ""
@@ -5327,6 +5471,12 @@ msgid ""
 "edit your ardour.rc file to set the\n"
 "\"allow-special-bus-removal\" option to be \"yes\""
 msgstr ""
+"删除主控或监控总线可不是个好主意\n"
+"且 %1 不允许这样做。\n"
+"\n"
+"如果您真的想做这种事\n"
+"编辑您的 ardour.rc 文件\n"
+"把\"allow-special-bus-removal\" 选项设为 \"yes\" "
 
 #: editor_ops.cc:6809
 msgid "tracks"
@@ -5351,10 +5501,11 @@ msgid ""
 "\n"
 "This action cannot be undone, and the session file will be overwritten!"
 msgstr ""
-"你确定移除 %1 %2 和 %3 %4?\n"
-"(这样播放列表可能会失去与 %2 的关联)\n"
+"您是否确定移除 %1 %2 和 %3 %4 ?\n"
+"(您也可能会丢失与 %2 相关的播放列表)\n"
 "\n"
-"此动作不可撤销, 而且此会话文件将会被重新写入!"
+"此操作不可撤销, 而且此会话文件将会被重写覆盖!(您也可能会丢失与 %2 相关的播放列"
+"表)"
 
 #: editor_ops.cc:6827
 msgid ""
@@ -5363,10 +5514,10 @@ msgid ""
 "\n"
 "This action cannot be undone, and the session file will be overwritten!"
 msgstr ""
-"你确定移除 %1 %2?\n"
-"(这样播放列表可能会失去与 %2 的关联)\n"
+"您是否确定移除 %1 %2 \n"
+"(您也可能会丢失与 %2 相关的播放列表)\n"
 "\n"
-"此动作不可撤销, 而且此会话文件将会被重新写入!"
+"此操作不可撤销, 而且此会话文件将会被重写覆盖!"
 
 #: editor_ops.cc:6833
 msgid ""
@@ -5374,14 +5525,17 @@ msgid ""
 "\n"
 "This action cannot be undone, and the session file will be overwritten"
 msgstr ""
+"您是否确定移除 %1 %2 ?\n"
+"\n"
+"此操作不可撤销, 而且此会话文件将会被重写覆盖"
 
 #: editor_ops.cc:6840
 msgid "Yes, remove them."
-msgstr "是的, 移除他们."
+msgstr "是的,移除它们。"
 
 #: editor_ops.cc:6842 editor_snapshots.cc:160 route_ui.cc:1570
 msgid "Yes, remove it."
-msgstr "使得, 移除它."
+msgstr "是的,移除它。"
 
 #: editor_ops.cc:6847 editor_ops.cc:6849
 msgid "Remove %1"
@@ -5393,11 +5547,11 @@ msgstr "插入时间"
 
 #: editor_ops.cc:7076
 msgid "There are too many tracks to fit in the current window"
-msgstr "现在的窗口可能容纳不下这么多的音轨."
+msgstr "音轨太多以至于无法匹配当前窗口。"
 
 #: editor_ops.cc:7137
 msgid "Sel"
-msgstr ""
+msgstr "选择"
 
 #: editor_ops.cc:7176
 #, c-format
@@ -5406,72 +5560,72 @@ msgstr "保存视图 %u"
 
 #: editor_ops.cc:7201
 msgid "mute regions"
-msgstr "这些区域静音"
+msgstr "静音区域"
 
 #: editor_ops.cc:7203
 msgid "mute region"
-msgstr "区域静音"
+msgstr "静音区域"
 
 #: editor_ops.cc:7240
 msgid "combine regions"
-msgstr "组合这些区域"
+msgstr "整合区域"
 
 #: editor_ops.cc:7278
 msgid "uncombine regions"
-msgstr "取消这些区域的组合"
+msgstr "解除整合区域"
 
 #: editor_ops.cc:7315
 msgid "%1: Locked"
-msgstr ""
+msgstr "%1: 锁定"
 
 #: editor_ops.cc:7322
 msgid "Click to unlock"
-msgstr ""
+msgstr "点击解除锁定"
 
 #: editor_ops.cc:7376
 msgid "Moving embedded files into session folder"
-msgstr ""
+msgstr "移动已嵌入的文件到会话文件夹"
 
 #: editor_regions.cc:112
 msgid "Region name, with number of channels in []'s"
-msgstr ""
+msgstr "区域名,在 [ ] 方括号内附带声道编号"
 
 #: editor_regions.cc:113
 msgid "Position of start of region"
-msgstr ""
+msgstr "区域起点的位置"
 
 #: editor_regions.cc:114 editor_regions.cc:851 time_info_box.cc:101
 msgid "End"
-msgstr "结束"
+msgstr "终点"
 
 #: editor_regions.cc:114
 msgid "Position of end of region"
-msgstr ""
+msgstr "区域终点的位置"
 
 #: editor_regions.cc:115
 msgid "Length of the region"
-msgstr ""
+msgstr "区域的长度"
 
 #: editor_regions.cc:116
 msgid "Position of region sync point, relative to start of the region"
-msgstr ""
+msgstr "区域同步点的位置,与区域起点相关"
 
 #: editor_regions.cc:117
 msgid "Length of region fade-in (units: secondary clock), () if disabled"
-msgstr ""
+msgstr "区域淡入的长度(如果无效时,加上单位:秒计时器)"
 
 #: editor_regions.cc:118
 msgid "Length of region fade-out (units: secondary clock), () if disabled"
-msgstr ""
+msgstr "区域淡出的长度(如果无效时,加上单位:秒计时器)"
 
-#: editor_regions.cc:119 mixer_strip.cc:2055 mono_panner.cc:203
-#: panner2d.cc:240 stereo_panner.cc:251 stereo_panner.cc:274
+#: editor_regions.cc:119 mixer_strip.cc:2055 mono_panner.cc:203 panner2d.cc:240
+#: stereo_panner.cc:251 stereo_panner.cc:274
 msgid "L"
 msgstr ""
 
 #: editor_regions.cc:119
 msgid "Region position locked?"
-msgstr ""
+msgstr "区域位置锁定?"
 
 #: editor_regions.cc:120 route_time_axis.cc:103
 msgid "G"
@@ -5479,17 +5633,17 @@ msgstr ""
 
 #: editor_regions.cc:120
 msgid "Region position glued to Bars|Beats time?"
-msgstr ""
+msgstr "区域位置粘连到小节|拍子时间?"
 
-#: editor_regions.cc:121 editor_routes.cc:211 gain_meter.cc:793
-#: mixer_strip.cc:2032 meter_strip.cc:359 panner_ui.cc:603
-#: route_time_axis.cc:2713 stereo_panner.cc:271 time_axis_view.cc:1190
+#: editor_regions.cc:121 editor_routes.cc:211 gain_meter.cc:793 mixer_strip.cc:2032
+#: meter_strip.cc:359 panner_ui.cc:603 route_time_axis.cc:2713 stereo_panner.cc:271
+#: time_axis_view.cc:1190
 msgid "M"
 msgstr ""
 
 #: editor_regions.cc:121
 msgid "Region muted?"
-msgstr ""
+msgstr "区域静音?"
 
 #: editor_regions.cc:122 mixer_strip.cc:1855
 msgid "O"
@@ -5497,7 +5651,7 @@ msgstr ""
 
 #: editor_regions.cc:122
 msgid "Region opaque (blocks regions below it from being heard)?"
-msgstr ""
+msgstr "区域模糊(从区域块以下的部分起可以被听见)?"
 
 #: editor_regions.cc:311 editor_regions.cc:316 editor_regions.cc:318
 msgid "Hidden"
@@ -5505,21 +5659,23 @@ msgstr "隐藏"
 
 #: editor_regions.cc:391
 msgid "(MISSING) "
-msgstr "(找不到) "
+msgstr "(缺失)"
 
 #: editor_regions.cc:459
 msgid ""
 "Do you really want to remove unused regions?\n"
 "(This is destructive and cannot be undone)"
 msgstr ""
+"您真的打算移除未使用的区域?\n"
+"(这是破坏性的且无法撤销)"
 
 #: editor_regions.cc:463
 msgid "Yes, remove."
-msgstr "确定移除."
+msgstr "是的,移除。"
 
 #: editor_regions.cc:465
 msgid "Remove unused regions"
-msgstr "移除没用的区域"
+msgstr "移除未使用的区域"
 
 #: editor_regions.cc:818 editor_regions.cc:832 editor_regions.cc:846
 msgid "Mult."
@@ -5527,15 +5683,15 @@ msgstr "多"
 
 #: editor_regions.cc:849 midi_list_editor.cc:104 time_info_box.cc:94
 msgid "Start"
-msgstr "开始"
+msgstr "起点"
 
 #: editor_regions.cc:867 editor_regions.cc:883
 msgid "Multiple"
-msgstr "多"
+msgstr "多个"
 
 #: editor_regions.cc:952
 msgid "MISSING "
-msgstr "找不到"
+msgstr "缺失"
 
 #: editor_routes.cc:182 editor_routes.cc:214
 msgid "SS"
@@ -5543,11 +5699,11 @@ msgstr ""
 
 #: editor_routes.cc:206
 msgid "Track/Bus Name"
-msgstr ""
+msgstr "音轨/总线名称"
 
 #: editor_routes.cc:207
 msgid "Track/Bus visible ?"
-msgstr ""
+msgstr "音轨/总线可见?"
 
 #: editor_routes.cc:208 mixer_strip.cc:2046 meter_strip.cc:371
 #: route_time_axis.cc:105 route_time_axis.cc:2701
@@ -5556,29 +5712,28 @@ msgstr ""
 
 #: editor_routes.cc:208
 msgid "Track/Bus active ?"
-msgstr ""
+msgstr "音轨/总线启用?"
 
-#: editor_routes.cc:209 mixer_strip.cc:2033 mixer_strip.cc:2054
-#: meter_strip.cc:379
+#: editor_routes.cc:209 mixer_strip.cc:2033 mixer_strip.cc:2054 meter_strip.cc:379
 msgid "I"
 msgstr ""
 
 #: editor_routes.cc:209
 msgid "MIDI input enabled"
-msgstr ""
+msgstr "MIDI输入已启用"
 
-#: editor_routes.cc:210 mono_panner.cc:220 panner2d.cc:241
-#: stereo_panner.cc:249 stereo_panner.cc:276
+#: editor_routes.cc:210 mono_panner.cc:220 panner2d.cc:241 stereo_panner.cc:249
+#: stereo_panner.cc:276
 msgid "R"
 msgstr ""
 
 #: editor_routes.cc:210
 msgid "Record enabled"
-msgstr ""
+msgstr "录制已启用"
 
 #: editor_routes.cc:211
 msgid "Muted"
-msgstr ""
+msgstr "已静音"
 
 #: editor_routes.cc:212 mixer_strip.cc:2042 meter_strip.cc:367
 #: route_time_axis.cc:2710
@@ -5587,7 +5742,7 @@ msgstr ""
 
 #: editor_routes.cc:212
 msgid "Soloed"
-msgstr ""
+msgstr "已独奏"
 
 #: editor_routes.cc:213
 msgid "SI"
@@ -5595,11 +5750,11 @@ msgstr ""
 
 #: editor_routes.cc:213
 msgid "Solo Isolated"
-msgstr ""
+msgstr "独奏已隔离"
 
 #: editor_routes.cc:214
 msgid "Solo Safe (Locked)"
-msgstr ""
+msgstr "独奏安全(锁定)"
 
 #: editor_routes.cc:477 mixer_ui.cc:1197
 msgid "Hide All"
@@ -5607,11 +5762,11 @@ msgstr "隐藏所有"
 
 #: editor_routes.cc:478 mixer_ui.cc:1198
 msgid "Show All Audio Tracks"
-msgstr "显示所有音轨"
+msgstr "显示所有音频轨道"
 
 #: editor_routes.cc:479 mixer_ui.cc:1199
 msgid "Hide All Audio Tracks"
-msgstr "隐藏所有音轨"
+msgstr "隐藏所有音频轨道"
 
 #: editor_routes.cc:480 mixer_ui.cc:1200
 msgid "Show All Audio Busses"
@@ -5631,11 +5786,11 @@ msgstr "隐藏所有MIDI轨"
 
 #: editor_routes.cc:484
 msgid "Show Tracks With Regions Under Playhead"
-msgstr ""
+msgstr "显示指针后面区域的轨道"
 
 #: editor_rulers.cc:211
 msgid "New location marker"
-msgstr "标记的新位置"
+msgstr "新建位置标记"
 
 #: editor_rulers.cc:212
 msgid "Clear all locations"
@@ -5647,7 +5802,7 @@ msgstr "取消隐藏位置"
 
 #: editor_rulers.cc:217
 msgid "New range"
-msgstr ""
+msgstr "新建范围"
 
 #: editor_rulers.cc:218
 msgid "Clear all ranges"
@@ -5659,15 +5814,15 @@ msgstr "取消隐藏范围"
 
 #: editor_rulers.cc:224
 msgid "Make Loop range"
-msgstr ""
+msgstr "设为循环范围"
 
 #: editor_rulers.cc:225
 msgid "Make Punch range"
-msgstr ""
+msgstr "设为切换范围"
 
 #: editor_rulers.cc:230
 msgid "New CD track marker"
-msgstr "新CD音轨标签"
+msgstr "新建CD音轨标签"
 
 #: editor_rulers.cc:235 tempo_dialog.cc:38
 msgid "New Tempo"
@@ -5675,23 +5830,23 @@ msgstr "新节奏"
 
 #: editor_rulers.cc:239 tempo_dialog.cc:296
 msgid "New Meter"
-msgstr "新标尺"
+msgstr "新节拍"
 
 #: editor_snapshots.cc:137
 msgid "Rename Snapshot"
-msgstr ""
+msgstr "重命名快照"
 
 #: editor_snapshots.cc:139
 msgid "New name of snapshot"
-msgstr "快照新名称"
+msgstr "快照的新名称"
 
 #: editor_snapshots.cc:157
 msgid ""
 "Do you really want to remove snapshot \"%1\" ?\n"
 "(which cannot be undone)"
 msgstr ""
-"你确定移除快照 \"%1\"?\n"
-"(不可撤销)"
+"您是否确定移除快照 \"%1\"?\n"
+"(此操作不可撤销)"
 
 #: editor_snapshots.cc:162
 msgid "Remove snapshot"
@@ -5707,7 +5862,7 @@ msgstr "添加节奏标记"
 
 #: editor_tempodisplay.cc:254
 msgid "add meter mark"
-msgstr "添加标尺标记"
+msgstr "添加节拍标记"
 
 #: editor_tempodisplay.cc:287 editor_tempodisplay.cc:315
 msgid "done"
@@ -5722,51 +5877,48 @@ msgid "remove tempo mark"
 msgstr "移除节奏标记"
 
 #: editor_tempodisplay.cc:370
-msgid ""
-"programming error: meter marker canvas item has no marker object pointer!"
-msgstr ""
+msgid "programming error: meter marker canvas item has no marker object pointer!"
+msgstr "程序错误:节拍标记版面条目没有标记对象物体指示!"
 
 #: editor_timefx.cc:68
 msgid "stretch/shrink"
-msgstr ""
+msgstr "延伸/收缩"
 
 #: editor_timefx.cc:129
 msgid "pitch shift"
-msgstr "音调切换"
+msgstr "音高替换"
 
 #: editor_timefx.cc:301
 msgid "timefx cannot be started - thread creation error"
-msgstr ""
-"Protáhnutí času (timefx) nemohlo být provedeno - Při vytváření vlákna došlo "
-"k chybÄ›"
+msgstr "间特效无法启动 - 线程创建错误"
 
 #: engine_dialog.cc:83
 msgid "Device Control Panel"
-msgstr ""
+msgstr "设备控制面板"
 
 #: engine_dialog.cc:84
 msgid "Midi Device Setup"
-msgstr ""
+msgstr "MIDI设备设置"
 
 #: engine_dialog.cc:85 engine_dialog.cc:2097
 msgid "Measure"
-msgstr ""
+msgstr "测量"
 
 #: engine_dialog.cc:86
 msgid "Use results"
-msgstr ""
+msgstr "使用结果"
 
 #: engine_dialog.cc:87
 msgid "Back to settings ... (ignore results)"
-msgstr ""
+msgstr "回到设置…(忽略结果)"
 
 #: engine_dialog.cc:88
 msgid "Calibrate Audio"
-msgstr ""
+msgstr "校正音频"
 
 #: engine_dialog.cc:92
 msgid "Back to settings"
-msgstr ""
+msgstr "回到设置"
 
 #: engine_dialog.cc:111
 msgid ""
@@ -5774,40 +5926,43 @@ msgid ""
 "\n"
 "(This is a build/packaging/system error. It should never happen.)"
 msgstr ""
+"未检测到音频/MIDI后端。 %1 无法运行\n"
+"\n"
+"(这是一个构建/包装/系统错误。它应该永远不会发生。)"
 
 #: engine_dialog.cc:137
 msgid "Latency Measurement Tool"
-msgstr ""
+msgstr "延迟测量工具"
 
 #: engine_dialog.cc:149
 msgid ""
-"<span weight=\"bold\">Turn down the volume on your audio equipment to a very "
-"low level.</span>"
-msgstr ""
+"<span weight=\"bold\">Turn down the volume on your audio equipment to a very low "
+"level.</span>"
+msgstr "<span weight=\"bold\">调低您的音频设备音量到一个非常低的水平。</span>"
 
 #: engine_dialog.cc:158
 msgid "Select two channels below and connect them using a cable."
-msgstr ""
+msgstr "选择下面两个声道并和使用线条连接它们。"
 
 #: engine_dialog.cc:163
 msgid "Output channel"
-msgstr ""
+msgstr "输出声道"
 
 #: engine_dialog.cc:171
 msgid "Input channel"
-msgstr ""
+msgstr "输入声道"
 
 #: engine_dialog.cc:206
 msgid "Once the channels are connected, click the \"Measure\" button."
-msgstr ""
+msgstr "一旦声道已连接好,单击“测量”按钮。"
 
 #: engine_dialog.cc:213
 msgid "When satisfied with the results, click the \"Use results\" button."
-msgstr ""
+msgstr "如果得到了令人满意的结果,请点击“使用结果”按钮。"
 
 #: engine_dialog.cc:228 engine_dialog.cc:2217 engine_dialog.cc:2227
 msgid "No measurement results yet"
-msgstr ""
+msgstr "还没有测量结果"
 
 #: engine_dialog.cc:238 route_params_ui.cc:106
 msgid "Latency"
@@ -5815,36 +5970,36 @@ msgstr "延迟"
 
 #: engine_dialog.cc:372
 msgid "Audio System:"
-msgstr ""
+msgstr "音频系统:"
 
 #: engine_dialog.cc:409
 msgid "Driver:"
-msgstr "驱动:"
+msgstr "驱动:"
 
 #: engine_dialog.cc:415
 msgid "Device:"
-msgstr ""
+msgstr "设备:"
 
 #: engine_dialog.cc:420 engine_dialog.cc:519 sfdb_ui.cc:153 sfdb_ui.cc:348
 #: sfdb_ui.cc:353
 msgid "Sample rate:"
-msgstr "采样率:"
+msgstr "采样率:"
 
 #: engine_dialog.cc:426 engine_dialog.cc:526
 msgid "Buffer size:"
-msgstr "缓冲区大小:"
+msgstr "缓冲区大小:"
 
 #: engine_dialog.cc:444
 msgid "Input Channels:"
-msgstr ""
+msgstr "输入声道:"
 
 #: engine_dialog.cc:457
 msgid "Output Channels:"
-msgstr ""
+msgstr "输出声道:"
 
 #: engine_dialog.cc:469
 msgid "Hardware input latency:"
-msgstr "硬件输入延迟:"
+msgstr "硬件输入延迟:"
 
 #: engine_dialog.cc:472 engine_dialog.cc:485
 msgid "samples"
@@ -5852,17 +6007,19 @@ msgstr "采样"
 
 #: engine_dialog.cc:482
 msgid "Hardware output latency:"
-msgstr "硬件输出延迟:"
+msgstr "硬件输出延迟:"
 
 #: engine_dialog.cc:493
 msgid "MIDI System:"
-msgstr ""
+msgstr "MIDI系统:"
 
 #: engine_dialog.cc:511
 msgid ""
 "The %1 audio backend was configured and started externally.\n"
 "This limits your control over it."
 msgstr ""
+"音频后端已配置并已在外部启动。\n"
+"这限制了您对它的控制力。"
 
 #: engine_dialog.cc:564
 msgid ""
@@ -5870,6 +6027,9 @@ msgid ""
 "\n"
 "Latency calibration requires a working audio interface."
 msgstr ""
+"启动或链接音频引擎失败。\n"
+"\n"
+"延迟校准需要有一个音频接口在工作。"
 
 #: engine_dialog.cc:570
 msgid ""
@@ -5877,10 +6037,13 @@ msgid ""
 "\n"
 "Latency calibration requires playback and capture"
 msgstr ""
+"您已选择的音频配置仅供回放或仅供捕获。\n"
+"\n"
+"延迟校准需要回放和捕捉"
 
 #: engine_dialog.cc:651
 msgid "MIDI Devices"
-msgstr ""
+msgstr "MIDI 设备"
 
 #: engine_dialog.cc:657
 msgid "Device"
@@ -5888,21 +6051,20 @@ msgstr "设备"
 
 #: engine_dialog.cc:659
 msgid "Hardware Latencies"
-msgstr ""
+msgstr "硬件延迟"
 
 #: engine_dialog.cc:700
 msgid "Calibrate"
-msgstr ""
+msgstr "æ ¡æ­£"
 
 #: engine_dialog.cc:800
 msgid "all available channels"
-msgstr ""
+msgstr "所有可用的声道"
 
 #: engine_dialog.cc:1039 latency_gui.cc:39
 msgid "sample"
 msgid_plural "samples"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "采样"
 
 #: engine_dialog.cc:1090
 #, c-format
@@ -5911,109 +6073,109 @@ msgstr ""
 
 #: engine_dialog.cc:1593
 msgid "Could not start backend engine %1"
-msgstr ""
+msgstr "无法启动后端引擎 %1"
 
 #: engine_dialog.cc:1644
 msgid "Cannot set driver to %1"
-msgstr ""
+msgstr "无法设置驱动到 %1"
 
 #: engine_dialog.cc:1648
 msgid "Cannot set device name to %1"
-msgstr ""
+msgstr "无法设置设备名称到 %1"
 
 #: engine_dialog.cc:1652
 msgid "Cannot set sample rate to %1"
-msgstr ""
+msgstr "无法设置采样率到 %1"
 
 #: engine_dialog.cc:1656
 msgid "Cannot set buffer size to %1"
-msgstr ""
+msgstr "无法设置缓冲区大小到 %1"
 
 #: engine_dialog.cc:1662
 msgid "Cannot set input channels to %1"
-msgstr ""
+msgstr "无法设置输入声道到 %1"
 
 #: engine_dialog.cc:1666
 msgid "Cannot set output channels to %1"
-msgstr ""
+msgstr "无法设置输出声道到 %1"
 
 #: engine_dialog.cc:1672
 msgid "Cannot set input latency to %1"
-msgstr ""
+msgstr "无法设置输入延迟到 %1"
 
 #: engine_dialog.cc:1676
 msgid "Cannot set output latency to %1"
-msgstr ""
+msgstr "无法设置输出延迟到 %1"
 
 #: engine_dialog.cc:1955 engine_dialog.cc:2014
 msgid "No signal detected "
-msgstr ""
+msgstr "未检测到信号"
 
 #: engine_dialog.cc:1968 engine_dialog.cc:2022 port_insert_ui.cc:70
 #: port_insert_ui.cc:98
 msgid "Disconnected from audio engine"
-msgstr "与音频引擎断开连接"
+msgstr "与音频引擎已断开连接"
 
 #: engine_dialog.cc:1977 engine_dialog.cc:2030
 msgid "Detected roundtrip latency: "
-msgstr ""
+msgstr "检测到往返延迟:"
 
 #: engine_dialog.cc:1979 engine_dialog.cc:2032
 msgid "Systemic latency: "
-msgstr ""
+msgstr "系统延迟:"
 
 #: engine_dialog.cc:1986
 msgid "(signal detection error)"
-msgstr ""
+msgstr "(信号检测错误)"
 
 #: engine_dialog.cc:1992
 msgid "(inverted - bad wiring)"
-msgstr ""
+msgstr "(反向 - 损坏接线)"
 
 #: engine_dialog.cc:2039
 msgid "(averaging)"
-msgstr ""
+msgstr "(平均)"
 
 #: engine_dialog.cc:2045
 msgid "(too large jitter)"
-msgstr ""
+msgstr "(振幅过大)"
 
 #: engine_dialog.cc:2049
 msgid "(large jitter)"
-msgstr ""
+msgstr "(大振幅)"
 
 #: engine_dialog.cc:2061
 msgid "Timeout - large MIDI jitter."
-msgstr ""
+msgstr "超时 - 大MIDI振幅。"
 
 #: engine_dialog.cc:2077 port_insert_ui.cc:134
 msgid "Detecting ..."
-msgstr "检测中..."
+msgstr "检测中…"
 
 #: engine_dialog.cc:2171
 msgid "Disconnect from %1"
-msgstr ""
+msgstr "与 %1 失去连接"
 
 #: engine_dialog.cc:2175 mixer_strip.cc:1522 route_group_dialog.cc:45
 #: route_time_axis.cc:841
 msgid "Active"
-msgstr "启用(Active)"
+msgstr "激活"
 
 #: engine_dialog.cc:2185
 msgid "Connect to %1"
-msgstr ""
+msgstr "连接到 %1"
 
 #: engine_dialog.cc:2190
 msgid "Inactive"
-msgstr ""
+msgstr "未激活"
 
 #: export_channel_selector.cc:45 sfdb_ui.cc:151
 msgid "Channels:"
-msgstr "通道:"
+msgstr "声道:"
 
 #: export_channel_selector.cc:46
 msgid "Split to mono files"
-msgstr "剪切到单音轨文件"
+msgstr "拆分到单声道文件"
 
 #: export_channel_selector.cc:182
 msgid "Bus or Track"
@@ -6021,33 +6183,32 @@ msgstr "总线或音轨"
 
 #: export_channel_selector.cc:459
 msgid "Region contents without fades nor region gain (channels: %1)"
-msgstr ""
+msgstr "区域内容没有淡化也没有区域增益(声道: %1)"
 
 #: export_channel_selector.cc:463
 msgid "Region contents with fades and region gain (channels: %1)"
-msgstr ""
+msgstr "区域内容带有淡化和区域增益(声道: %1)"
 
 #: export_channel_selector.cc:467
 msgid "Track output (channels: %1)"
-msgstr "音轨输出 (声道: %1)"
+msgstr "音轨输出 (声道: %1)"
 
 #: export_channel_selector.cc:536
 msgid "Export region contents"
-msgstr ""
+msgstr "导出区域内容"
 
 #: export_channel_selector.cc:537
 msgid "Export track output"
-msgstr ""
+msgstr "导出音轨输出"
 
 #: export_dialog.cc:46
 msgid ""
-"<span color=\"#ffa755\">Some already existing files will be overwritten.</"
-"span>"
-msgstr "<span color=\"#ffa755\">一些已存在的文件将会被重新写入.</span>"
+"<span color=\"#ffa755\">Some already existing files will be overwritten.</span>"
+msgstr "<span color=\"#ffa755\">一些已存在的文件将会被写入覆盖。</span>"
 
 #: export_dialog.cc:47
 msgid "List files"
-msgstr "文件列表"
+msgstr "列表文件"
 
 #: export_dialog.cc:158 export_format_dialog.cc:59
 msgid "File format"
@@ -6067,40 +6228,40 @@ msgid ""
 "Export has been aborted due to an error!\n"
 "See the Log for details."
 msgstr ""
-"有个错误导致导出失败!\n"
-"详情请见日志文件."
+"导出意外中止,因为有个错误!\n"
+"详情请见日志。"
 
 #: export_dialog.cc:251
 msgid "Files that will be overwritten"
-msgstr "将会被重新写入的文件"
+msgstr "将会被被写入覆盖的文件"
 
 #: export_dialog.cc:296
 msgid "Export initialization failed: %1"
-msgstr ""
+msgstr "导出初始化失败: %1"
 
 #: export_dialog.cc:306
 msgid "Stop Export"
-msgstr "停止导出"
+msgstr "Stop Export 停止导出"
 
 #: export_dialog.cc:327
 msgid "export"
-msgstr ""
+msgstr "导出"
 
 #: export_dialog.cc:346
 msgid "Normalizing '%3' (timespan %1 of %2)"
-msgstr ""
+msgstr "规范化 '%3' (时间跨度 %1 的 %2)"
 
 #: export_dialog.cc:350
 msgid "Exporting '%3' (timespan %1 of %2)"
-msgstr ""
+msgstr "导出 '%3' (时间跨度 %1 的 %2)"
 
 #: export_dialog.cc:373 export_dialog.cc:375
 msgid "<span color=\"#ffa755\">Error: "
-msgstr "<span color=\"#ffa755\">错误: "
+msgstr "<span color=\"#ffa755\">错误:"
 
 #: export_dialog.cc:385
 msgid "<span color=\"#ffa755\">Warning: "
-msgstr "<span color=\"#ffa755\">警告: "
+msgstr "<span color=\"#ffa755\">警告:"
 
 #: export_dialog.cc:387
 msgid ""
@@ -6108,11 +6269,11 @@ msgid ""
 "<span color=\"#ffa755\">Warning: "
 msgstr ""
 "\n"
-"<span color=\"#ffa755\">警告: "
+"<span color=\"#ffa755\">警告:"
 
 #: export_dialog.cc:411
 msgid "Export Selection"
-msgstr "导出选区"
+msgstr "导出已选择部分"
 
 #: export_dialog.cc:425
 msgid "Export Region"
@@ -6124,11 +6285,11 @@ msgstr "源"
 
 #: export_dialog.cc:450
 msgid "Stem Export"
-msgstr ""
+msgstr "逆向导出"
 
 #: export_file_notebook.cc:39
 msgid "Add another format"
-msgstr ""
+msgstr "添加另一个格式"
 
 #: export_file_notebook.cc:193
 msgid "Format"
@@ -6140,19 +6301,19 @@ msgstr "位置"
 
 #: export_file_notebook.cc:195
 msgid "Upload to Soundcloud"
-msgstr ""
+msgstr "上传到Soundcloud"
 
 #: export_file_notebook.cc:273
 msgid "No format!"
-msgstr ""
+msgstr "不格式化!"
 
 #: export_file_notebook.cc:291
 msgid "Format %1: %2"
-msgstr ""
+msgstr "格式化 %1: %2"
 
 #: export_filename_selector.cc:32
 msgid "Label:"
-msgstr "标签:"
+msgstr "标签:"
 
 #: export_filename_selector.cc:33
 msgid "Session Name"
@@ -6160,38 +6321,37 @@ msgstr "会话名称"
 
 #: export_filename_selector.cc:34
 msgid "Revision:"
-msgstr ""
+msgstr "修订版本:"
 
 #: export_filename_selector.cc:36
 msgid "Folder:"
-msgstr "文件:"
+msgstr "文件夹:"
 
 #: export_filename_selector.cc:37 session_import_dialog.cc:45
-#: transcode_video_dialog.cc:59 video_server_dialog.cc:54
-#: video_server_dialog.cc:56 export_video_dialog.cc:81
-#: export_video_dialog.cc:83
+#: transcode_video_dialog.cc:59 video_server_dialog.cc:54 video_server_dialog.cc:56
+#: export_video_dialog.cc:81 export_video_dialog.cc:83
 msgid "Browse"
 msgstr "浏览"
 
 #: export_filename_selector.cc:41
 msgid "<i>Build filename(s) from these components:</i>"
-msgstr ""
+msgstr "<i>从这些组件构建文件名:</i>"
 
 #: export_filename_selector.cc:212
-msgid ""
-"<small><i>Sorry, no example filename can be shown at the moment</i></small>"
-msgstr ""
+msgid "<small><i>Sorry, no example filename can be shown at the moment</i></small>"
+msgstr "<small><i>对不起,目前没有例子文件名可以显示</i></small>"
 
 #: export_filename_selector.cc:214
 msgid "<small><i>Current (approximate) filename: \"%1\"</i></small>"
-msgstr ""
+msgstr "<small><i>当前(近似)文件名: ”%1“</i></small>"
 
 #: export_filename_selector.cc:250 export_filename_selector.cc:336
 msgid ""
 "%1: this is only the directory/folder name, not the filename.\n"
-"The filename will be chosen from the information just above the folder "
-"selector."
+"The filename will be chosen from the information just above the folder selector."
 msgstr ""
+"%1:这仅是目录/文件夹名称,不是文件名\n"
+"将会从刚才上面的文件选择器信息里选出文件名。"
 
 #: export_filename_selector.cc:322
 msgid "Choose export folder"
@@ -6199,41 +6359,43 @@ msgstr "选择导出文件夹"
 
 #: export_format_dialog.cc:31
 msgid "New Export Format Profile"
-msgstr "新的导出格式属性"
+msgstr "新建导出格式配置文件"
 
 #: export_format_dialog.cc:31
 msgid "Edit Export Format Profile"
-msgstr "编辑导出格式属性"
+msgstr "编辑导出格式配置文件"
 
 #: export_format_dialog.cc:38
 msgid "Label: "
-msgstr "标签:"
+msgstr "标签:"
 
 #: export_format_dialog.cc:41 normalize_dialog.cc:42
 msgid "Normalize to:"
-msgstr "标准化到:"
+msgstr "规范化到:"
 
 #: export_format_dialog.cc:46
 msgid "Trim silence at start"
-msgstr "在开始时修剪沉默"
+msgstr "在起点修剪无声"
 
 #: export_format_dialog.cc:47
 msgid "Add silence at start:"
-msgstr "在开始时添加沉默:"
+msgstr "在起点添加无声:"
 
 #: export_format_dialog.cc:50
 msgid "Trim silence at end"
-msgstr "在末尾修剪沉默"
+msgstr "在终点修剪无声"
 
 #: export_format_dialog.cc:51
 msgid "Add silence at end:"
-msgstr "在末尾添加沉默:"
+msgstr "在终点添加无声:"
 
 #: export_format_dialog.cc:54
 msgid ""
 "Command to run post-export\n"
 "(%f=full path & filename, %d=directory, %b=basename):"
 msgstr ""
+"运行后置-导出的命令\n"
+"(%f=完整路径和文件名,%d=目录,%b=基本名称):"
 
 #: export_format_dialog.cc:57
 msgid "Compatibility"
@@ -6245,19 +6407,21 @@ msgstr "质量"
 
 #: export_format_dialog.cc:61
 msgid "Sample rate conversion quality:"
-msgstr "采样率转换质量"
+msgstr "采样率转换质量:"
 
 #: export_format_dialog.cc:68
 msgid "Dithering"
 msgstr "抖动"
 
+# CUE  cuesheet 是指光盘映像(镜像)辅助文件或称标记文件
 #: export_format_dialog.cc:70
 msgid "Create CUE file for disk-at-once CD/DVD creation"
-msgstr ""
+msgstr "为创建一次性CD/DVD光盘而创建CUE文件"
 
+# 目录数据 (Table of Content,TOC)
 #: export_format_dialog.cc:71
 msgid "Create TOC file for disk-at-once CD/DVD creation"
-msgstr ""
+msgstr "为创建一次性CD/DVD光盘而创建TOC文件"
 
 #: export_format_dialog.cc:73
 msgid "Tag file with session's metadata"
@@ -6265,15 +6429,15 @@ msgstr "会话元数据的标签文件"
 
 #: export_format_dialog.cc:470
 msgid "Best (sinc)"
-msgstr "最好(同步)"
+msgstr "最佳(sinc)"
 
 #: export_format_dialog.cc:475
 msgid "Medium (sinc)"
-msgstr "中(同步)"
+msgstr "中等(sinc)"
 
 #: export_format_dialog.cc:480
 msgid "Fast (sinc)"
-msgstr "快(同步)"
+msgstr "快速(sinc)"
 
 #: export_format_dialog.cc:490
 msgid "Zero order hold"
@@ -6285,19 +6449,19 @@ msgstr "线性编码选项"
 
 #: export_format_dialog.cc:911
 msgid "Ogg Vorbis options"
-msgstr "Ogg Vorbis选项"
+msgstr "Ogg Vorbis 选项"
 
 #: export_format_dialog.cc:922
 msgid "FLAC options"
-msgstr "FLAC选项"
+msgstr "FLAC 选项"
 
 #: export_format_dialog.cc:939
 msgid "Broadcast Wave options"
-msgstr "广播Wave (Broadcast Wave) 选项"
+msgstr "广播Wave选项"
 
 #: export_format_selector.cc:136
 msgid "Do you really want to remove the format?"
-msgstr ""
+msgstr "您是否真的要移除这个格式?"
 
 #: export_preset_selector.cc:28
 msgid "Preset"
@@ -6308,16 +6472,16 @@ msgid ""
 "The selected preset did not load successfully!\n"
 "Perhaps it references a format that has been removed?"
 msgstr ""
-"被选中的预设载入不成功!\n"
-"是不是其引用的的格式被删除了?"
+"被选中的预设载入失败!\n"
+"也许它引用了一个已被删除的格式?"
 
 #: export_preset_selector.cc:156
 msgid "Do you really want to remove this preset?"
-msgstr ""
+msgstr "您是否真的要移除这个预设?"
 
 #: export_timespan_selector.cc:46
 msgid "Show Times as:"
-msgstr "显示时间:"
+msgstr "显示时间为:"
 
 #: export_timespan_selector.cc:53 processor_box.cc:2466
 msgid "Select All"
@@ -6333,15 +6497,15 @@ msgstr "范围"
 
 #: sfdb_freesound_mootcher.cc:189 sfdb_freesound_mootcher.cc:324
 msgid "curl error %1 (%2)"
-msgstr ""
+msgstr "回旋错误 %1 (%2)"
 
 #: sfdb_freesound_mootcher.cc:266
 msgid "getSoundResourceFile: There is no valid root in the xml file"
-msgstr ""
+msgstr "获取声音资源文件:在 xml 文件里没有正确的根"
 
 #: sfdb_freesound_mootcher.cc:271
 msgid "getSoundResourceFile: root = %1, != response"
-msgstr ""
+msgstr "获取声音资源文件:根 = %1, ! = 响应"
 
 #: sfdb_freesound_mootcher.cc:410 rc_option_editor.cc:1824
 msgid "%1"
@@ -6353,11 +6517,11 @@ msgstr ""
 
 #: gain_meter.cc:147 gain_meter.cc:958
 msgid "Fader automation mode"
-msgstr ""
+msgstr "淡化器自动模式"
 
 #: gain_meter.cc:148 gain_meter.cc:959
 msgid "Fader automation type"
-msgstr ""
+msgstr "淡化器自动类型"
 
 #: gain_meter.cc:157 gain_meter.cc:829 panner_ui.cc:179 panner_ui.cc:639
 msgid "Abs"
@@ -6382,15 +6546,15 @@ msgstr "<span size=\"large\">预设</span>"
 
 #: generic_pluginui.cc:97
 msgid "Manual"
-msgstr ""
+msgstr "手册"
 
 #: generic_pluginui.cc:106
 msgid "All Automation"
-msgstr ""
+msgstr "全部自动化"
 
 #: generic_pluginui.cc:250
 msgid "Switches"
-msgstr ""
+msgstr "转换"
 
 #: generic_pluginui.cc:260 generic_pluginui.cc:436 processor_box.cc:2440
 msgid "Controls"
@@ -6398,19 +6562,19 @@ msgstr "控制"
 
 #: generic_pluginui.cc:293
 msgid "Plugin Editor: could not build control element for port %1"
-msgstr "插件编辑器: 无法为端口 %1 建立控制元素"
+msgstr "插件编辑器:无法为端口 %1 建立控制元素"
 
 #: generic_pluginui.cc:318
 msgid "Plugin Editor: no control for property %1"
-msgstr ""
+msgstr "插件编辑器:无法控制 %1 属性"
 
 #: generic_pluginui.cc:324
 msgid "Plugin Editor: could not build control element for property %1"
-msgstr ""
+msgstr "插件编辑器:无法为 %1 属性建立控制元素"
 
 #: generic_pluginui.cc:468
 msgid "Meters"
-msgstr ""
+msgstr "节拍"
 
 #: generic_pluginui.cc:490
 msgid "Automation control"
@@ -6422,11 +6586,11 @@ msgstr ""
 
 #: global_port_matrix.cc:158
 msgid "Audio Connection Manager"
-msgstr "音频连结管理"
+msgstr "音频连结管理器"
 
 #: global_port_matrix.cc:161
 msgid "MIDI Connection Manager"
-msgstr "MIDI连接管理"
+msgstr "MIDI连接管理器"
 
 #: global_port_matrix.cc:201 io_selector.cc:211 mixer_strip.cc:793
 #: mixer_strip.cc:894
@@ -6435,109 +6599,111 @@ msgstr "取消连接"
 
 #: global_port_matrix.cc:207 io_selector.cc:217
 msgid "port"
-msgstr ""
+msgstr "端口"
 
 #: group_tabs.cc:312
 msgid "Selection..."
-msgstr ""
+msgstr "已选择部分…"
 
 #: group_tabs.cc:313
 msgid "Record Enabled..."
-msgstr "启用录音..."
+msgstr "启用录制…"
 
 #: group_tabs.cc:314
 msgid "Soloed..."
-msgstr "独奏..."
+msgstr "独奏…"
 
 #: group_tabs.cc:320
 msgid "Create New Group ..."
-msgstr ""
+msgstr "创建新的分组…"
 
 #: group_tabs.cc:321
 msgid "Create New Group From"
-msgstr ""
+msgstr "创建新的分组来自于"
 
 #: group_tabs.cc:324
 msgid "Edit Group..."
-msgstr ""
+msgstr "编辑分组…"
 
 #: group_tabs.cc:325
 msgid "Collect Group"
-msgstr ""
+msgstr "收集分组"
 
 #: group_tabs.cc:326
 msgid "Remove Group"
-msgstr ""
+msgstr "移除分组"
 
 #: group_tabs.cc:329
 msgid "Remove Subgroup Bus"
-msgstr ""
+msgstr "移除次级分组总线"
 
 #: group_tabs.cc:331
 msgid "Add New Subgroup Bus"
-msgstr ""
+msgstr "添加新的次级分组总线"
 
 #: group_tabs.cc:333
 msgid "Add New Aux Bus (pre-fader)"
-msgstr ""
+msgstr "添加新的辅助总线(前置淡化)"
 
 #: group_tabs.cc:334
 msgid "Add New Aux Bus (post-fader)"
-msgstr ""
+msgstr "添加新的辅助总线(后置淡化)"
 
 #: group_tabs.cc:340
 msgid "Enable All Groups"
-msgstr ""
+msgstr "启用所有分组"
 
 #: group_tabs.cc:341
 msgid "Disable All Groups"
-msgstr ""
+msgstr "禁用所有分组"
 
 #: insert_time_dialog.cc:46
 msgid "Time to insert:"
-msgstr ""
+msgstr "要插入的时间位置:"
 
 #: insert_time_dialog.cc:54
 msgid "Intersected regions should:"
-msgstr ""
+msgstr "相交的区域应该:"
 
 #: insert_time_dialog.cc:57
 msgid "stay in position"
-msgstr ""
+msgstr "停留在原位"
 
 #: insert_time_dialog.cc:58
 msgid "move"
-msgstr ""
+msgstr "移动"
 
 #: insert_time_dialog.cc:59
 msgid "be split"
-msgstr ""
+msgstr "拆分"
 
 #: insert_time_dialog.cc:65
 msgid "Insert time on all the track's playlists"
-msgstr ""
+msgstr "在所有的音轨播放列表上插入时间"
 
 #: insert_time_dialog.cc:68
 msgid "Move glued regions"
-msgstr ""
+msgstr "移动被粘连的区域"
 
 #: insert_time_dialog.cc:70
 msgid "Move markers"
-msgstr ""
+msgstr "移动标记"
 
 #: insert_time_dialog.cc:73
 msgid "Move glued markers"
-msgstr ""
+msgstr "移动被粘连的标记"
 
 #: insert_time_dialog.cc:78
 msgid "Move locked markers"
-msgstr ""
+msgstr "移动被锁定的标记"
 
 #: insert_time_dialog.cc:83
 msgid ""
 "Move tempo and meter changes\n"
 "<i>(may cause oddities in the tempo map)</i>"
 msgstr ""
+"移动节奏和节拍变化\n"
+"(也许会在节奏图中引发异常)"
 
 #: insert_time_dialog.cc:91
 msgid "Insert time"
@@ -6545,15 +6711,15 @@ msgstr "插入时间"
 
 #: instrument_selector.cc:62
 msgid "-none-"
-msgstr ""
+msgstr "— 无 —"
 
 #: interthread_progress_window.cc:103
 msgid "Importing file: %1 of %2"
-msgstr "导入文件: %2 的 %1"
+msgstr "导入文件: %2 的 %1"
 
 #: io_selector.cc:221
 msgid "I/O selector"
-msgstr "输入/输出 选择器"
+msgstr "输入/输出选择器"
 
 #: io_selector.cc:266
 msgid "%1 input"
@@ -6565,15 +6731,15 @@ msgstr "%1 输出"
 
 #: keyboard.cc:70
 msgid "your own"
-msgstr ""
+msgstr "您自己的"
 
 #: keyboard.cc:133 keyboard.cc:157
 msgid "Default keybindings not found - %1 will be hard to use!"
-msgstr ""
+msgstr "找不到默认的按键绑定—— %1 将很难使用!"
 
 #: keyboard.cc:136
 msgid "Key bindings file \"%1\" not found. Default bindings used instead"
-msgstr ""
+msgstr "找不到按键绑定文件 \"%1\"。使用默认绑定替代。"
 
 #: keyeditor.cc:54
 msgid "Remove shortcut"
@@ -6581,7 +6747,7 @@ msgstr "移除快捷键"
 
 #: keyeditor.cc:63
 msgid "Action"
-msgstr "动作"
+msgstr "操作"
 
 #: keyeditor.cc:64
 msgid "Shortcut"
@@ -6589,45 +6755,44 @@ msgstr "快捷键"
 
 #: keyeditor.cc:84
 msgid "Select an action, then press the key(s) to (re)set its shortcut"
-msgstr "选择一个动作, 然后点击按键来(重)设置快捷键"
+msgstr "选择一个操作,然后按下按键来(重新)设置快捷键"
 
 #: keyeditor.cc:98
 msgid "Reset Bindings to Defaults"
-msgstr ""
+msgstr "重置为默认绑定"
 
 #: keyeditor.cc:263
 msgid "Main_menu"
-msgstr ""
+msgstr "主菜单"
 
 #: keyeditor.cc:265
 msgid "redirectmenu"
-msgstr ""
+msgstr "重定向菜单"
 
 #: keyeditor.cc:267
 msgid "Editor_menus"
-msgstr ""
+msgstr "编辑器菜单"
 
 #: keyeditor.cc:269
 msgid "RegionList"
-msgstr ""
+msgstr "区域列表"
 
 #: keyeditor.cc:271
 msgid "ProcessorMenu"
-msgstr ""
+msgstr "处理器菜单"
 
 #: latency_gui.cc:40
 msgid "msec"
-msgstr ""
+msgstr "毫秒"
 
 #: latency_gui.cc:41
 msgid "period"
-msgstr ""
+msgstr "周期"
 
 #: latency_gui.cc:55
 msgid "%1 sample"
 msgid_plural "%1 samples"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%1 采样"
 
 #: latency_gui.cc:72 panner_ui.cc:409
 msgid "Reset"
@@ -6635,7 +6800,7 @@ msgstr "预设"
 
 #: latency_gui.cc:149 rhythm_ferret.cc:273 sfdb_ui.cc:1912
 msgid "programming error: %1 (%2)"
-msgstr "程序错误: %1 (%2)"
+msgstr "程序错误: %1 (%2)"
 
 #: location_ui.cc:52 location_ui.cc:54
 msgid "Use PH"
@@ -6643,75 +6808,75 @@ msgstr "使用 PH"
 
 #: location_ui.cc:59
 msgid "Glue"
-msgstr ""
+msgstr "粘连"
 
 #: location_ui.cc:87
 msgid "Performer:"
-msgstr ""
+msgstr "演奏者:"
 
 #: location_ui.cc:88
 msgid "Composer:"
-msgstr ""
+msgstr "作曲家:"
 
 #: location_ui.cc:90
 msgid "Pre-Emphasis"
-msgstr ""
+msgstr "预加重"
 
 #: location_ui.cc:317
 msgid "Remove this range"
-msgstr ""
+msgstr "移除这个范围"
 
 #: location_ui.cc:318
 msgid "Start time - middle click to locate here"
-msgstr ""
+msgstr "起点时间——鼠标中键点击放置在此处"
 
 #: location_ui.cc:319
 msgid "End time - middle click to locate here"
-msgstr ""
+msgstr "终点时间——鼠标中键点击放置在此处"
 
 #: location_ui.cc:322
 msgid "Set range start from playhead location"
-msgstr ""
+msgstr "从指针位置设置范围起点"
 
 #: location_ui.cc:323
 msgid "Set range end from playhead location"
-msgstr ""
+msgstr "从指针位置设置范围终点"
 
 #: location_ui.cc:327
 msgid "Remove this marker"
-msgstr ""
+msgstr "移除这个标记"
 
 #: location_ui.cc:328
 msgid "Position - middle click to locate here"
-msgstr ""
+msgstr "位置——鼠标中键点击放置在此处"
 
 #: location_ui.cc:330
 msgid "Set marker time from playhead location"
-msgstr ""
+msgstr "从指针位置设置标记时间"
 
 #: location_ui.cc:499
 msgid "You cannot put a CD marker at the start of the session"
-msgstr "无法在会话开始放置CD标记"
+msgstr "您不能在会话起点处放置CD标记"
 
 #: location_ui.cc:725
 msgid "New Marker"
-msgstr "新标记"
+msgstr "新建标记"
 
 #: location_ui.cc:726
 msgid "New Range"
-msgstr "新范围"
+msgstr "新建范围"
 
 #: location_ui.cc:739
 msgid "<b>Loop/Punch Ranges</b>"
-msgstr "<b>循环/Punch 范围</b>"
+msgstr "<b>循环/切换范围</b>"
 
 #: location_ui.cc:764
 msgid "<b>Markers (Including CD Index)</b>"
-msgstr "<b>标记(包括CD索引)</b>"
+msgstr "<b>标记(包括CD索引)</b>"
 
 #: location_ui.cc:799
 msgid "<b>Ranges (Including CD Track Ranges)</b>"
-msgstr "<b>范围(包括CD轨道区间)</b>"
+msgstr "<b>范围(包括CD音轨范围)</b>"
 
 #: location_ui.cc:1042
 msgid "add range marker"
@@ -6719,11 +6884,11 @@ msgstr "添加范围标记"
 
 #: main.cc:82
 msgid "%1 could not connect to the audio backend."
-msgstr ""
+msgstr "%1无法连接到音频后端。"
 
 #: main.cc:107 main.cc:123
 msgid "The audio backend (%1) has failed, or terminated"
-msgstr ""
+msgstr "音频后端(%1)失效或者中止。"
 
 #: main.cc:110
 msgid ""
@@ -6733,80 +6898,87 @@ msgid ""
 "\n"
 "Click OK to exit %1."
 msgstr ""
+"%2 意外退出,且没有通知 %1 。\n"
+"\n"
+"这可能是由于错误配置或者定向到错误 %2 内部错误。\n"
+"点击 OK 退出 %1。"
 
 #: main.cc:124
 msgid "%2 exited unexpectedly, and without notifying %1."
-msgstr ""
+msgstr "%2 exited unexpectedly, and without notifying %1."
 
 #: main.cc:219
 msgid ""
 "\n"
 "   %1 could not understand your command line      "
 msgstr ""
+"\n"
+"   %1 无法识别您的命令行      "
 
 #: main.cc:221
 msgid "An error was encountered while launching %1"
-msgstr ""
+msgstr "启动 %1 时遇到一个意外错误"
 
 #: main.cc:310
 msgid " (built using "
-msgstr ""
+msgstr "(构建使用 "
 
 #: main.cc:313
 msgid " and GCC version "
-msgstr ""
+msgstr "和 GCC 版本 "
 
 #: main.cc:323
 msgid "Copyright (C) 1999-2012 Paul Davis"
-msgstr ""
+msgstr " 版权 (C) 1999-2012 Paul Davis"
 
 #: main.cc:324
 msgid ""
-"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
-"Baker, Robin Gareus"
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, "
+"Robin Gareus"
 msgstr ""
+"部分版权 (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, Robin Gareus"
 
 #: main.cc:326
 msgid "%1 comes with ABSOLUTELY NO WARRANTY"
-msgstr ""
+msgstr "%1 绝对不附带任何担保"
 
 #: main.cc:327
 msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-msgstr ""
+msgstr " 甚至不包括可销售性质和适用于任何特定目的的保证。"
 
 #: main.cc:328
 msgid "This is free software, and you are welcome to redistribute it "
-msgstr ""
+msgstr "这是自由软件,且欢迎您分发推广它,"
 
 #: main.cc:329
 msgid "under certain conditions; see the source for copying conditions."
-msgstr ""
+msgstr "在一定条件下;请参阅复制协议的源文件。"
 
 #: main.cc:334
 msgid "could not initialize %1."
-msgstr "无法初始化 %1."
+msgstr "无法初始化 %1 。"
 
 #: main.cc:344
 msgid "Cannot xinstall SIGPIPE error handler"
-msgstr ""
+msgstr "无法安装卸载 SIGPIPE 错误处理程序"
 
 #: main.cc:351
 msgid "could not create %1 GUI"
-msgstr ""
+msgstr "无法创建  %1 图形用户界面"
 
 #: main_clock.cc:52
 msgid "Display delta to edit cursor"
-msgstr ""
+msgstr "显示次级以编辑游标"
 
 #: marker.cc:273
 msgid "MarkerText"
-msgstr ""
+msgstr "标记文本"
 
 #: midi_channel_selector.cc:161 midi_channel_selector.cc:400
-#: midi_channel_selector.cc:436 rc_option_editor.cc:1573
-#: rc_option_editor.cc:2203 sfdb_ui.cc:665
+#: midi_channel_selector.cc:436 rc_option_editor.cc:1573 rc_option_editor.cc:2203
+#: sfdb_ui.cc:665
 msgid "None"
-msgstr ""
+msgstr "æ— "
 
 #: midi_channel_selector.cc:165 midi_channel_selector.cc:405
 #: midi_channel_selector.cc:441
@@ -6815,171 +6987,171 @@ msgstr "反转"
 
 #: midi_channel_selector.cc:169
 msgid "Force"
-msgstr ""
+msgstr "强制"
 
 #: midi_channel_selector.cc:328 midi_channel_selector.cc:370
 msgid "MIDI Channel Control"
-msgstr ""
+msgstr "MIDI 声道控制"
 
 #: midi_channel_selector.cc:330
 msgid "Playback all channels"
-msgstr ""
+msgstr "回放所有声道"
 
 #: midi_channel_selector.cc:331
 msgid "Play only selected channels"
-msgstr ""
+msgstr "仅播放已选中的声道"
 
 #: midi_channel_selector.cc:332
 msgid "Use a single fixed channel for all playback"
-msgstr ""
+msgstr "所有回放使用一个单独固定的声道"
 
 #: midi_channel_selector.cc:333
 msgid "Record all channels"
-msgstr ""
+msgstr "录制所有声道"
 
 #: midi_channel_selector.cc:334
 msgid "Record only selected channels"
-msgstr ""
+msgstr "仅录制已选中的声道"
 
 #: midi_channel_selector.cc:335
 msgid "Force all channels to 1 channel"
-msgstr ""
+msgstr "强制所有声道为 1 声道"
 
 #: midi_channel_selector.cc:376
 msgid "Inbound"
-msgstr ""
+msgstr "进场"
 
 #: midi_channel_selector.cc:396
 msgid "Click to enable recording all channels"
-msgstr ""
+msgstr "点击启用录制所有声道"
 
 #: midi_channel_selector.cc:401
 msgid "Click to disable recording all channels"
-msgstr ""
+msgstr "点击禁用录制所有声道"
 
 #: midi_channel_selector.cc:406
 msgid "Click to invert currently selected recording channels"
-msgstr ""
+msgstr "点击反转当前已选择的录制声道"
 
 #: midi_channel_selector.cc:413
 msgid "Playback"
-msgstr ""
+msgstr "回放"
 
 #: midi_channel_selector.cc:432
 msgid "Click to enable playback of all channels"
-msgstr ""
+msgstr "点击启用回放所有声道"
 
 #: midi_channel_selector.cc:437
 msgid "Click to disable playback of all channels"
-msgstr ""
+msgstr "点击禁用回放所有声道"
 
 #: midi_channel_selector.cc:442
 msgid "Click to invert current selected playback channels"
-msgstr ""
+msgstr "点击反转当前已选择的回放声道"
 
 #: midi_channel_selector.cc:620
 msgid "Click to toggle playback of channel %1"
-msgstr ""
+msgstr "点击切换回放声道 %1"
 
 #: midi_channel_selector.cc:628
 msgid "Click to force all MIDI channel messages to channel %1"
-msgstr ""
+msgstr "点击强制所有MIDI声道发送信息到声道 %1"
 
 #: midi_channel_selector.cc:718
 msgid "Click to toggle recording of channel %1"
-msgstr ""
+msgstr "点击切换录制声道 %1"
 
 #: midi_channel_selector.cc:726
 msgid "Click to force all recorded channels to %1"
-msgstr ""
+msgstr "点击强制所有已录制声道到 %1"
 
 #: midi_export_dialog.cc:35
 msgid "Export MIDI: %1"
-msgstr ""
+msgstr "导出MIDI: %1"
 
 #: midi_list_editor.cc:56
 msgid "Whole"
-msgstr ""
+msgstr "整体"
 
 #: midi_list_editor.cc:57
 msgid "Half"
-msgstr ""
+msgstr "一半"
 
 #: midi_list_editor.cc:58
 msgid "Triplet"
-msgstr ""
+msgstr "三分之一"
 
 #: midi_list_editor.cc:59
 msgid "Quarter"
-msgstr ""
+msgstr "四分之一"
 
 #: midi_list_editor.cc:60
 msgid "Eighth"
-msgstr ""
+msgstr "八分之一"
 
 #: midi_list_editor.cc:61
 msgid "Sixteenth"
-msgstr ""
+msgstr "十六分之一"
 
 #: midi_list_editor.cc:62
 msgid "Thirty-second"
-msgstr ""
+msgstr "三十二分之一"
 
 #: midi_list_editor.cc:63
 msgid "Sixty-fourth"
-msgstr ""
+msgstr "六十四分之一"
 
 #: midi_list_editor.cc:106
 msgid "Num"
-msgstr ""
+msgstr "数值"
 
 #: midi_list_editor.cc:108
 msgid "Vel"
-msgstr ""
+msgstr "力度"
 
 #: midi_list_editor.cc:216
 msgid "edit note start"
-msgstr ""
+msgstr "编辑音符起点"
 
 #: midi_list_editor.cc:225
 msgid "edit note channel"
-msgstr ""
+msgstr "编辑音符声道"
 
 #: midi_list_editor.cc:235
 msgid "edit note number"
-msgstr ""
+msgstr "编辑音符编号"
 
 #: midi_list_editor.cc:245
 msgid "edit note velocity"
-msgstr ""
+msgstr "编辑音符力度"
 
 #: midi_list_editor.cc:259
 msgid "edit note length"
-msgstr ""
+msgstr "编辑音符长度"
 
 #: midi_list_editor.cc:463
 msgid "insert new note"
-msgstr ""
+msgstr "插入新的音符"
 
 #: midi_list_editor.cc:527
 msgid "delete notes (from list)"
-msgstr ""
+msgstr "删除音符(从列表中)"
 
 #: midi_list_editor.cc:602
 msgid "change note channel"
-msgstr ""
+msgstr "切换音符声道"
 
 #: midi_list_editor.cc:610
 msgid "change note number"
-msgstr ""
+msgstr "切换音符编号"
 
 #: midi_list_editor.cc:620
 msgid "change note velocity"
-msgstr ""
+msgstr "切换音符力度"
 
 #: midi_list_editor.cc:690
 msgid "change note length"
-msgstr ""
+msgstr "切换音符长度"
 
 #: midi_port_dialog.cc:39
 msgid "Add MIDI Port"
@@ -6987,11 +7159,11 @@ msgstr "添加MIDI端口"
 
 #: midi_port_dialog.cc:40
 msgid "Port name:"
-msgstr "端口名称:"
+msgstr "端口名称:"
 
 #: midi_port_dialog.cc:45
 msgid "MidiPortDialog"
-msgstr ""
+msgstr "MIDI端口对话框"
 
 #: midi_region_view.cc:859
 msgid "channel edit"
@@ -6999,35 +7171,35 @@ msgstr "声道编辑"
 
 #: midi_region_view.cc:895
 msgid "velocity edit"
-msgstr ""
+msgstr "力度编辑"
 
 #: midi_region_view.cc:954
 msgid "add note"
-msgstr ""
+msgstr "添加音符"
 
 #: midi_region_view.cc:1885
 msgid "step add"
-msgstr "步增"
+msgstr "步进添加"
 
 #: midi_region_view.cc:1979 midi_region_view.cc:2002
 msgid "alter patch change"
-msgstr ""
+msgstr "更改音色变换"
 
 #: midi_region_view.cc:2038
 msgid "add patch change"
-msgstr ""
+msgstr "添加音色变换"
 
 #: midi_region_view.cc:2060 midi_region_view.cc:2061
 msgid "move patch change"
-msgstr ""
+msgstr "移动音色变换"
 
 #: midi_region_view.cc:2073 midi_region_view.cc:2074
 msgid "delete patch change"
-msgstr "删除"
+msgstr "删除音色变换"
 
 #: midi_region_view.cc:2112
 msgid "delete selection"
-msgstr "删除选取"
+msgstr "删除已选取部分"
 
 #: midi_region_view.cc:2128
 msgid "delete note"
@@ -7043,7 +7215,7 @@ msgstr "改变力度"
 
 #: midi_region_view.cc:3136
 msgid "transpose"
-msgstr ""
+msgstr "变调"
 
 #: midi_region_view.cc:3164
 msgid "change note lengths"
@@ -7059,15 +7231,15 @@ msgstr "改变声道"
 
 #: midi_region_view.cc:3295
 msgid "Bank "
-msgstr ""
+msgstr "库"
 
 #: midi_region_view.cc:3296
 msgid "Program "
-msgstr ""
+msgstr "程序"
 
 #: midi_region_view.cc:3297
 msgid "Channel "
-msgstr ""
+msgstr "声道"
 
 #: midi_region_view.cc:3484
 msgid "paste"
@@ -7075,39 +7247,39 @@ msgstr "粘贴"
 
 #: midi_streamview.cc:185
 msgid "attempt to display MIDI region with no source"
-msgstr ""
+msgstr "尝试显示无来源的 MIDI 区域"
 
 #: midi_streamview.cc:195
 msgid "attempt to display MIDI region with no model"
-msgstr ""
+msgstr "尝试显示无模式的 MIDI 区域"
 
 #: midi_streamview.cc:506
 msgid "failed to create MIDI region"
-msgstr ""
+msgstr "创建 MIDI 区域失败"
 
 #: midi_time_axis.cc:309
 msgid "External MIDI Device"
-msgstr ""
+msgstr "外部 MIDI 设备"
 
 #: midi_time_axis.cc:310
 msgid "External Device Mode"
-msgstr ""
+msgstr "外部设备模式"
 
 #: midi_time_axis.cc:318
 msgid "Chns"
-msgstr ""
+msgstr "声道"
 
 #: midi_time_axis.cc:320
 msgid "Click to edit channel settings"
-msgstr ""
+msgstr "点击编辑声道设置"
 
 #: midi_time_axis.cc:519
 msgid "Show Full Range"
-msgstr "显示所有范围"
+msgstr "显示全部范围"
 
 #: midi_time_axis.cc:524
 msgid "Fit Contents"
-msgstr "放置内容"
+msgstr "匹配内容"
 
 #: midi_time_axis.cc:528
 msgid "Note Range"
@@ -7119,7 +7291,7 @@ msgstr "音符模式"
 
 #: midi_time_axis.cc:530
 msgid "Channel Selector"
-msgstr ""
+msgstr "声道选择器"
 
 #: midi_time_axis.cc:535
 msgid "Color Mode"
@@ -7127,31 +7299,31 @@ msgstr "颜色模式"
 
 #: midi_time_axis.cc:594
 msgid "Bender"
-msgstr ""
+msgstr "滑音器"
 
 #: midi_time_axis.cc:598
 msgid "Pressure"
-msgstr ""
+msgstr "压力"
 
 #: midi_time_axis.cc:610
 msgid "Controllers"
-msgstr ""
+msgstr "控制器 "
 
 #: midi_time_axis.cc:615
 msgid "No MIDI Channels selected"
-msgstr "没有选择MIDI通道"
+msgstr "未选择 MIDI 声道"
 
 #: midi_time_axis.cc:672 midi_time_axis.cc:801
 msgid "Hide all channels"
-msgstr "隐藏所有通道"
+msgstr "隐藏所有声道"
 
 #: midi_time_axis.cc:676 midi_time_axis.cc:805
 msgid "Show all channels"
-msgstr "显示所有通道"
+msgstr "显示所有声道"
 
 #: midi_time_axis.cc:687 midi_time_axis.cc:816
 msgid "Channel %1"
-msgstr "通道 %1"
+msgstr "声道 %1"
 
 #: midi_time_axis.cc:942 midi_time_axis.cc:974
 msgid "Controllers %1-%2"
@@ -7159,23 +7331,23 @@ msgstr "控制器 %1-%2"
 
 #: midi_time_axis.cc:965 midi_time_axis.cc:968
 msgid "Controller %1"
-msgstr ""
+msgstr "控制器 %1"
 
 #: midi_time_axis.cc:991
 msgid "Sustained"
-msgstr "保持"
+msgstr "持续"
 
 #: midi_time_axis.cc:998
 msgid "Percussive"
-msgstr ""
+msgstr "敲击"
 
 #: midi_time_axis.cc:1018
 msgid "Meter Colors"
-msgstr "标尺颜色"
+msgstr "节拍颜色"
 
 #: midi_time_axis.cc:1025
 msgid "Channel Colors"
-msgstr "通道颜色"
+msgstr " 声道颜色"
 
 #: midi_time_axis.cc:1032
 msgid "Track Color"
@@ -7184,15 +7356,15 @@ msgstr "音轨颜色"
 #: midi_time_axis.cc:1606 midi_time_axis.cc:1612 midi_time_axis.cc:1622
 #: midi_time_axis.cc:1628
 msgid "all"
-msgstr ""
+msgstr "所有"
 
 #: midi_time_axis.cc:1609 midi_time_axis.cc:1625
 msgid "some"
-msgstr ""
+msgstr "一些"
 
 #: midi_tracer.cc:48
 msgid "Line history: "
-msgstr ""
+msgstr "线条历史:"
 
 #: midi_tracer.cc:55
 msgid "Auto-Scroll"
@@ -7208,19 +7380,19 @@ msgstr "启用"
 
 #: midi_tracer.cc:58
 msgid "Delta times"
-msgstr ""
+msgstr "次级时间"
 
 #: midi_tracer.cc:71
 msgid "Port:"
-msgstr "端口:"
+msgstr "端口:"
 
 #: midi_velocity_dialog.cc:31
 msgid "New velocity"
-msgstr ""
+msgstr "新建力度"
 
 #: missing_file_dialog.cc:35
 msgid "Missing File"
-msgstr ""
+msgstr "缺失文件"
 
 #: missing_file_dialog.cc:37
 msgid "Select a folder to search"
@@ -7228,7 +7400,7 @@ msgstr "选择一个要搜索的文件夹"
 
 #: missing_file_dialog.cc:38
 msgid "Add chosen folder to search path, and try again"
-msgstr "请添加文件夹的搜索路径,然后再试一次"
+msgstr "请添加已选择的文件夹到搜索路径,然后再试一次"
 
 #: missing_file_dialog.cc:40
 msgid "Stop loading this session"
@@ -7236,7 +7408,7 @@ msgstr "停止载入此会话"
 
 #: missing_file_dialog.cc:41
 msgid "Skip all missing files"
-msgstr "跳过所有丢失的文件"
+msgstr "跳过所有缺失的文件"
 
 #: missing_file_dialog.cc:42
 msgid "Skip this file"
@@ -7261,7 +7433,7 @@ msgstr ""
 "\n"
 "<i>%3</i>\n"
 "\n"
-"在下列任何文件夹:\n"
+"在下列任何文件夹中:\n"
 "\n"
 "<tt>%4</tt>\n"
 "\n"
@@ -7272,170 +7444,172 @@ msgstr "点击选择一个额外的文件夹"
 
 #: missing_plugin_dialog.cc:29
 msgid "Missing Plugins"
-msgstr "丢失插件"
+msgstr "缺失插件"
 
 #: missing_plugin_dialog.cc:33 transcode_video_dialog.cc:60
 msgid "OK"
-msgstr "OK"
+msgstr ""
 
 #: mixer_actor.cc:55
 msgid "Toggle Solo on Mixer-Selected Tracks/Busses"
-msgstr ""
+msgstr "在混音器已选中的音轨/总线上切换独奏"
 
 #: mixer_actor.cc:56
 msgid "Toggle Mute on Mixer-Selected Tracks/Busses"
-msgstr ""
+msgstr "在混音器已选中的音轨/总线上切换静音"
 
 #: mixer_actor.cc:57
 msgid "Toggle Rec-enable on Mixer-Selected Tracks/Busses"
-msgstr ""
+msgstr "在混音器已选中的音轨/总线上切换可录制"
 
 #: mixer_actor.cc:58
 msgid "Decrease Gain on Mixer-Selected Tracks/Busses"
-msgstr ""
+msgstr "在混音器已选中的音轨/总线上减小增益"
 
 #: mixer_actor.cc:59
 msgid "Increase Gain on Mixer-Selected Tracks/Busses"
-msgstr ""
+msgstr "在混音器已选中的音轨/总线上加大增益"
 
 #: mixer_actor.cc:60
 msgid "Set Gain to 0dB on Mixer-Selected Tracks/Busses"
-msgstr ""
+msgstr "在混音器已选中的音轨/总线上设置增益为 0dB"
 
 #: mixer_actor.cc:63
 msgid "Copy Selected Processors"
-msgstr ""
+msgstr "复制已选中的处理器"
 
 #: mixer_actor.cc:64
 msgid "Cut Selected Processors"
-msgstr ""
+msgstr "剪切已选中的处理器"
 
 #: mixer_actor.cc:65
 msgid "Paste Selected Processors"
-msgstr ""
+msgstr "粘贴已选中的处理器"
 
 #: mixer_actor.cc:66
 msgid "Delete Selected Processors"
-msgstr ""
+msgstr "删除已选中的处理器"
 
 #: mixer_actor.cc:67
 msgid "Select All (visible) Processors"
-msgstr ""
+msgstr "选择所有(可见的)处理器"
 
 #: mixer_actor.cc:68
 msgid "Toggle Selected Processors"
-msgstr ""
+msgstr "切换已选中的处理器"
 
 #: mixer_actor.cc:69
 msgid "Toggle Selected Plugins"
-msgstr ""
+msgstr "切换已选中的插件"
 
 #: mixer_actor.cc:70
 msgid "Deselect all strips and processors"
-msgstr ""
+msgstr "不选中所有片段和处理器"
 
 #: mixer_actor.cc:72 mixer_actor.cc:73
 msgid "Scroll Mixer Window to the left"
-msgstr ""
+msgstr "滚动混音器窗口到左侧"
 
 #: mixer_actor.cc:75
 msgid "Toggle MIDI Input Active for Mixer-Selected Tracks/Busses"
-msgstr ""
+msgstr "为混音器已选中的音轨/总线激活切换 MIDI 输入"
 
 #: mixer_actor.cc:90
 msgid "Loaded mixer bindings from %1"
-msgstr ""
+msgstr "从 %1 载入混音器绑定"
 
 #: mixer_actor.cc:92
 msgid "Could not find mixer.bindings in search path %1"
-msgstr ""
+msgstr "在搜索路径 %1 找不到混音器绑定"
 
 #: mixer_strip.cc:96 mixer_strip.cc:125
 msgid "pre"
-msgstr ""
+msgstr "预先"
 
 #: mixer_strip.cc:98 mixer_strip.cc:127 mixer_strip.cc:372 mixer_strip.cc:1410
 #: rc_option_editor.cc:2331
 msgid "Comments"
-msgstr ""
+msgstr "注释"
 
 #: mixer_strip.cc:149
 msgid "Click to toggle the width of this mixer strip."
-msgstr ""
+msgstr "点击切换此混音器片段的宽度。"
 
 #: mixer_strip.cc:151
 msgid ""
 "\n"
 "%1-%2-click to toggle the width of all strips."
 msgstr ""
+"\n"
+"%1-%2-点击切换所有片段的宽度。"
 
 #: mixer_strip.cc:158
 msgid "Hide this mixer strip"
-msgstr ""
+msgstr "隐藏此混音器片段"
 
 #: mixer_strip.cc:169
 msgid "Click to select metering point"
-msgstr ""
+msgstr "点击选择节拍点"
 
 #: mixer_strip.cc:185
 msgid "Isolate Solo"
-msgstr ""
+msgstr "隔离独奏"
 
 #: mixer_strip.cc:193
 msgid "Lock Solo Status"
-msgstr ""
+msgstr "锁定独奏状态"
 
 #: mixer_strip.cc:196 mixer_strip.cc:2027
 msgid "Iso"
-msgstr ""
+msgstr "隔离"
 
 #: mixer_strip.cc:250
 msgid "Mix group"
-msgstr ""
+msgstr "混合分组"
 
 #: mixer_strip.cc:368 rc_option_editor.cc:2327
 msgid "Phase Invert"
-msgstr ""
+msgstr "相位反转"
 
 #: mixer_strip.cc:369 rc_option_editor.cc:2328
 msgid "Record & Monitor"
-msgstr ""
+msgstr "录制和监控"
 
 #: mixer_strip.cc:370 rc_option_editor.cc:2329
 msgid "Solo Iso / Lock"
-msgstr ""
+msgstr "独奏隔离/锁定"
 
 #: mixer_strip.cc:524
 msgid "Enable/Disable MIDI input"
-msgstr "启用/禁用MIDI输入"
+msgstr "启用/禁用 MIDI 输入"
 
 #: mixer_strip.cc:688
 msgid "Aux"
-msgstr ""
+msgstr "辅助"
 
 #: mixer_strip.cc:710
 msgid "Snd"
-msgstr ""
+msgstr "声音"
 
 #: mixer_strip.cc:776 mixer_strip.cc:879 processor_box.cc:2382
 msgid "Not connected to audio engine - no I/O changes are possible"
-msgstr ""
+msgstr "未连接到音频引擎——不可能改变输入/输出"
 
 #: mixer_strip.cc:833 mixer_strip.cc:935
 msgid "Add %1 port"
-msgstr ""
+msgstr "添加 %1 端口"
 
 #: mixer_strip.cc:840 mixer_strip.cc:942
 msgid "Routing Grid"
-msgstr ""
+msgstr "路由网格"
 
 #: mixer_strip.cc:1171
 msgid "<b>INPUT</b> to %1"
-msgstr ""
+msgstr "<b>输入</b> 到 %1"
 
 #: mixer_strip.cc:1174
 msgid "<b>OUTPUT</b> from %1"
-msgstr ""
+msgstr "<b>输出</b> 来自 %1"
 
 #: mixer_strip.cc:1287
 msgid "Disconnected"
@@ -7443,23 +7617,23 @@ msgstr "失去连接"
 
 #: mixer_strip.cc:1413
 msgid "*Comments*"
-msgstr ""
+msgstr "*注释*"
 
 #: mixer_strip.cc:1420
 msgid "Cmt"
-msgstr ""
+msgstr "注释"
 
 #: mixer_strip.cc:1423
 msgid "*Cmt*"
-msgstr ""
+msgstr "*注释*"
 
 #: mixer_strip.cc:1429
 msgid "Click to Add/Edit Comments"
-msgstr ""
+msgstr "点击添加/编辑注释"
 
 #: mixer_strip.cc:1473
 msgid "Grp"
-msgstr "组"
+msgstr "分组"
 
 #: mixer_strip.cc:1476
 msgid "~G"
@@ -7467,19 +7641,19 @@ msgstr "~G"
 
 #: mixer_strip.cc:1505 route_time_axis.cc:561
 msgid "Color..."
-msgstr "颜色..."
+msgstr "颜色…"
 
 #: mixer_strip.cc:1507 route_time_axis.cc:563
 msgid "Comments..."
-msgstr "注释..."
+msgstr "注释…"
 
 #: mixer_strip.cc:1509 route_time_axis.cc:565
 msgid "Inputs..."
-msgstr ""
+msgstr "输入…"
 
 #: mixer_strip.cc:1511 route_time_axis.cc:567
 msgid "Outputs..."
-msgstr ""
+msgstr "输出…"
 
 #: mixer_strip.cc:1516
 msgid "Save As Template..."
@@ -7491,27 +7665,27 @@ msgstr "调整延迟..."
 
 #: mixer_strip.cc:1533
 msgid "Protect Against Denormals"
-msgstr ""
+msgstr "防止异常违反"
 
 #: mixer_strip.cc:1539 route_time_axis.cc:580
 msgid "Remote Control ID..."
-msgstr ""
+msgstr "远程控制 ID…"
 
 #: mixer_strip.cc:1823
 msgid "Pre"
-msgstr ""
+msgstr "预先"
 
 #: mixer_strip.cc:1827
 msgid "Post"
-msgstr ""
+msgstr "后置"
 
 #: mixer_strip.cc:1847
 msgid "Pr"
-msgstr ""
+msgstr "预先"
 
 #: mixer_strip.cc:1851
 msgid "Po"
-msgstr ""
+msgstr "后置"
 
 #: mixer_strip.cc:1860
 msgid "C"
@@ -7519,15 +7693,17 @@ msgstr ""
 
 #: mixer_strip.cc:2008 route_ui.cc:168
 msgid "Disk"
-msgstr ""
+msgstr "硬盘"
 
+# AFL - Aside Fade Listen. 衰减后监听
 #: mixer_strip.cc:2020 monitor_section.cc:70
 msgid "AFL"
-msgstr ""
+msgstr "后置淡化试听"
 
+# PFL Pre-Fader-Listen衰减前监听
 #: mixer_strip.cc:2023 monitor_section.cc:71
 msgid "PFL"
-msgstr ""
+msgstr "前置淡化试听"
 
 #: mixer_strip.cc:2034 meter_strip.cc:380
 msgid "D"
@@ -7535,55 +7711,55 @@ msgstr ""
 
 #: mixer_strip.cc:2241
 msgid "Pre Fader"
-msgstr ""
+msgstr "前置淡化"
 
 #: mixer_strip.cc:2242
 msgid "Post Fader"
-msgstr ""
+msgstr "后置淡化"
 
 #: mixer_strip.cc:2286 meter_strip.cc:847
 msgid "Change all in Group to %1"
-msgstr ""
+msgstr "改变分组里所有的到 %1"
 
 #: mixer_strip.cc:2288 meter_strip.cc:849
 msgid "Change all to %1"
-msgstr ""
+msgstr "改变所有的到 %1"
 
 #: mixer_strip.cc:2290 meter_strip.cc:851
 msgid "Change same track-type to %1"
-msgstr ""
+msgstr "改变相同轨道类型的到 %1"
 
 #: mixer_ui.cc:130 route_time_axis.cc:818
 msgid "Group"
-msgstr "组"
+msgstr "分组"
 
 #: mixer_ui.cc:1224
 msgid "track display list item for renamed strip not found!"
-msgstr ""
+msgstr "未找到音轨显示列表的重命名片段条目!"
 
 #: mixer_ui.cc:1316
 msgid "-all-"
-msgstr ""
+msgstr "—所有—"
 
 #: mixer_ui.cc:1853
 msgid "Strips"
-msgstr ""
+msgstr "片段"
 
 #: meter_strip.cc:157
 msgid "Reset Peak"
-msgstr ""
+msgstr "重置峰值"
 
 #: meter_strip.cc:883
 msgid "Variable height"
-msgstr ""
+msgstr "变量高度"
 
 #: meter_strip.cc:884
 msgid "Short"
-msgstr ""
+msgstr "短小的"
 
 #: meter_strip.cc:885
 msgid "Tall"
-msgstr ""
+msgstr "高大的"
 
 #: meter_strip.cc:886
 msgid "Grande"
@@ -7595,11 +7771,11 @@ msgstr ""
 
 #: meter_patterns.cc:82
 msgid "Peak"
-msgstr ""
+msgstr "峰值"
 
 #: meter_patterns.cc:85
 msgid "RMS + Peak"
-msgstr ""
+msgstr "均方根 + 峰值"
 
 #: meter_patterns.cc:88
 msgid "IEC1/DIN"
@@ -7643,183 +7819,188 @@ msgstr "独奏中"
 
 #: monitor_section.cc:100
 msgid "Isolated"
-msgstr ""
+msgstr "已隔离"
 
 #: monitor_section.cc:104
 msgid "Auditioning"
-msgstr ""
+msgstr "监听中"
 
 #: monitor_section.cc:114
 msgid ""
 "When active, something is solo-isolated.\n"
 "Click to de-isolate everything"
 msgstr ""
+"启用时,某些被独奏隔离。\n"
+"点击解除所有的隔离"
 
 #: monitor_section.cc:117
 msgid ""
 "When active, auditioning is active.\n"
 "Click to stop the audition"
 msgstr ""
-"启用时, 监听正在进行.\n"
-"点击来停止监听."
+"启用时,监听激活。\n"
+"点击停止监听."
 
 #: monitor_section.cc:134
 msgid "Solo controls affect solo-in-place"
-msgstr ""
+msgstr "独奏控制影响独奏入位"
 
 #: monitor_section.cc:140
 msgid "Solo controls toggle after-fader-listen"
-msgstr ""
+msgstr "独奏控制切换后置淡化试听"
 
 #: monitor_section.cc:146
 msgid "Solo controls toggle pre-fader-listen"
-msgstr ""
+msgstr "独奏控制切换前置淡化试听"
 
 #: monitor_section.cc:156
 msgid "Gain increase for soloed signals (0dB is normal)"
-msgstr ""
+msgstr "为独奏信号加大增益(正常值为 0dB)"
 
 #: monitor_section.cc:170
 msgid "Solo Boost"
-msgstr ""
+msgstr "独奏提升"
 
 #: monitor_section.cc:185
 msgid ""
 "Gain reduction non-soloed signals\n"
 "A value above -inf dB causes \"solo-in-front\""
 msgstr ""
+"增益减少非独奏信号\n"
+"一个数值高于 -inf dB 引起”独奏在前“"
 
 #: monitor_section.cc:196
 msgid "SiP Cut"
-msgstr ""
+msgstr "SiP 剪切"
 
 #: monitor_section.cc:211
 msgid "Gain reduction to use when dimming monitor outputs"
-msgstr ""
+msgstr "当减弱监控输出时,减小增益的使用"
 
 #: monitor_section.cc:225 monitor_section.cc:283
 msgid "Dim"
-msgstr ""
+msgstr "减弱"
 
 #: monitor_section.cc:235
 msgid "Excl. Solo"
-msgstr ""
+msgstr "把独奏排除在外"
 
 #: monitor_section.cc:237
 msgid "Exclusive solo means that only 1 solo is active at a time"
-msgstr ""
+msgstr "专属独奏意味着在同一时间仅有一个独奏是激活的"
 
 #: monitor_section.cc:244
 msgid "Solo » Mute"
-msgstr ""
+msgstr "独奏 » 静音"
 
 #: monitor_section.cc:246
 msgid ""
 "If enabled, solo will override mute\n"
 "(a soloed & muted track or bus will be audible)"
 msgstr ""
+"如果启用,独奏将覆盖静音\n"
+"(一个独奏且静音的音轨或总线将成为可听见)"
 
 #: monitor_section.cc:323
 msgid "Monitor"
-msgstr ""
+msgstr "监控"
 
 #: monitor_section.cc:744
 msgid "Switch monitor to mono"
-msgstr ""
+msgstr "转换监控到单声道"
 
 #: monitor_section.cc:747
 msgid "Cut monitor"
-msgstr ""
+msgstr "剪切监控"
 
 #: monitor_section.cc:750
 msgid "Dim monitor"
-msgstr ""
+msgstr "减弱监控"
 
 #: monitor_section.cc:753
 msgid "Toggle exclusive solo mode"
-msgstr ""
+msgstr "切换专属的独奏模式"
 
 #: monitor_section.cc:759
 msgid "Toggle mute overrides solo mode"
-msgstr ""
+msgstr "切换静音覆盖独奏模式"
 
 #: monitor_section.cc:771
 msgid "Cut monitor channel %1"
-msgstr ""
+msgstr "剪切监控声道 %1"
 
 #: monitor_section.cc:776
 msgid "Dim monitor channel %1"
-msgstr ""
+msgstr "减弱监控声道 %1"
 
 #: monitor_section.cc:781
 msgid "Solo monitor channel %1"
-msgstr ""
+msgstr "独奏监控声道 %1"
 
 #: monitor_section.cc:786
 msgid "Invert monitor channel %1"
-msgstr ""
+msgstr "反转监控声道 %1"
 
 #: monitor_section.cc:796
 msgid "In-place solo"
-msgstr ""
+msgstr "入位独奏"
 
 #: monitor_section.cc:798
 msgid "After Fade Listen (AFL) solo"
-msgstr ""
+msgstr "衰减后监听(AFL)独奏"
 
 #: monitor_section.cc:800
 msgid "Pre Fade Listen (PFL) solo"
-msgstr ""
+msgstr "衰减前监听(PFL)独奏"
 
 #: mono_panner.cc:109 stereo_panner.cc:119
 msgid "bypassed"
-msgstr ""
+msgstr "支路"
 
 #: mono_panner.cc:123
 #, c-format
 msgid "L:%3d R:%3d"
-msgstr ""
+msgstr "左:%3d 右:%3d"
 
 #: mono_panner_editor.cc:33
 msgid "Mono Panner"
-msgstr ""
+msgstr "单声道面板"
 
-#: mono_panner_editor.cc:44 mono_panner_editor.cc:49
-#: stereo_panner_editor.cc:46 stereo_panner_editor.cc:51
+#: mono_panner_editor.cc:44 mono_panner_editor.cc:49 stereo_panner_editor.cc:46
+#: stereo_panner_editor.cc:51
 msgid "%"
 msgstr ""
 
 #: nag.cc:41
 msgid "Support %1 Development"
-msgstr ""
+msgstr "支持 %1 的开发"
 
 #: nag.cc:42
 msgid "I'd like to make a one-time donation"
-msgstr "我想来个一次性捐赠"
+msgstr "我愿意给予一次性捐助"
 
 #: nag.cc:43
 msgid "Tell me more about becoming a subscriber"
-msgstr "跟我讲讲关于成为订购者"
+msgstr "请告知我关于成为捐助者的信息"
 
 #: nag.cc:44
 msgid "I'm already a subscriber!"
-msgstr "我已经是订购者了"
+msgstr "我已经是捐助者了!"
 
 #: nag.cc:45
 msgid "Ask about this the next time I export"
-msgstr "在下次导出时提醒我一下"
+msgstr "在下次我导出时询问这事"
 
 #: nag.cc:46
 msgid "Never ever ask me about this again"
-msgstr "以后别再问我了"
+msgstr "再也不要询问我这事"
 
 #: nag.cc:49
 msgid ""
 "Congratulations on your session export.\n"
 "\n"
 "It looks as if you may already be a subscriber. If so, thanks, and sorry\n"
-"to bother you again about this - I'm working on improving our subscriber "
-"system\n"
+"to bother you again about this - I'm working on improving our subscriber system\n"
 "so that I don't have to keep annoying you with this message.\n"
 "\n"
 "If you're not a subscriber, perhaps you might consider supporting my work\n"
@@ -7827,53 +8008,52 @@ msgid ""
 "happen if you choose not to do so. However Ardour's continuing development\n"
 "relies on a stable, sustainable income stream. Thanks for using Ardour!"
 msgstr ""
-"恭喜!你的会话已导出.\n"
+"恭喜!你的会话已导出。\n"
 "\n"
-"你是订购者吗? 如果是的话, 先谢谢你, 然后因为再一次打扰你而抱歉.\n"
-"我们会提高我们的订购者系统, 这样就不会再因为这条信息而打扰你了.\n"
+"看起来您可能已经是捐助者。 如果是的话,感谢您,\n"
+"抱歉为这事而再次打扰了您——我们正致力于改善我们的捐助系统\n"
+"希望我们就不会再因为这条信息而打扰您。\n"
 "\n"
-"如果您不是注册用户, 您可以考虑一下支持我们的工作\n"
-"您可以一次性捐赠或者订购. 如果您不想这样的话也没事.\n"
-"不管怎样, Ardour不断的开发需要一个稳定持续的资金来源.\n"
-"谢谢您的使用!"
+"如果您不是捐助者,也许您可以考虑一下支持我们在Ardour上的工作\n"
+"您可以一次性捐赠或者定期捐助均可。 如果您不想这样做的话也没事。\n"
+"不管怎样, Ardour的后续开发需要一个稳定、持续的资金来源。\n"
+"感谢使用Ardour!"
 
 #: nag.cc:58
 msgid ""
 "Congratulations on your session export.\n"
 "\n"
-"I hope you find Ardour a useful tool. I'd like to ask you to consider "
-"supporting\n"
+"I hope you find Ardour a useful tool. I'd like to ask you to consider supporting\n"
 "its development with either a one-time donation or subscription. Nothing\n"
-"will happen if you choose not to do so. However Ardour's continuing "
-"development\n"
+"will happen if you choose not to do so. However Ardour's continuing development\n"
 "relies on a stable, sustainable income stream. Thanks for using Ardour!"
 msgstr ""
-"恭喜!你的会话已导出.\n"
+"恭喜!你的会话已导出。\n"
 "\n"
-"我们希望您觉得Ardour好用. 我想建议您考虑一下支持Ardour的开发,\n"
-"一次性捐赠或者订购均可. 如果您不想这样的话也没事.\n"
-"不管怎样, Ardour不断的开发需要一个稳定持续的资金来源.\n"
-"谢谢您的使用!"
+"我们希望您觉得Ardour是个有用的工具。我想建议您考虑一下支持它的开发。\n"
+"不论是一次性捐赠或者捐助均可。如果您不想这样做的话也没事。\n"
+"不管怎样, Ardour后续的开发需要一个稳定、持续的资金来源。\n"
+"感谢使用Ardour!"
 
 #: new_plugin_preset_dialog.cc:29
 msgid "New Preset"
-msgstr "新的预设"
+msgstr "新建预设"
 
 #: new_plugin_preset_dialog.cc:30
 msgid "Replace existing preset with this name"
-msgstr "用这个名称代替已存在的预设"
+msgstr "用这个名称替代已存在的预设"
 
 #: new_plugin_preset_dialog.cc:34
 msgid "Name of new preset"
-msgstr "新预设的名称"
+msgstr "新建预设的名称"
 
 #: normalize_dialog.cc:34
 msgid "Normalize regions"
-msgstr "标准化区域"
+msgstr "规范化区域"
 
 #: normalize_dialog.cc:34
 msgid "Normalize region"
-msgstr "标准化区域"
+msgstr "规范化区域"
 
 #: normalize_dialog.cc:49 strip_silence_dialog.cc:66
 msgid "dbFS"
@@ -7881,27 +8061,27 @@ msgstr ""
 
 #: normalize_dialog.cc:56
 msgid "Normalize each region using its own peak value"
-msgstr ""
+msgstr "用每个区域它自己的峰值数值规范化每个区域"
 
 #: normalize_dialog.cc:58
 msgid "Normalize each region using the peak value of all regions"
-msgstr ""
+msgstr "用所有区域的峰值数值规范化每个区域"
 
 #: normalize_dialog.cc:73
 msgid "Normalize"
-msgstr "标准化"
+msgstr "规范化"
 
 #: note_select_dialog.cc:33
 msgid "Select Note"
-msgstr ""
+msgstr "选择音符"
 
 #: opts.cc:57
 msgid "Usage: "
-msgstr "用法: "
+msgstr "用法:"
 
 #: opts.cc:58
 msgid "  [SESSION_NAME]              Name of session to load\n"
-msgstr "  [SESSION_NAME]              载入的会话名称\n"
+msgstr "  [SESSION_NAME]              要载入的会话的名称\n"
 
 #: opts.cc:59
 msgid "  -v, --version               Show version information\n"
@@ -7909,47 +8089,43 @@ msgstr "  -v, --version               显示版本信息\n"
 
 #: opts.cc:60
 msgid "  -h, --help                  Print this message\n"
-msgstr "  -h, --help                  打印此信息\n"
+msgstr "  -h, --help                  打印本信息\n"
 
 #: opts.cc:61
-msgid ""
-"  -a, --no-announcements      Do not contact website for announcements\n"
-msgstr ""
+msgid "  -a, --no-announcements      Do not contact website for announcements\n"
+msgstr "  -a, --no-announcements      不联系网站公告\n"
 
 #: opts.cc:62
-msgid ""
-"  -b, --bindings              Print all possible keyboard binding names\n"
+msgid "  -b, --bindings              Print all possible keyboard binding names\n"
 msgstr "  -b, --bindings              打印所有可能的键盘绑定名称\n"
 
 #: opts.cc:63
 msgid ""
 "  -c, --name <name>           Use a specific backend client name, default is "
 "ardour\n"
-msgstr ""
+msgstr "  -c, --name <name>           使用一个特定的后端客户名称,默认是ardour\n"
 
 #: opts.cc:64
-msgid ""
-"  -d, --disable-plugins       Disable all plugins in an existing session\n"
+msgid "  -d, --disable-plugins       Disable all plugins in an existing session\n"
 msgstr "  -d, --disable-plugins       在一个已存在的会话中禁用所有插件\n"
 
 #: opts.cc:65
 msgid ""
-"  -D, --debug <options>       Set debug flags. Use \"-D list\" to see "
-"available options\n"
+"  -D, --debug <options>       Set debug flags. Use \"-D list\" to see available "
+"options\n"
 msgstr ""
 "  -D, --debug <options>       设置调试标志. 使用 \"-D list\" 显示可用的选项\n"
 
 #: opts.cc:66
 msgid "  -n, --no-splash             Do not show splash screen\n"
-msgstr ""
+msgstr "  -n, --no-splash             不显示闪屏\n"
 
 #: opts.cc:67
 msgid "  -m, --menus file            Use \"file\" to define menus\n"
-msgstr "  -m, --menus file            使用 \"file\" 定义菜单\n"
+msgstr "  -m, --menus file            使用 \"file\" (文件)来定义菜单\n"
 
 #: opts.cc:68
-msgid ""
-"  -N, --new session-name      Create a new session from the command line\n"
+msgid "  -N, --new session-name      Create a new session from the command line\n"
 msgstr "  -N, --new session-name      从命令行创建一个新的会话\n"
 
 #: opts.cc:69
@@ -7958,7 +8134,7 @@ msgstr "  -O, --no-hw-optimizations   禁用 h/w 特殊的优化\n"
 
 #: opts.cc:70
 msgid "  -P, --no-connect-ports      Do not connect any ports at startup\n"
-msgstr ""
+msgstr "  -P, --no-connect-ports     在启动时不连接任何端口 \n"
 
 #: opts.cc:71
 msgid "  -S, --sync                  Draw the gui synchronously \n"
@@ -7970,9 +8146,10 @@ msgstr "  -V, --novst                 不使用VST支持\n"
 
 #: opts.cc:75
 msgid ""
-"  -E, --save <file>           Load the specified session, save it to <file> "
-"and then quit\n"
-msgstr "  -E, --save <file>           载入特殊的会话, 保存在<file> 并退出\n"
+"  -E, --save <file>           Load the specified session, save it to <file> and "
+"then quit\n"
+msgstr ""
+"  -E, --save <file>           载入指定的会话, 保存它在 <file 文件> 中并退出\n"
 
 #: opts.cc:76
 msgid "  -C, --curvetest filename    Curve algorithm debugger\n"
@@ -7980,31 +8157,31 @@ msgstr "  -C, --curvetest filename    曲线算法调试器\n"
 
 #: opts.cc:77
 msgid ""
-"  -k, --keybindings filename  Name of key bindings to load (default is ~/."
-"ardour3/ardour.bindings)\n"
+"  -k, --keybindings filename  Name of key bindings to load (default is ~/.ardour3/"
+"ardour.bindings)\n"
 msgstr ""
-"  -k, --keybindings 文件名  载入的按键绑定名称 (默认是 ~/.ardour3/ardour."
-"bindings)\n"
+"  -k, --keybindings 文件名  要载入的按键绑定名称(默认是 ~/.ardour3/ardour."
+"bindings)\n"
 
 #: panner2d.cc:854
 msgid "Panner (2D)"
-msgstr ""
+msgstr "面板(2D)"
 
 #: panner2d.cc:856 panner_ui.cc:400 plugin_ui.cc:452
 msgid "Bypass"
-msgstr ""
+msgstr "支路"
 
 #: panner2d.cc:862
 msgid "Panner"
-msgstr ""
+msgstr "面板"
 
 #: panner_ui.cc:72
 msgid "Pan automation mode"
-msgstr ""
+msgstr "筛选自动模式"
 
 #: panner_ui.cc:73
 msgid "Pan automation type"
-msgstr ""
+msgstr "筛选自动类型"
 
 #: playlist_selector.cc:43
 msgid "Playlists"
@@ -8024,15 +8201,15 @@ msgstr "其他音轨"
 
 #: playlist_selector.cc:139
 msgid "unassigned"
-msgstr ""
+msgstr "未指定"
 
 #: playlist_selector.cc:194
 msgid "Imported"
-msgstr "Zavedeno"
+msgstr "已导入"
 
 #: plugin_eq_gui.cc:85 plugin_eq_gui.cc:109
 msgid "dB scale"
-msgstr "dB标尺"
+msgstr "dB 比例"
 
 #: plugin_eq_gui.cc:116
 msgid "Show phase"
@@ -8072,7 +8249,7 @@ msgstr "插件管理"
 
 #: plugin_selector.cc:85
 msgid "Fav"
-msgstr "收"
+msgstr "收藏"
 
 #: plugin_selector.cc:87
 msgid "Available Plugins"
@@ -8129,7 +8306,7 @@ msgstr "插入插件"
 #: plugin_selector.cc:337 plugin_selector.cc:338 plugin_selector.cc:339
 #: plugin_selector.cc:340
 msgid "variable"
-msgstr ""
+msgstr "变量"
 
 #: plugin_selector.cc:496
 msgid ""
@@ -8137,6 +8314,9 @@ msgid ""
 "\n"
 "See the Log window for more details (maybe)"
 msgstr ""
+"无法载入插件 \"%1\"\n"
+"\n"
+"更多的信息(也许可以)参阅日志窗口"
 
 #: plugin_selector.cc:644
 msgid "Favorites"
@@ -8144,7 +8324,7 @@ msgstr "收藏"
 
 #: plugin_selector.cc:646
 msgid "Plugin Manager..."
-msgstr "插件管理器..."
+msgstr "插件管理器…"
 
 #: plugin_selector.cc:650
 msgid "By Creator"
@@ -8156,35 +8336,35 @@ msgstr "根据类别"
 
 #: plugin_ui.cc:113
 msgid "Eh? LADSPA plugins don't have editors!"
-msgstr "呃?LADSPA插件没有编辑器"
+msgstr "噢?LADSPA插件没有编辑器!"
 
 #: plugin_ui.cc:122 plugin_ui.cc:227
 msgid ""
-"unknown type of editor-supplying plugin (note: no VST support in this "
-"version of %1)"
-msgstr ""
+"unknown type of editor-supplying plugin (note: no VST support in this version of "
+"%1)"
+msgstr "未知的编辑器应用插件类型(注意:在这个 %1 版本无 VST 支持)"
 
 #: plugin_ui.cc:125
 msgid "unknown type of editor-supplying plugin"
-msgstr "未知类型编辑器插件"
+msgstr "未知的编辑器应用插件类型"
 
 #: plugin_ui.cc:257
 msgid ""
-"unknown type of editor-supplying plugin (note: no linuxVST support in this "
-"version of %1)"
-msgstr ""
+"unknown type of editor-supplying plugin (note: no linuxVST support in this version "
+"of %1)"
+msgstr "未知的编辑器应用插件类型(注意:在这个 %1 版本无 linuxVST 支持)"
 
 #: plugin_ui.cc:329
 msgid "create_lv2_editor called on non-LV2 plugin"
-msgstr ""
+msgstr "创建_lv2_编辑器调用 non-LV2 插件"
 
 #: plugin_ui.cc:418
 msgid "Add"
-msgstr "增添"
+msgstr "添加"
 
 #: plugin_ui.cc:422
 msgid "Description"
-msgstr ""
+msgstr "说明"
 
 #: plugin_ui.cc:423
 msgid "Plugin analysis"
@@ -8195,62 +8375,63 @@ msgid ""
 "Presets (if any) for this plugin\n"
 "(Both factory and user-created)"
 msgstr ""
+"预设这个插件(如果有的话)\n"
+"(包括出厂设置和用户创建的设置)"
 
 #: plugin_ui.cc:431
 msgid "Save a new preset"
-msgstr ""
+msgstr "保存一个新的预设"
 
 #: plugin_ui.cc:432
 msgid "Save the current preset"
-msgstr ""
+msgstr "保存当前预设"
 
 #: plugin_ui.cc:433
 msgid "Delete the current preset"
-msgstr ""
+msgstr "删除当前预设"
 
 #: plugin_ui.cc:434
 msgid "Disable signal processing by the plugin"
-msgstr ""
+msgstr "按插件禁用信号处理"
 
 #: plugin_ui.cc:467 plugin_ui.cc:663
 msgid ""
-"Click to allow the plugin to receive keyboard events that %1 would normally "
-"use as a shortcut"
-msgstr "单击来允许此插件接受键盘事件, 这样子就可以正常地使用 %1 快捷键"
+"Click to allow the plugin to receive keyboard events that %1 would normally use as "
+"a shortcut"
+msgstr "单击允许此插件接受键盘事件,以便 %1 可以正常地作为一个快捷键使用"
 
 #: plugin_ui.cc:468
 msgid "Click to enable/disable this plugin"
-msgstr "单击来启用/禁用此插件"
+msgstr "单击启用/禁用此插件"
 
 #: plugin_ui.cc:507
 msgid "latency (%1 sample)"
 msgid_plural "latency (%1 samples)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "延迟(%1 采样)"
 
 #: plugin_ui.cc:509
 msgid "latency (%1 ms)"
-msgstr "延迟 (%1 毫秒)"
+msgstr "延迟(%1 毫秒)"
 
 #: plugin_ui.cc:520
 msgid "Edit Latency"
-msgstr "Upravit prodlevu"
+msgstr "编辑延迟"
 
 #: plugin_ui.cc:566
 msgid ""
-"Plugin presets are not supported in this build of %1. Consider paying for a "
-"full version"
-msgstr ""
+"Plugin presets are not supported in this build of %1. Consider paying for a full "
+"version"
+msgstr "插件预设在本个 %1 构建中不支持。请考虑为完整版本付"
 
 #: plugin_ui.cc:574
 msgid ""
 "Plugin presets are not supported in this build, see the Log window for more "
 "information."
-msgstr ""
+msgstr "插件预设在本构建中不支持,更多信息请参阅日志窗口。"
 
 #: plugin_ui.cc:670
 msgid "Click to allow normal use of %1 keyboard shortcuts"
-msgstr "单击来允许正常地使用 %1 快捷键"
+msgstr "单击允许正常使用 %1 键盘快捷键"
 
 #: port_group.cc:337
 msgid "%1 Busses"
@@ -8262,7 +8443,7 @@ msgstr "%1 音轨"
 
 #: port_group.cc:339
 msgid "Hardware"
-msgstr "银监"
+msgstr "硬件"
 
 #: port_group.cc:340
 msgid "%1 Misc"
@@ -8270,55 +8451,55 @@ msgstr "%1 杂项"
 
 #: port_group.cc:341
 msgid "Other"
-msgstr "其他"
+msgstr "其它"
 
 #: port_group.cc:432 port_group.cc:433
 msgid "LTC Out"
-msgstr ""
+msgstr "LTC 输出"
 
 #: port_group.cc:436 port_group.cc:437
 msgid "LTC In"
-msgstr ""
+msgstr "LTC 输入"
 
 #: port_group.cc:463
 msgid "MTC in"
-msgstr "MTC输入"
+msgstr "MTC 输入"
 
 #: port_group.cc:466
 msgid "MIDI control in"
-msgstr "MIDI控制输入"
+msgstr "MIDI 控制输入"
 
 #: port_group.cc:469
 msgid "MIDI clock in"
-msgstr "MIDI时钟输入"
+msgstr "MIDI 计时器输入"
 
 #: port_group.cc:472
 msgid "MMC in"
-msgstr "MMC输入"
+msgstr "MMC 输入"
 
 #: port_group.cc:476
 msgid "MTC out"
-msgstr "MTC输出"
+msgstr "MTC 输出"
 
 #: port_group.cc:479
 msgid "MIDI control out"
-msgstr "MIDI控制输出"
+msgstr "MIDI 控制输出"
 
 #: port_group.cc:482
 msgid "MIDI clock out"
-msgstr "MIDI时钟输出"
+msgstr "MIDI 计时器输出"
 
 #: port_group.cc:485
 msgid "MMC out"
-msgstr "MMC输出"
+msgstr "MMC 输出"
 
 #: port_group.cc:532
 msgid ":monitor"
-msgstr ""
+msgstr ":监控"
 
 #: port_group.cc:544
 msgid "system:"
-msgstr ""
+msgstr "系统:"
 
 #: port_group.cc:545
 msgid "alsa_pcm"
@@ -8338,11 +8519,11 @@ msgstr "返回/输入"
 
 #: port_insert_ui.cc:85
 msgid "No signal detected"
-msgstr "没有检测到信号"
+msgstr "未检测到信号"
 
 #: port_insert_ui.cc:165
 msgid "Port Insert "
-msgstr "插入端口"
+msgstr "端口插入"
 
 #: port_matrix.cc:331 port_matrix.cc:357
 msgid "<b>Sources</b>"
@@ -8355,7 +8536,7 @@ msgstr "<b>目的地</b>"
 #: port_matrix.cc:440 port_matrix.cc:448
 #, c-format
 msgid "Add %s %s"
-msgstr "增加 %s %s"
+msgstr "添加 %s %s"
 
 #: port_matrix.cc:456
 #, c-format
@@ -8381,21 +8562,21 @@ msgstr "显示各个端口"
 
 #: port_matrix.cc:535
 msgid "Flip"
-msgstr ""
+msgstr "轻弹"
 
 #: port_matrix.cc:722
 msgid ""
-"It is not possible to add a port here, as the first processor in the track "
-"or buss cannot support the new configuration."
-msgstr ""
+"It is not possible to add a port here, as the first processor in the track or buss "
+"cannot support the new configuration."
+msgstr "不可能在此添加一个端口,作为在音轨或总线里的第一个处理器无法支持新的配置。"
 
 #: port_matrix.cc:725
 msgid "Cannot add port"
-msgstr ""
+msgstr "无法添加端口"
 
 #: port_matrix.cc:747
 msgid "Port removal not allowed"
-msgstr "不允许端口移除"
+msgstr "不允许移除端口"
 
 #: port_matrix.cc:748
 msgid ""
@@ -8403,6 +8584,9 @@ msgid ""
 "Either the first plugin in the track or buss cannot accept\n"
 "the new number of inputs or the last plugin has more outputs."
 msgstr ""
+"该端口不能被移除。\n"
+"不论是新的输入号码或者最后一个插件有更多的输出,\n"
+"在音轨或总线里的第一个插件都无法接受。"
 
 #: port_matrix.cc:965
 #, c-format
@@ -8412,7 +8596,7 @@ msgstr "移除 '%s'"
 #: port_matrix.cc:980
 #, c-format
 msgid "%s all from '%s'"
-msgstr "%s 所有, 从 '%s'"
+msgstr "%s 所有来自于 '%s'"
 
 #: port_matrix.cc:1046 transform_dialog.cc:62
 msgid "channel"
@@ -8420,7 +8604,7 @@ msgstr "声道"
 
 #: port_matrix_body.cc:82
 msgid "There are no ports to connect."
-msgstr "没有连接的端口"
+msgstr "没有端口可连接。"
 
 #: port_matrix_body.cc:84
 msgid "There are no %1 ports to connect."
@@ -8428,17 +8612,19 @@ msgstr "没有 %1 端口可连接."
 
 #: processor_box.cc:150
 msgid "Send"
-msgstr ""
+msgstr "发送"
 
 #: processor_box.cc:152
 msgid "Return"
-msgstr ""
+msgstr "返回"
 
 #: processor_box.cc:310
 msgid ""
 "\n"
 "This mono plugin has been replicated %1 times."
 msgstr ""
+"\n"
+"这个单声道插件已经被复制了 %1 次。"
 
 #: processor_box.cc:314
 msgid ""
@@ -8446,12 +8632,17 @@ msgid ""
 "Double-click to show GUI.\n"
 "Alt+double-click to show generic GUI.%2"
 msgstr ""
+"<b>%1</b>\n"
+"双击显示图形用户界面。\n"
+"Alt+双击显示通用图形用户界面。%2"
 
 #: processor_box.cc:317
 msgid ""
 "<b>%1</b>\n"
 "Double-click to show generic GUI.%2"
 msgstr ""
+"<b>%1</b>\n"
+"双击显示通用图形用户界面。%2"
 
 #: processor_box.cc:361
 #, c-format
@@ -8460,37 +8651,39 @@ msgstr ""
 
 #: processor_box.cc:437
 msgid "Show All Controls"
-msgstr ""
+msgstr "显示所有控制"
 
 #: processor_box.cc:441
 msgid "Hide All Controls"
-msgstr ""
+msgstr "隐藏所有控制"
 
 #: processor_box.cc:475
 msgid "Link panner controls"
-msgstr ""
+msgstr "链接面板控制"
 
 #: processor_box.cc:575
 msgid "on"
-msgstr ""
+msgstr "开启"
 
 #: processor_box.cc:575 rc_option_editor.cc:2360 rc_option_editor.cc:2374
 msgid "off"
-msgstr ""
+msgstr "关闭"
 
 #: processor_box.cc:957
 msgid ""
 "Right-click to add/remove/edit\n"
 "plugins,inserts,sends and more"
 msgstr ""
+"右键点击添加/移除/编辑\n"
+"插件、插入、发送以及更多"
 
 #: processor_box.cc:1429 processor_box.cc:1804
 msgid "Plugin Incompatibility"
-msgstr "插件不匹配"
+msgstr "插件不兼容"
 
 #: processor_box.cc:1432
 msgid "You attempted to add the plugin \"%1\" in slot %2.\n"
-msgstr ""
+msgstr "您试图在空位 %2 中添加插件 \"%1\" 。\n"
 
 #: processor_box.cc:1438
 msgid ""
@@ -8498,37 +8691,35 @@ msgid ""
 "This plugin has:\n"
 msgstr ""
 "\n"
-"此插件:\n"
+"此插件有:\n"
 
 #: processor_box.cc:1441
 msgid "\t%1 MIDI input\n"
 msgid_plural "\t%1 MIDI inputs\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "\t%1 MIDI 输入\n"
 
 #: processor_box.cc:1445
 msgid "\t%1 audio input\n"
 msgid_plural "\t%1 audio inputs\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "\t%1 音频输出\n"
 
 #: processor_box.cc:1448
 msgid ""
 "\n"
 "but at the insertion point, there are:\n"
 msgstr ""
+"\n"
+"但在插入点那里有:\n"
 
 #: processor_box.cc:1451
 msgid "\t%1 MIDI channel\n"
 msgid_plural "\t%1 MIDI channels\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "\t%1 MIDI 声道\n"
 
 #: processor_box.cc:1455
 msgid "\t%1 audio channel\n"
 msgid_plural "\t%1 audio channels\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "\t%1 音频声道\n"
 
 #: processor_box.cc:1458
 msgid ""
@@ -8536,11 +8727,11 @@ msgid ""
 "%1 is unable to insert this plugin here.\n"
 msgstr ""
 "\n"
-"%1 无法再次插入插件."
+"%1 无法在此处再次插入插件.\n"
 
 #: processor_box.cc:1495
 msgid "Cannot set up new send: %1"
-msgstr ""
+msgstr "无法建立新的发送: %1"
 
 #: processor_box.cc:1807
 msgid ""
@@ -8548,6 +8739,9 @@ msgid ""
 "in that way because the inputs and\n"
 "outputs will not work correctly."
 msgstr ""
+"您不能以这种方式\n"
+"要求这些插件/发送/插入\n"
+"因为输入和输出将无法正确工作。"
 
 #: processor_box.cc:1991
 msgid "Rename Processor"
@@ -8555,11 +8749,11 @@ msgstr "重命名处理器"
 
 #: processor_box.cc:2022
 msgid "At least 100 IO objects exist with a name like %1 - name not changed"
-msgstr "至少有100个IO(输入输出)对象存在着这样的%1的名称 -名称没有改变"
+msgstr "至少有100个输入输出对象物体存在着像 %1这样的名称——名称没有改变"
 
 #: processor_box.cc:2159
 msgid "plugin insert constructor failed"
-msgstr ""
+msgstr "插件插入构造函数失败"
 
 #: processor_box.cc:2170
 msgid ""
@@ -8567,18 +8761,21 @@ msgid ""
 "probably because the I/O configuration of the plugins\n"
 "could not match the configuration of this track."
 msgstr ""
+"复制剪贴板上的处理器集成失败,\n"
+"可能是因为插件的输入/输出配置\n"
+"无法匹配这条音轨的配置。"
 
 #: processor_box.cc:2216
 msgid ""
 "Do you really want to remove all processors from %1?\n"
 "(this cannot be undone)"
 msgstr ""
-"你真想要移除所有处理器从 %1?\n"
-"(此操作不可撤销)"
+"您是否真的要从 %1 移除所有的处理器?\n"
+"(此操作不可撤销)"
 
 #: processor_box.cc:2220 processor_box.cc:2245
 msgid "Yes, remove them all"
-msgstr "确定移除所有"
+msgstr "是的,全部移除它们"
 
 #: processor_box.cc:2222 processor_box.cc:2247
 msgid "Remove processors"
@@ -8589,44 +8786,48 @@ msgid ""
 "Do you really want to remove all pre-fader processors from %1?\n"
 "(this cannot be undone)"
 msgstr ""
+"您是否真的要从 %1 移除所有的前置淡化处理器?\n"
+"(此操作不可撤销)"
 
 #: processor_box.cc:2240
 msgid ""
 "Do you really want to remove all post-fader processors from %1?\n"
 "(this cannot be undone)"
 msgstr ""
+"您是否真的要从 %1 移除所有的后置淡化处理器?\n"
+"(此操作不可撤销)"
 
 #: processor_box.cc:2428
 msgid "New Plugin"
-msgstr "新插件"
+msgstr "新建插件"
 
 #: processor_box.cc:2431
 msgid "New Insert"
-msgstr "新插入"
+msgstr "新建插入"
 
 #: processor_box.cc:2434
 msgid "New External Send ..."
-msgstr ""
+msgstr "新建外部发送…"
 
 #: processor_box.cc:2438
 msgid "New Aux Send ..."
-msgstr ""
+msgstr "新建辅助发送"
 
 #: processor_box.cc:2441
 msgid "Send Options"
-msgstr ""
+msgstr "发送选项"
 
 #: processor_box.cc:2443
 msgid "Clear (all)"
-msgstr "清除(所有)"
+msgstr "清除(所有)"
 
 #: processor_box.cc:2445
 msgid "Clear (pre-fader)"
-msgstr ""
+msgstr "清除(前置淡化)"
 
 #: processor_box.cc:2447
 msgid "Clear (post-fader)"
-msgstr ""
+msgstr "清除(后置淡化)"
 
 #: processor_box.cc:2473
 msgid "Activate All"
@@ -8634,7 +8835,7 @@ msgstr "激活所有"
 
 #: processor_box.cc:2475
 msgid "Deactivate All"
-msgstr ""
+msgstr "不激活所有"
 
 #: processor_box.cc:2477
 msgid "A/B Plugins"
@@ -8642,75 +8843,75 @@ msgstr "A/B 插件"
 
 #: processor_box.cc:2486
 msgid "Edit with generic controls..."
-msgstr ""
+msgstr "以通用控制编辑…"
 
 #: processor_box.cc:2789
 msgid "%1: %2 (by %3)"
-msgstr ""
+msgstr "%1: %2(通过 %3)"
 
 #: processor_box.cc:2791
 msgid "%1 (by %2)"
-msgstr ""
+msgstr "%1(通过 %2)"
 
 #: patch_change_dialog.cc:50
 msgid "Patch Change"
-msgstr ""
+msgstr "音色变换"
 
 #: patch_change_dialog.cc:76
 msgid "Patch Bank"
-msgstr ""
+msgstr "音色库"
 
 #: patch_change_dialog.cc:83
 msgid "Patch"
-msgstr ""
+msgstr "音色"
 
 #: patch_change_dialog.cc:98 step_entry.cc:430
 msgid "Program"
-msgstr ""
+msgstr "程序"
 
 #: patch_change_dialog.cc:106 step_entry.cc:422
 msgid "Bank"
-msgstr ""
+msgstr "库"
 
 #: quantize_dialog.cc:36
 msgid "main grid"
-msgstr ""
+msgstr "主要网格"
 
 #: quantize_dialog.cc:52 quantize_dialog.cc:109
 msgid "Quantize"
-msgstr "量化"
+msgstr "数字转换"
 
 #: quantize_dialog.cc:56
 msgid "Strength"
-msgstr ""
+msgstr "强度"
 
 #: quantize_dialog.cc:59
 msgid "Swing"
-msgstr ""
+msgstr "摆动"
 
 #: quantize_dialog.cc:62
 msgid "Threshold (ticks)"
-msgstr ""
+msgstr "临界值(识别声)"
 
 #: quantize_dialog.cc:63
 msgid "Snap note start"
-msgstr "对齐音符开始"
+msgstr "对齐音符起点"
 
 #: quantize_dialog.cc:64
 msgid "Snap note end"
-msgstr "对齐音符结束"
+msgstr "对齐音符终点"
 
 #: rc_option_editor.cc:77
 msgid "Click audio file:"
-msgstr "单击音频文件:"
+msgstr "单击音频文件:"
 
 #: rc_option_editor.cc:80 rc_option_editor.cc:87
 msgid "Browse..."
-msgstr "浏览..."
+msgstr "浏览…"
 
 #: rc_option_editor.cc:84
 msgid "Click emphasis audio file:"
-msgstr ""
+msgstr "点击加重音频文件:"
 
 #: rc_option_editor.cc:116
 msgid "Choose Click"
@@ -8718,11 +8919,11 @@ msgstr "选择点击"
 
 #: rc_option_editor.cc:139
 msgid "Choose Click Emphasis"
-msgstr ""
+msgstr "选择点击加重"
 
 #: rc_option_editor.cc:170
 msgid "Limit undo history to"
-msgstr "显示撤销历史"
+msgstr "限制撤销历史到"
 
 #: rc_option_editor.cc:171
 msgid "Save undo history of"
@@ -8734,7 +8935,7 @@ msgstr "命令"
 
 #: rc_option_editor.cc:325
 msgid "Edit using:"
-msgstr "用于编辑:"
+msgstr "编辑使用:"
 
 #: rc_option_editor.cc:331 rc_option_editor.cc:357 rc_option_editor.cc:384
 msgid "+ button"
@@ -8742,142 +8943,152 @@ msgstr "+按钮"
 
 #: rc_option_editor.cc:351
 msgid "Delete using:"
-msgstr "用于删除:"
+msgstr "删除使用:"
 
 #: rc_option_editor.cc:378
 msgid "Insert note using:"
-msgstr "用户插入音符:"
+msgstr "插入音符使用:"
 
 #: rc_option_editor.cc:405
 msgid "Ignore snap using:"
-msgstr ""
+msgstr "忽略音符使用:"
 
 #: rc_option_editor.cc:421
 msgid "Keyboard layout:"
-msgstr "键盘布局:"
+msgstr "键盘布局:"
 
 #: rc_option_editor.cc:544
 msgid "Font scaling:"
-msgstr "字体缩放:"
+msgstr "字体缩放:"
 
 #: rc_option_editor.cc:547
 msgid "Default"
-msgstr ""
+msgstr "默认"
 
 #: rc_option_editor.cc:573
 msgid "Major font-scale changes require an application restart to re-layout."
-msgstr ""
+msgstr "重要的字体缩放变化要求应用程序重新启动以便于重新布局。"
 
 #: rc_option_editor.cc:614
 msgid "Waveform Clip Level (dBFS):"
-msgstr ""
+msgstr "波形截波电平(dBFS):"
 
 #: rc_option_editor.cc:666
 msgid "Playback (seconds of buffering):"
-msgstr "回放(缓冲的秒数):"
+msgstr "回放(缓冲的秒数):"
 
 #: rc_option_editor.cc:679
 msgid "Recording (seconds of buffering):"
-msgstr "录音(缓冲的秒数):"
+msgstr "录制(缓冲的秒数):"
 
 #: rc_option_editor.cc:737
 msgid "Control Surface Protocol"
-msgstr ""
+msgstr "控制面协议"
 
 #: rc_option_editor.cc:746
 msgid "Double-click on a name to edit settings for an enabled protocol"
-msgstr "双击名称来标记已启用的协议设置"
+msgstr "双击名称以便编辑已启用协议的设置"
 
 #: rc_option_editor.cc:903
 msgid "Show Video Export Info before export"
-msgstr ""
+msgstr "导出前显示视频导出信息"
 
 #: rc_option_editor.cc:904
 msgid "Show Video Server Startup Dialog"
-msgstr ""
+msgstr "显示视频服务启动对话框"
 
 #: rc_option_editor.cc:905
 msgid "Advanced Setup (remote video server)"
-msgstr ""
+msgstr "高级设置(远程视频服务)"
 
 #: rc_option_editor.cc:913
 msgid ""
-"<b>When enabled</b> you can speficify a custom video-server URL and docroot. "
-"- Do not enable this option unless you know what you are doing."
+"<b>When enabled</b> you can speficify a custom video-server URL and docroot. - Do "
+"not enable this option unless you know what you are doing."
 msgstr ""
+"<b>启用时</b> 您可以指定一个定制的视频服务器网址和文档根。——不要启用该选项,除非您"
+"知道您正在做什么。"
 
 #: rc_option_editor.cc:915
 msgid "Video Server URL:"
-msgstr ""
+msgstr "视频服务器网址:"
 
 #: rc_option_editor.cc:920
 msgid ""
 "Base URL of the video-server including http prefix. This is usually 'http://"
-"hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when "
-"the video-server is running locally"
+"hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the "
+"video-server is running locally"
 msgstr ""
+"基于网址的视频服务包括 http 前缀。当视频服务器是运行在本地时,这网址通常是 “http://"
+"hostname.example.org:1554/” 以及默认是 “http://localhost:1554/” 。"
 
 #: rc_option_editor.cc:922
 msgid "Video Folder:"
-msgstr ""
+msgstr "视频文件夹:"
 
 #: rc_option_editor.cc:927
 msgid ""
-"Local path to the video-server document-root. Only files below this "
-"directory will be accessible by the video-server. If the server run on a "
-"remote host, it should point to a network mounted folder of the server's "
-"docroot or be left empty if it is unvailable. It is used for the local video-"
-"monitor and file-browsing when opening/adding a video file."
+"Local path to the video-server document-root. Only files below this directory will "
+"be accessible by the video-server. If the server run on a remote host, it should "
+"point to a network mounted folder of the server's docroot or be left empty if it "
+"is unvailable. It is used for the local video-monitor and file-browsing when "
+"opening/adding a video file."
 msgstr ""
+"视频服务器文档根的本地路径。视频服务器仅访问这个目录下的文件。如果服务器运行在远程"
+"主机上,它将指向服务器文档根的一个网络挂载文件夹,或者如果它不可用就留着空白。这是"
+"用于在打开/添加一个视频文件时的本地视频监控以及文件浏览。"
 
 #: rc_option_editor.cc:934
 msgid ""
-"<b>When enabled</b> an information window with details is displayed before "
-"the video-export dialog."
-msgstr ""
+"<b>When enabled</b> an information window with details is displayed before the "
+"video-export dialog."
+msgstr "<b>启用时</b> 在视频输出对话框前显示一个细节信息窗口。"
 
 #: rc_option_editor.cc:939
 msgid ""
 "<b>When enabled</b> the video server is never launched automatically without "
 "confirmation"
-msgstr ""
+msgstr "<b>启用时</b> 视频服务器在没有得到确认前不会自动启动。"
 
 #: rc_option_editor.cc:1022
 msgid "Always Display Plugin Scan Progress"
-msgstr ""
+msgstr "总是显示插件扫描程序"
 
 #: rc_option_editor.cc:1023
 msgid "Scan for [new] VST Plugins on Application Start"
-msgstr ""
+msgstr "在应用起点扫描 [新] VST 插件"
 
 #: rc_option_editor.cc:1024
 msgid "Scan for AudioUnit Plugins on Application Start"
-msgstr ""
+msgstr "在应用起点扫描音频单位插件"
 
 #: rc_option_editor.cc:1035
 msgid "General"
-msgstr ""
+msgstr "通用"
 
 #: rc_option_editor.cc:1041
 msgid "Scan for Plugins"
-msgstr ""
+msgstr "扫描插件"
 
 #: rc_option_editor.cc:1048
 msgid ""
-"<b>When enabled</b> a popup window showing plugin scan progress is displayed "
-"for indexing (cache load) and discovery (detect new plugins)"
+"<b>When enabled</b> a popup window showing plugin scan progress is displayed for "
+"indexing (cache load) and discovery (detect new plugins)"
 msgstr ""
+"<b>启用时</b> 一个弹出窗口显示插件扫描程序,以展示索引(缓存载入)和发现(探测新插"
+"件)。"
 
 #: rc_option_editor.cc:1055
 msgid ""
-"Specify the default timeout for plugin instantiation in 1/10 seconds. "
-"Plugins that require more time to load will be blacklisted. A value of 0 "
-"disables the timeout."
+"Specify the default timeout for plugin instantiation in 1/10 seconds. Plugins that "
+"require more time to load will be blacklisted. A value of 0 disables the timeout."
 msgstr ""
+"插件实例化指定的默认超时在 1/10 以内。需要更多时间载入的插件将被列入黑名单。数值为 "
+"0 则禁用超时。"
 
 #: rc_option_editor.cc:1057
 msgid "Scan Time Out [deciseconds]"
-msgstr ""
+msgstr "扫描超时 [十分之一秒]"
 
 #: rc_option_editor.cc:1065
 msgid "VST"
@@ -8885,54 +9096,59 @@ msgstr ""
 
 #: rc_option_editor.cc:1071
 msgid "Clear VST Cache"
-msgstr ""
+msgstr "清除 VST 缓存"
 
 #: rc_option_editor.cc:1075
 msgid "Clear VST Blacklist"
-msgstr ""
+msgstr "清除 VST 黑名单"
 
 #: rc_option_editor.cc:1083
 msgid ""
-"<b>When enabled</b> new VST plugins are searched, tested and added to the "
-"cache index on application start. When disabled new plugins will only be "
-"available after triggering a 'Scan' manually"
+"<b>When enabled</b> new VST plugins are searched, tested and added to the cache "
+"index on application start. When disabled new plugins will only be available after "
+"triggering a 'Scan' manually"
 msgstr ""
+"<b>启用时</b> 新的 VST 插件被搜索、测试以及添加到应用起点的缓存索引中。当禁用新插件"
+"时,仅在手动触发“扫描”时可用。"
 
 #: rc_option_editor.cc:1086
 msgid "Linux VST Path:"
-msgstr ""
+msgstr "Linux VST 路径:"
 
 #: rc_option_editor.cc:1093
 msgid "Windows VST Path:"
-msgstr ""
+msgstr "Windows VST 路径:"
 
 #: rc_option_editor.cc:1102
 msgid "Audio Unit"
-msgstr ""
+msgstr "音频单位"
 
 #: rc_option_editor.cc:1111
 msgid ""
-"<b>When enabled</b> Audio Unit Plugins are discovered on application start. "
-"When disabled AU plugins will only be available after triggering a 'Scan' "
-"manually. The first successful scan will enable AU auto-scan, Any crash "
-"during plugin discovery will disable it."
+"<b>When enabled</b> Audio Unit Plugins are discovered on application start. When "
+"disabled AU plugins will only be available after triggering a 'Scan' manually. The "
+"first successful scan will enable AU auto-scan, Any crash during plugin discovery "
+"will disable it."
 msgstr ""
+"<b>启用时</b> 音频单位插件被应用起点发现。当禁用音频单位插件时,仅在手动触发“扫"
+"描”时可用。第一次成功的扫描将启用音频单位自动扫描,若插件发现任何崩溃的情况都将禁用"
+"自动扫描。"
 
 #: rc_option_editor.cc:1114
 msgid "Clear AU Cache"
-msgstr ""
+msgstr "清除音频单位缓存"
 
 #: rc_option_editor.cc:1118
 msgid "Clear AU Blacklist"
-msgstr ""
+msgstr "清除音频单位黑名单"
 
 #: rc_option_editor.cc:1201
 msgid "Set Windows VST Search Path"
-msgstr ""
+msgstr "设置 Windows VST 搜索路径"
 
 #: rc_option_editor.cc:1216
 msgid "Set Linux VST Search Path"
-msgstr ""
+msgstr "设置 Linux VST 搜索路径"
 
 #: rc_option_editor.cc:1297
 msgid "%1 Preferences"
@@ -8940,7 +9156,7 @@ msgstr "%1 首选项"
 
 #: rc_option_editor.cc:1309
 msgid "DSP CPU Utilization"
-msgstr "DSP的CPU使用率"
+msgstr "DSP 的 CPU 利用率"
 
 #: rc_option_editor.cc:1313
 msgid "Signal processing uses"
@@ -8948,7 +9164,7 @@ msgstr "信号处理使用"
 
 #: rc_option_editor.cc:1318
 msgid "all but one processor"
-msgstr "除了一个处理器"
+msgstr "除了一个处理器外所有的"
 
 #: rc_option_editor.cc:1319
 msgid "all available processors"
@@ -8960,15 +9176,15 @@ msgstr "%1 处理器"
 
 #: rc_option_editor.cc:1325
 msgid "This setting will only take effect when %1 is restarted."
-msgstr ""
+msgstr "该设置将仅仅在 %1 重新启动时起作用"
 
 #: rc_option_editor.cc:1330
 msgid "Options|Undo"
-msgstr ""
+msgstr "选项|撤销"
 
 #: rc_option_editor.cc:1337
 msgid "Verify removal of last capture"
-msgstr "确认移除最后的录音"
+msgstr "确认移除最后的捕获部分"
 
 #: rc_option_editor.cc:1345
 msgid "Make periodic backups of the session file"
@@ -8976,7 +9192,7 @@ msgstr "定期备份会话文件"
 
 #: rc_option_editor.cc:1350
 msgid "Session Management"
-msgstr ""
+msgstr "会话管理"
 
 #: rc_option_editor.cc:1355
 msgid "Always copy imported files"
@@ -8984,15 +9200,15 @@ msgstr "总是复制导入的文件"
 
 #: rc_option_editor.cc:1362
 msgid "Default folder for new sessions:"
-msgstr ""
+msgstr "新会话的默认文件夹:"
 
 #: rc_option_editor.cc:1370
 msgid "Maximum number of recent sessions"
-msgstr ""
+msgstr "当前会话的最大数量"
 
 #: rc_option_editor.cc:1383
 msgid "Click gain level"
-msgstr ""
+msgstr "点击增益电平"
 
 #: rc_option_editor.cc:1388 route_time_axis.cc:266 route_time_axis.cc:821
 msgid "Automation"
@@ -9000,93 +9216,104 @@ msgstr "自动化"
 
 #: rc_option_editor.cc:1393
 msgid "Thinning factor (larger value => less data)"
-msgstr ""
+msgstr " 稀释参数(较大的数值 => 较少的数据)"
 
 #: rc_option_editor.cc:1402
 msgid "Automation sampling interval (milliseconds)"
-msgstr ""
+msgstr "自动化样本间隔(毫秒)"
 
 #: rc_option_editor.cc:1414
 msgid "Keep record-enable engaged on stop"
-msgstr ""
+msgstr "停止时,保持启用的录制仍在启用中"
 
 #: rc_option_editor.cc:1423
 msgid "Play loop is a transport mode"
-msgstr ""
+msgstr "播放循环是一个播送模式"
 
 #: rc_option_editor.cc:1428
 msgid ""
-"<b>When enabled</b> the loop button does not start playback but forces "
-"playback to always play the loop\n"
+"<b>When enabled</b> the loop button does not start playback but forces playback to "
+"always play the loop\n"
 "\n"
 "<b>When disabled</b> the loop button starts playing the loop, but stop then "
 "cancels loop playback"
 msgstr ""
+"<b>启用时</b> 循环按钮不启动回放,但强制回放总是播放循环\n"
+"\n"
+"<b>禁用时</b> 循环按钮启动播放循环,但停止也取消循环回放"
 
 #: rc_option_editor.cc:1434
 msgid "Stop recording when an xrun occurs"
-msgstr "在xruns出现时停止录音"
+msgstr "在x运行出现时停止录制"
 
 #: rc_option_editor.cc:1439
 msgid ""
-"<b>When enabled</b> %1 will stop recording if an over- or underrun is "
-"detected by the audio engine"
-msgstr ""
+"<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by "
+"the audio engine"
+msgstr "<b>启用时</b> 如果音频引擎检测到一个超载或者欠载运行 %1 将停止录制"
 
 #: rc_option_editor.cc:1445
 msgid "Create markers where xruns occur"
-msgstr "在xruns出现时创建标记"
+msgstr "在x运行出现时创建标记"
 
 #: rc_option_editor.cc:1454
 msgid "Stop at the end of the session"
-msgstr "在会话结尾停止"
+msgstr "在会话终点停止"
 
 #: rc_option_editor.cc:1459
 msgid ""
-"<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the "
-"transport when it reaches the current session end marker\n"
+"<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport when "
+"it reaches the current session end marker\n"
 "\n"
-"<b>When disabled</b> %1 will continue to roll past the session end marker at "
-"all times"
+"<b>When disabled</b> %1 will continue to roll past the session end marker at all "
+"times"
 msgstr ""
+"<b>启用时</b> 如果 %1 是 <b>非录制中</b>,当它达到当前会话的终点标记时它将停止播"
+"送\n"
+"\n"
+"<b>禁用时</b> %1 将继续一直滚动运行到会话终点标记"
 
 #: rc_option_editor.cc:1467
 msgid "Do seamless looping (not possible when slaved to MTC, LTC etc)"
-msgstr ""
+msgstr "做无缝循环(当从属于 MTC,LTC 诸如此类时不可能实现)"
 
 #: rc_option_editor.cc:1472
 msgid ""
-"<b>When enabled</b> this will loop by reading ahead and wrapping around at "
-"the loop point, preventing any need to do a transport locate at the end of "
-"the loop\n"
+"<b>When enabled</b> this will loop by reading ahead and wrapping around at the "
+"loop point, preventing any need to do a transport locate at the end of the loop\n"
 "\n"
-"<b>When disabled</b> looping is done by locating back to the start of the "
-"loop when %1 reaches the end which will often cause a small click or delay"
+"<b>When disabled</b> looping is done by locating back to the start of the loop "
+"when %1 reaches the end which will often cause a small click or delay"
 msgstr ""
+"<b>启用时</b>这将通过预先读取来循环并且在循环点围绕,防止任何需要把播送定位在循环的"
+"终点的情况\n"
+"\n"
+"<b>禁用时</b> 当 %1 到达会经常引起一个轻微识别声或延迟的终点时,通过定位回到循环的"
+"起点而完成循环"
 
 #: rc_option_editor.cc:1480
 msgid "Disable per-track record disarm while rolling"
-msgstr ""
+msgstr "当滚动时禁用预先音轨录制解除"
 
 #: rc_option_editor.cc:1484
 msgid ""
-"<b>When enabled</b> this will prevent you from accidentally stopping "
-"specific tracks recording during a take"
-msgstr ""
+"<b>When enabled</b> this will prevent you from accidentally stopping specific "
+"tracks recording during a take"
+msgstr "<b>启用时</b> 这将防止您在这过程中意外停止指定的音轨录制"
 
 #: rc_option_editor.cc:1489
 msgid "12dB gain reduction during fast-forward and fast-rewind"
-msgstr "快进和倒带时有12dB的增益减少"
+msgstr "快进和倒带时有 12dB 的增益减少"
 
 #: rc_option_editor.cc:1493
 msgid ""
-"This will reduce the unpleasant increase in perceived volume that occurs "
-"when fast-forwarding or rewinding through some kinds of audio"
-msgstr ""
+"This will reduce the unpleasant increase in perceived volume that occurs when fast-"
+"forwarding or rewinding through some kinds of audio"
+msgstr "当快进或倒带通过某些音频类型时,这将减少令人感到不适的可感知音量增加的现像"
 
 #: rc_option_editor.cc:1497
 msgid "Sync/Slave"
-msgstr ""
+msgstr "同步/从属"
 
 #: rc_option_editor.cc:1501
 msgid "External timecode source"
@@ -9094,150 +9321,168 @@ msgstr "外部时间码源"
 
 #: rc_option_editor.cc:1510
 msgid "Match session video frame rate to external timecode"
-msgstr ""
+msgstr "匹配会话视频帧率到外部时间码"
 
 #: rc_option_editor.cc:1516
 msgid ""
-"This option controls the value of the video frame rate <i>while chasing</i> "
-"an external timecode source.\n"
+"This option controls the value of the video frame rate <i>while chasing</i> an "
+"external timecode source.\n"
 "\n"
-"<b>When enabled</b> the session video frame rate will be changed to match "
-"that of the selected external timecode source.\n"
+"<b>When enabled</b> the session video frame rate will be changed to match that of "
+"the selected external timecode source.\n"
 "\n"
-"<b>When disabled</b> the session video frame rate will not be changed to "
-"match that of the selected external timecode source.Instead the frame rate "
-"indication in the main clock will flash red and %1 will convert between the "
-"external timecode standard and the session standard."
+"<b>When disabled</b> the session video frame rate will not be changed to match "
+"that of the selected external timecode source.Instead the frame rate indication in "
+"the main clock will flash red and %1 will convert between the external timecode "
+"standard and the session standard."
 msgstr ""
+"这个选项控制视频帧率的数值<i>当追随</i>一个外部时间码源时\n"
+"\n"
+"<b>启用时</b> 会话视频帧率将被改变为匹配到已选中的外部时间码源。\n"
+"\n"
+"<b>禁用时</b> 会话视频帧率将不会被改变为匹配到已选中的外部时间码源。取而代之的是,"
+"帧率在主计时器里的指示将在转换外部时间代码标准和会话标准两者间转换。"
 
 #: rc_option_editor.cc:1526
 msgid "Sync lock timecode to clock - Disable drift compensation."
-msgstr ""
+msgstr "同步时间代码到计时器——禁用漂移补偿。"
 
 #: rc_option_editor.cc:1532
 msgid ""
-"<b>When enabled</b> %1 will never varispeed when slaved to external "
-"timecode. Sync Lock indicates that the selected external timecode source "
-"shares clock-sync (Black & Burst, Wordclock, etc) with the audio "
-"interface. This option disables drift compensation. The transport speed is "
-"fixed at 1.0.Varispeed LTC will be ignored and cause drift.\n"
+"<b>When enabled</b> %1 will never varispeed when slaved to external timecode. Sync "
+"Lock indicates that the selected external timecode source shares clock-sync (Black "
+"& Burst, Wordclock, etc) with the audio interface. This option disables drift "
+"compensation. The transport speed is fixed at 1.0.Varispeed LTC will be ignored "
+"and cause drift.\n"
 "\n"
-"<b>When disabled</b> %1 will compensate for potential drift, regardless if "
-"the timecode sources shares clock sync."
+"<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
+"timecode sources shares clock sync."
 msgstr ""
+"<b>启用时</b> 在从属于外部时间码时 %1 将不会变速。同步锁定表明已选中的外部时间码源"
+"与音频界面共享计时器同步( Black & Burst, Wordclock,等等)。这个选项禁用漂移"
+"补偿。播送速度被修正于 1.0.Varispeed LTC 将被忽略且引起漂移。\n"
+"\n"
+"<b>禁用时</b> %1 将补偿潜在的漂移,不论时间码源是否共享时间同步。"
 
 #: rc_option_editor.cc:1547
 msgid "Lock to 29.9700 fps instead of 30000/1001"
-msgstr ""
+msgstr "锁定到 29.9700 fps 以替代 30000/1001"
 
 #: rc_option_editor.cc:1553
 msgid ""
 "<b>When enabled</b> the external timecode source is assumed to use 29.97 fps "
 "instead of 30000/1001.\n"
-"SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions "
-"that drop-frame timecode has an accumulated error of -86ms over a 24-hour "
-"period.\n"
-"Drop-frame timecode would compensate exactly for a NTSC color frame rate of "
-"30 * 0.9990 (ie 29.970000). That is not the actual rate. However, some "
-"vendors use that rate - despite it being against the specs - because the "
-"variant of using exactly 29.97 fps has zero timecode drift.\n"
-msgstr ""
+"SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
+"drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
+"Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * "
+"0.9990 (ie 29.970000). That is not the actual rate. However, some vendors use that "
+"rate - despite it being against the specs - because the variant of using exactly "
+"29.97 fps has zero timecode drift.\n"
+msgstr ""
+"<b>启用时</b> 外部时间码源被假定使用 29.97 fps 以替代 30000/1001 。\n"
+"SMPTE 12M-1999 指定 29.97df 为 30000/1001 。进一步的规范提到丢帧时间码有一个在 24 "
+"小时内 -86ms 的累积错误。\n"
+"丢帧时间码将完全补偿 30 * 0.9990 (ie 29.970000)的 NTSC 色彩帧率。那不是实际帧率。"
+"然而,某些厂商使用这帧率——尽管它违背规范——因为使用实际 29.97 fps 的时间码漂移变化"
+"为 0 。\n"
 
 #: rc_option_editor.cc:1563
 msgid "LTC Reader"
-msgstr ""
+msgstr "LTC 阅读器"
 
 #: rc_option_editor.cc:1567
 msgid "LTC incoming port"
-msgstr ""
+msgstr "LTC 导入端口"
 
 #: rc_option_editor.cc:1582
 msgid "LTC Generator"
-msgstr ""
+msgstr "LTC 生成器"
 
 #: rc_option_editor.cc:1587
 msgid "Enable LTC generator"
-msgstr ""
+msgstr "启用 LTC 生成器"
 
 #: rc_option_editor.cc:1594
 msgid "Send LTC while stopped"
-msgstr ""
+msgstr "停止时发送 LTC "
 
 #: rc_option_editor.cc:1600
 msgid ""
 "<b>When enabled</b> %1 will continue to send LTC information even when the "
 "transport (playhead) is not moving"
-msgstr ""
+msgstr "<b>启用时</b> %1 将继续发送 LTC 信息,即使当播送(指针)不再移动"
 
 #: rc_option_editor.cc:1606
 msgid "LTC generator level"
-msgstr ""
+msgstr "LTC 生成器电平"
 
 #: rc_option_editor.cc:1610
 msgid ""
-"Specify the Peak Volume of the generated LTC signal in dbFS. A good value "
-"is  0dBu ^= -18dbFS in an EBU calibrated system"
+"Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu "
+"^= -18dbFS in an EBU calibrated system"
 msgstr ""
+"以 dbFS 指定生成 LTC 信号音量的峰值。建议的数值是 0dBu ^= -18dbFS 在一个 EBU 校准系"
+"统里"
 
 #: rc_option_editor.cc:1622
 msgid "Allow dragging of playhead"
-msgstr ""
+msgstr "允许拖拽指针"
 
 #: rc_option_editor.cc:1630
 msgid "Move relevant automation when audio regions are moved"
-msgstr "当音频区域移除时移除相应自动化"
+msgstr "当音频区域移动时,也移动相关的自动化"
 
 #: rc_option_editor.cc:1638
 msgid "Show meters on tracks in the editor"
-msgstr "在编辑器的音轨显示仪表"
+msgstr "在编辑器的音轨上显示节拍"
 
 #: rc_option_editor.cc:1646
 msgid "Display master-meter in the toolbar"
-msgstr ""
+msgstr "在工具栏里显示主控节拍"
 
 #: rc_option_editor.cc:1653
 msgid "Default fade shape"
-msgstr ""
+msgstr "默认淡化形状"
 
 #: rc_option_editor.cc:1672
 msgid "Regions in active edit groups are edited together"
-msgstr ""
+msgstr "区域位于激活编辑的分组里会被彼此编辑"
 
 #: rc_option_editor.cc:1673
 msgid "whenever they overlap in time"
-msgstr ""
+msgstr "不论何时都及时重叠它们"
 
 #: rc_option_editor.cc:1674
 msgid "only if they have identical length, position and origin"
-msgstr ""
+msgstr "仅在当它们拥有完全相同的长度、位置和原点时"
 
 #: rc_option_editor.cc:1684
 msgid "Make rubberband selection rectangle snap to the grid"
-msgstr ""
+msgstr "使橡皮带已选择部分矩形吸附到网格对齐"
 
 #: rc_option_editor.cc:1692
 msgid "Show waveforms in regions"
-msgstr "显示区域的波形"
+msgstr "在区域内显示波形"
 
 #: rc_option_editor.cc:1700
 msgid "Show gain envelopes in audio regions"
-msgstr ""
+msgstr "在音频区域内显示增益封装"
 
 #: rc_option_editor.cc:1701
 msgid "in all modes"
-msgstr ""
+msgstr "在所有模式内"
 
 #: rc_option_editor.cc:1702
 msgid "only in region gain mode"
-msgstr ""
+msgstr "仅在区域增益模式内"
 
 #: rc_option_editor.cc:1709
 msgid "Waveform scale"
-msgstr "波形标尺"
+msgstr "波形比例"
 
 #: rc_option_editor.cc:1714
 msgid "linear"
-msgstr "先行"
+msgstr "线性"
 
 #: rc_option_editor.cc:1715
 msgid "logarithmic"
@@ -9253,11 +9498,11 @@ msgstr "传统的"
 
 #: rc_option_editor.cc:1727
 msgid "rectified"
-msgstr "整流的"
+msgstr "已矫正的"
 
 #: rc_option_editor.cc:1736
 msgid "Show waveforms for audio while it is being recorded"
-msgstr "在录制音频的时候显示波形"
+msgstr "在音频被录制时显示它的波形"
 
 #: rc_option_editor.cc:1744
 msgid "Show zoom toolbar"
@@ -9265,11 +9510,11 @@ msgstr "显示缩放工具栏"
 
 #: rc_option_editor.cc:1752
 msgid "Update editor window during drags of the summary"
-msgstr ""
+msgstr "当拖拽摘要时,更新编辑器窗口"
 
 #: rc_option_editor.cc:1760
 msgid "Synchronise editor and mixer selection"
-msgstr ""
+msgstr "同步编辑器和混音器已选中部分"
 
 #: rc_option_editor.cc:1767
 msgid "Name new markers"
@@ -9277,31 +9522,34 @@ msgstr "命名新标签"
 
 #: rc_option_editor.cc:1773
 msgid ""
-"If enabled, popup a dialog when a new marker is created to allow its name to "
-"be set as it is created.\n"
+"If enabled, popup a dialog when a new marker is created to allow its name to be "
+"set as it is created.\n"
 "\n"
 "You can always rename markers by right-clicking on them"
 msgstr ""
+"如果启用,当创建一个新标记时会弹出一个对话框,允许为创建它而设置它的名称。\n"
+"\n"
+"您总是可以通过右键单击它们来重命名标志"
 
 #: rc_option_editor.cc:1779
 msgid "Auto-scroll editor window when dragging near its edges"
-msgstr ""
+msgstr "当拖动边缘附近时,自动滚动编辑器窗口"
 
 #: rc_option_editor.cc:1786
 msgid "After splitting selected regions, select"
-msgstr ""
+msgstr "在拆分已选中区域之后,选择"
 
 #: rc_option_editor.cc:1791
 msgid "no regions"
-msgstr ""
+msgstr "无区域"
 
 #: rc_option_editor.cc:1794
 msgid "newly-created regions"
-msgstr ""
+msgstr "新创建的区域"
 
 #: rc_option_editor.cc:1798
 msgid "existing selection and newly-created regions"
-msgstr ""
+msgstr "已存在的已选中部分和新创建的区域"
 
 #: rc_option_editor.cc:1805
 msgid "Buffering"
@@ -9309,11 +9557,11 @@ msgstr "缓冲中"
 
 #: rc_option_editor.cc:1813
 msgid "Record monitoring handled by"
-msgstr ""
+msgstr "录制监控的处理是通过"
 
 #: rc_option_editor.cc:1819
 msgid "via Audio Driver"
-msgstr ""
+msgstr "via 音频驱动"
 
 #: rc_option_editor.cc:1825
 msgid "audio hardware"
@@ -9321,7 +9569,7 @@ msgstr "音频硬件"
 
 #: rc_option_editor.cc:1832
 msgid "Tape machine mode"
-msgstr "磁带机模式"
+msgstr "磁带机器模式"
 
 #: rc_option_editor.cc:1837
 msgid "Connection of tracks and busses"
@@ -9329,15 +9577,15 @@ msgstr "音轨和总线的连接"
 
 #: rc_option_editor.cc:1842
 msgid "Auto-connect master/monitor busses"
-msgstr "自动连接 主控/监视 总线"
+msgstr "自动连接主控/监控总线"
 
 #: rc_option_editor.cc:1849
 msgid "Connect track inputs"
-msgstr "链接音轨输入"
+msgstr "连接音轨输入"
 
 #: rc_option_editor.cc:1854
 msgid "automatically to physical inputs"
-msgstr "自动物理数入"
+msgstr "自动化物理输入"
 
 #: rc_option_editor.cc:1855 rc_option_editor.cc:1868
 msgid "manually"
@@ -9345,11 +9593,11 @@ msgstr "手动"
 
 #: rc_option_editor.cc:1861
 msgid "Connect track and bus outputs"
-msgstr "链接音轨和总线的输出"
+msgstr "连接音轨和总线输出"
 
 #: rc_option_editor.cc:1866
 msgid "automatically to physical outputs"
-msgstr "自动物理数出"
+msgstr "自动化物理输出"
 
 #: rc_option_editor.cc:1867
 msgid "automatically to master bus"
@@ -9361,7 +9609,7 @@ msgstr "异常"
 
 #: rc_option_editor.cc:1877
 msgid "Use DC bias to protect against denormals"
-msgstr "使用偏压直流放置异常"
+msgstr "使用直流偏压针对异常防护"
 
 #: rc_option_editor.cc:1884
 msgid "Processor handling"
@@ -9373,19 +9621,19 @@ msgstr "无处理器处理"
 
 #: rc_option_editor.cc:1896
 msgid "use FlushToZero"
-msgstr ""
+msgstr "使用齐平为零"
 
 #: rc_option_editor.cc:1903
 msgid "use DenormalsAreZero"
-msgstr ""
+msgstr "使用异常齐平为零"
 
 #: rc_option_editor.cc:1910
 msgid "use FlushToZero and DenormalsAreZero"
-msgstr ""
+msgstr "使用齐平为零和异常齐平为零"
 
 #: rc_option_editor.cc:1926
 msgid "Silence plugins when the transport is stopped"
-msgstr ""
+msgstr "当播送停止时插件也无声"
 
 #: rc_option_editor.cc:1934
 msgid "Make new plugins active"
@@ -9397,7 +9645,7 @@ msgstr "启用音频自动分析"
 
 #: rc_option_editor.cc:1952
 msgid "Replicate missing region channels"
-msgstr "复制遗失的区域通道"
+msgstr "复制缺失的区域声道"
 
 #: rc_option_editor.cc:1959 rc_option_editor.cc:1961 rc_option_editor.cc:1976
 #: rc_option_editor.cc:1988 rc_option_editor.cc:2000 rc_option_editor.cc:2012
@@ -9406,123 +9654,123 @@ msgstr "复制遗失的区域通道"
 #: rc_option_editor.cc:2058 rc_option_editor.cc:2066 rc_option_editor.cc:2074
 #: rc_option_editor.cc:2076
 msgid "Solo / mute"
-msgstr "独奏/静音"
+msgstr "独奏 / 静音"
 
 #: rc_option_editor.cc:1964
 msgid "Solo-in-place mute cut (dB)"
-msgstr ""
+msgstr "适当的独奏削减静音(dB)"
 
 #: rc_option_editor.cc:1971
 msgid "Solo controls are Listen controls"
-msgstr ""
+msgstr "单独控制即是试听控制"
 
 #: rc_option_editor.cc:1980
 msgid "Listen Position"
-msgstr ""
+msgstr "试听位置"
 
 #: rc_option_editor.cc:1985
 msgid "after-fader (AFL)"
-msgstr ""
+msgstr "后置淡化(AFL)"
 
 #: rc_option_editor.cc:1986
 msgid "pre-fader (PFL)"
-msgstr ""
+msgstr "前置淡化(PFL)"
 
 #: rc_option_editor.cc:1992
 msgid "PFL signals come from"
-msgstr ""
+msgstr "前置淡化信号来自"
 
 #: rc_option_editor.cc:1997
 msgid "before pre-fader processors"
-msgstr ""
+msgstr "在前置淡化处理器之前"
 
 #: rc_option_editor.cc:1998
 msgid "pre-fader but after pre-fader processors"
-msgstr ""
+msgstr "前置淡化但在前置淡化处理器之后"
 
 #: rc_option_editor.cc:2004
 msgid "AFL signals come from"
-msgstr ""
+msgstr "后置淡化信号来自于"
 
 #: rc_option_editor.cc:2009
 msgid "immediately post-fader"
-msgstr ""
+msgstr "立即后置淡化"
 
 #: rc_option_editor.cc:2010
 msgid "after post-fader processors (before pan)"
-msgstr ""
+msgstr "后置淡化处理器之后(平移之前)"
 
 #: rc_option_editor.cc:2019
 msgid "Exclusive solo"
-msgstr "执行solo"
+msgstr "专属独奏"
 
 #: rc_option_editor.cc:2027
 msgid "Show solo muting"
-msgstr ""
+msgstr "显示独奏静音"
 
 #: rc_option_editor.cc:2035
 msgid "Soloing overrides muting"
-msgstr ""
+msgstr "独奏覆盖静音"
 
 #: rc_option_editor.cc:2040
 msgid "Default track / bus muting options"
-msgstr "默认 音轨/总线 静音选项"
+msgstr "默认音轨 / 总线静音选项"
 
 #: rc_option_editor.cc:2045
 msgid "Mute affects pre-fader sends"
-msgstr ""
+msgstr "静音效果前置淡化发送"
 
 #: rc_option_editor.cc:2053
 msgid "Mute affects post-fader sends"
-msgstr ""
+msgstr "静音效果后置淡化发送"
 
 #: rc_option_editor.cc:2061
 msgid "Mute affects control outputs"
-msgstr ""
+msgstr "静音效果控制输出"
 
 #: rc_option_editor.cc:2069
 msgid "Mute affects main outputs"
-msgstr " ovlivní hlavní výstupy"
+msgstr "静音效果主要输出"
 
 #: rc_option_editor.cc:2074
 msgid "Send Routing"
-msgstr ""
+msgstr "发送路由"
 
 #: rc_option_editor.cc:2079
 msgid "Link panners of Aux and External Sends with main panner by default"
-msgstr ""
+msgstr "链接辅助和外部发送面板和默认的主要面板"
 
 #: rc_option_editor.cc:2087
 msgid "MIDI read-ahead time (seconds)"
-msgstr ""
+msgstr "MIDI 预先读取时间(秒)"
 
 #: rc_option_editor.cc:2105
 msgid "Send MIDI Time Code"
-msgstr "发送MIDI时间码"
+msgstr "发送 MIDI 时间码"
 
 #: rc_option_editor.cc:2113
 msgid "Percentage either side of normal transport speed to transmit MTC"
-msgstr ""
+msgstr "正常播送速度与传输 MTC 之间的百分比"
 
 #: rc_option_editor.cc:2122
 msgid "Obey MIDI Machine Control commands"
-msgstr "遵守MIDI机器控制命令(MTC commands)"
+msgstr "遵守 MIDI 机器控制命令"
 
 #: rc_option_editor.cc:2130
 msgid "Send MIDI Machine Control commands"
-msgstr "发送MIDI机器控制命令(MTC commands)"
+msgstr "发送 MIDI 机器控制命令"
 
 #: rc_option_editor.cc:2138
 msgid "Send MIDI control feedback"
-msgstr "发送MIDI控制反馈"
+msgstr "发送 MIDI 控制反馈"
 
 #: rc_option_editor.cc:2146
 msgid "Inbound MMC device ID"
-msgstr "向内的MMC设备ID"
+msgstr "进场的 MMC 设备 ID"
 
 #: rc_option_editor.cc:2155
 msgid "Outbound MMC device ID"
-msgstr "向外的MMC设备ID"
+msgstr "出场的 MMC 设备 ID"
 
 #: rc_option_editor.cc:2164
 msgid "Initial program change"
@@ -9530,27 +9778,27 @@ msgstr "初始程序改变"
 
 #: rc_option_editor.cc:2173
 msgid "Display first MIDI bank/program as 0"
-msgstr ""
+msgstr "显示第一个 MIDI 库/程序为 0"
 
 #: rc_option_editor.cc:2181
 msgid "Never display periodic MIDI messages (MTC, MIDI Clock)"
-msgstr ""
+msgstr "不再显示定期 MIDI 信息(MTC, MIDI 计时器)"
 
 #: rc_option_editor.cc:2189
 msgid "Sound MIDI notes as they are selected"
-msgstr ""
+msgstr "当 MIDI 音符被选中时发出声音"
 
 #: rc_option_editor.cc:2194
 msgid "Midi Audition"
-msgstr ""
+msgstr "Midi 监听"
 
 #: rc_option_editor.cc:2198
 msgid "Midi Audition Synth (LV2)"
-msgstr ""
+msgstr "Midi 监听合成(LV2)"
 
 #: rc_option_editor.cc:2229 rc_option_editor.cc:2239 rc_option_editor.cc:2241
 msgid "User interaction"
-msgstr ""
+msgstr "用户交互"
 
 #: rc_option_editor.cc:2232
 msgid ""
@@ -9558,6 +9806,9 @@ msgid ""
 "   <i>(requires a restart of %1 to take effect)</i>\n"
 "   <i>(if available for your language preferences)</i>"
 msgstr ""
+"%1 信息的用户交互\n"
+"    <i>(要求重启 %1 以生效)</i>\n"
+"     <i>(如果您的语言首选项可用)</i>"
 
 #: rc_option_editor.cc:2239
 msgid "Keyboard"
@@ -9565,7 +9816,7 @@ msgstr "键盘"
 
 #: rc_option_editor.cc:2249
 msgid "Control surface remote ID"
-msgstr "控制表面移动的ID"
+msgstr "控制面远程 ID"
 
 #: rc_option_editor.cc:2254
 msgid "assigned by user"
@@ -9573,55 +9824,55 @@ msgstr "由用户指定"
 
 #: rc_option_editor.cc:2255
 msgid "follows order of mixer"
-msgstr "混音器的如下顺序"
+msgstr "混音器按如下排序"
 
 #: rc_option_editor.cc:2269 rc_option_editor.cc:2278 rc_option_editor.cc:2287
 #: rc_option_editor.cc:2297 rc_option_editor.cc:2321 rc_option_editor.cc:2334
 #: rc_option_editor.cc:2343
 msgid "Preferences|GUI"
-msgstr ""
+msgstr "首选项|图形用户界面"
 
 #: rc_option_editor.cc:2272
 msgid "Graphically indicate mouse pointer hovering over various widgets"
-msgstr ""
+msgstr "当悬停在各种小部件上面时显示鼠标指针"
 
 #: rc_option_editor.cc:2281
 msgid "Show tooltips if mouse hovers over a control"
-msgstr ""
+msgstr "如果鼠标悬停在一个控件上面时显示工具提示"
 
 #: rc_option_editor.cc:2290
 msgid "Use name highlight bars in region displays (requires a restart)"
-msgstr ""
+msgstr "在区域显示中使用名称突出显示栏(需要重新启动)"
 
 #: rc_option_editor.cc:2303
 msgid "update transport clock display at FPS instead of every 100ms"
-msgstr ""
+msgstr "以 FPS 替代每 100ms 更新播送计时器显示"
 
 #: rc_option_editor.cc:2312
 msgid "Lock timeout (seconds)"
-msgstr ""
+msgstr "锁定超时(秒)"
 
 #: rc_option_editor.cc:2320
 msgid "Lock GUI after this many idle seconds (zero to never lock)"
-msgstr ""
+msgstr "在空闲这么多秒之后锁定图形用户界面(零则永不锁定)"
 
 #: rc_option_editor.cc:2336
 msgid "Mixer Strip"
-msgstr ""
+msgstr "混音器栏"
 
 #: rc_option_editor.cc:2346
 msgid "Use narrow strips in the mixer by default"
-msgstr ""
+msgstr "默认在混音器里使用细长栏"
 
 #: rc_option_editor.cc:2351 rc_option_editor.cc:2365 rc_option_editor.cc:2384
 #: rc_option_editor.cc:2400 rc_option_editor.cc:2416 rc_option_editor.cc:2430
 #: rc_option_editor.cc:2444 rc_option_editor.cc:2446
 msgid "Preferences|Metering"
-msgstr ""
+msgstr "首选项|节拍"
 
 #: rc_option_editor.cc:2355
 msgid "Peak hold time"
-msgstr ""
+msgstr "峰值停留时间"
 
 #: rc_option_editor.cc:2361
 msgid "short"
@@ -9637,43 +9888,43 @@ msgstr "é•¿"
 
 #: rc_option_editor.cc:2369
 msgid "DPM fall-off"
-msgstr ""
+msgstr "DPM 衰减"
 
 #: rc_option_editor.cc:2375
 msgid "slowest [6.6dB/sec]"
-msgstr ""
+msgstr "最慢 [6.6dB/sec]"
 
 #: rc_option_editor.cc:2376
 msgid "slow [8.6dB/sec] (BBC PPM, EBU PPM)"
-msgstr ""
+msgstr "æ…¢ [8.6dB/sec] (BBC PPM, EBU PPM)"
 
 #: rc_option_editor.cc:2377
 msgid "slowish [12.0dB/sec] (DIN)"
-msgstr ""
+msgstr "稍慢 [12.0dB/sec] (DIN)"
 
 #: rc_option_editor.cc:2378
 msgid "moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"
-msgstr ""
+msgstr "稳健 [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"
 
 #: rc_option_editor.cc:2379
 msgid "medium [20dB/sec]"
-msgstr ""
+msgstr "中等 [20dB/sec]"
 
 #: rc_option_editor.cc:2380
 msgid "fast [32dB/sec]"
-msgstr ""
+msgstr "å¿« [32dB/sec]"
 
 #: rc_option_editor.cc:2381
 msgid "faster [46dB/sec]"
-msgstr ""
+msgstr "较快 [46dB/sec]"
 
 #: rc_option_editor.cc:2382
 msgid "fastest [70dB/sec]"
-msgstr ""
+msgstr "最快 [70dB/sec]"
 
 #: rc_option_editor.cc:2388
 msgid "Meter line-up level; 0dBu"
-msgstr ""
+msgstr "节拍排队电平;0dBu"
 
 #: rc_option_editor.cc:2393 rc_option_editor.cc:2409
 msgid "-24dBFS (SMPTE US: 4dBu = -20dBFS)"
@@ -9693,33 +9944,35 @@ msgstr ""
 
 #: rc_option_editor.cc:2398
 msgid ""
-"Configure meter-marks and color-knee point for dBFS scale DPM, set reference "
-"level for IEC1/Nordic, IEC2 PPM and VU meter."
+"Configure meter-marks and color-knee point for dBFS scale DPM, set reference level "
+"for IEC1/Nordic, IEC2 PPM and VU meter."
 msgstr ""
+"配置节拍标志和转角颜色点用于 dBFS 缩放 DPM,为 IEC1/Nordic、IEC2 PPM 和 VU 节拍设置"
+"参考电平。"
 
 #: rc_option_editor.cc:2404
 msgid "IEC1/DIN Meter line-up level; 0dBu"
-msgstr ""
+msgstr "IEC1/DIN 节拍排队电平;0dBu"
 
 #: rc_option_editor.cc:2414
 msgid "Reference level for IEC1/DIN meter."
-msgstr ""
+msgstr "IEC1/DIN 节拍参考电平。"
 
 #: rc_option_editor.cc:2420
 msgid "VU Meter standard"
-msgstr ""
+msgstr "VU 节拍标准"
 
 #: rc_option_editor.cc:2425
 msgid "0VU = -2dBu (France)"
-msgstr ""
+msgstr "0VU = -2dBu (法国)"
 
 #: rc_option_editor.cc:2426
 msgid "0VU = 0dBu (North America, Australia)"
-msgstr ""
+msgstr "0VU = 0dBu (北美,澳洲)"
 
 #: rc_option_editor.cc:2427
 msgid "0VU = +4dBu (standard)"
-msgstr ""
+msgstr "0VU = +4dBu (标准)"
 
 #: rc_option_editor.cc:2428
 msgid "0VU = +8dBu"
@@ -9727,21 +9980,21 @@ msgstr ""
 
 #: rc_option_editor.cc:2434
 msgid "Peak threshold [dBFS]"
-msgstr ""
+msgstr "峰值临界值 [dBFS]"
 
 #: rc_option_editor.cc:2442
 msgid ""
-"Specify the audio signal level in dbFS at and above which the meter-peak "
-"indicator will flash red."
-msgstr ""
+"Specify the audio signal level in dbFS at and above which the meter-peak indicator "
+"will flash red."
+msgstr "以 dbFS 指定音频信号电平,达到以及超过节拍峰时,值指示器将闪烁红灯。"
 
 #: rc_option_editor.cc:2449
 msgid "LED meter style"
-msgstr ""
+msgstr "LED 节拍类型"
 
 #: rc_option_editor.cc:2457
 msgid "Theme"
-msgstr ""
+msgstr "主题"
 
 #: region_editor.cc:79
 msgid "audition this region"
@@ -9749,35 +10002,35 @@ msgstr "监听此区域"
 
 #: region_editor.cc:88 region_layering_order_editor.cc:75
 msgid "Position:"
-msgstr "位置:"
+msgstr "位置:"
 
 #: region_editor.cc:90 add_video_dialog.cc:155
 msgid "End:"
-msgstr "终点:"
+msgstr "终点:"
 
 #: region_editor.cc:92 sfdb_ui.cc:145
 msgid "Length:"
-msgstr "长度:"
+msgstr "长度:"
 
 #: region_editor.cc:94
 msgid "Sync point (relative to region):"
-msgstr "同步点 (相对于区域):"
+msgstr "同步点(相对于区域):"
 
 #: region_editor.cc:96
 msgid "Sync point (absolute):"
-msgstr "同步点 (绝对的):"
+msgstr "同步点(绝对):"
 
 #: region_editor.cc:98
 msgid "File start:"
-msgstr "文件开始:"
+msgstr "文件起点:"
 
 #: region_editor.cc:102
 msgid "Sources:"
-msgstr "源:"
+msgstr "源:"
 
 #: region_editor.cc:104
 msgid "Source:"
-msgstr "源:"
+msgstr "源:"
 
 #: region_editor.cc:166
 msgid "Region '%1'"
@@ -9785,11 +10038,11 @@ msgstr "区域 '%1'"
 
 #: region_editor.cc:273
 msgid "change region start position"
-msgstr "改变区域开始位置"
+msgstr "改变区域起点位置"
 
 #: region_editor.cc:289
 msgid "change region end position"
-msgstr "改变区域结束位置"
+msgstr "改变区域终点位置"
 
 #: region_editor.cc:309
 msgid "change region length"
@@ -9801,7 +10054,7 @@ msgstr "改变区域同步点"
 
 #: region_layering_order_editor.cc:42
 msgid "RegionLayeringOrderEditor"
-msgstr ""
+msgstr "区域分层排序编辑器"
 
 #: region_layering_order_editor.cc:55
 msgid "Region Name"
@@ -9809,33 +10062,32 @@ msgstr "区域名称"
 
 #: region_layering_order_editor.cc:72
 msgid "Track:"
-msgstr "音轨:"
+msgstr "音轨:"
 
 #: region_layering_order_editor.cc:104
 msgid "Choose Top Region"
-msgstr "选择置顶区域"
+msgstr "选择顶部区域"
 
 #: region_view.cc:277
 msgid "SilenceText"
-msgstr ""
+msgstr "无声文本"
 
 #: region_view.cc:292 region_view.cc:311
 msgid "minutes"
-msgstr "分数"
+msgstr "分钟"
 
 #: region_view.cc:295 region_view.cc:314
 msgid "msecs"
-msgstr "毫秒数"
+msgstr "毫秒"
 
 #: region_view.cc:298 region_view.cc:317
 msgid "secs"
-msgstr "秒数"
+msgstr "秒"
 
 #: region_view.cc:301
 msgid "%1 silent segment"
 msgid_plural "%1 silent segments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%1 无声片段"
 
 #: region_view.cc:303
 msgid "shortest = %1 %2"
@@ -9847,7 +10099,7 @@ msgid ""
 "  (shortest audible segment = %1 %2)"
 msgstr ""
 "\n"
-"  (最短的可听片段 = %1 %2)"
+"  (最短的可听见片段 = %1 %2)"
 
 #: return_ui.cc:102
 msgid "Return "
@@ -9855,31 +10107,31 @@ msgstr "返回"
 
 #: rhythm_ferret.cc:48
 msgid "Percussive Onset"
-msgstr ""
+msgstr "敲击启动"
 
 #: rhythm_ferret.cc:49
 msgid "Note Onset"
-msgstr ""
+msgstr "音符启动"
 
 #: rhythm_ferret.cc:54
 msgid "Energy Based"
-msgstr ""
+msgstr "能量基准"
 
 #: rhythm_ferret.cc:55
 msgid "Spectral Difference"
-msgstr ""
+msgstr "波谱差异"
 
 #: rhythm_ferret.cc:56
 msgid "High-Frequency Content"
-msgstr ""
+msgstr "高频内容"
 
 #: rhythm_ferret.cc:57
 msgid "Complex Domain"
-msgstr ""
+msgstr "复合领域"
 
 #: rhythm_ferret.cc:58
 msgid "Phase Deviation"
-msgstr ""
+msgstr "相位偏差"
 
 #: rhythm_ferret.cc:59
 msgid "Kullback-Liebler"
@@ -9887,23 +10139,23 @@ msgstr ""
 
 #: rhythm_ferret.cc:60
 msgid "Modified Kullback-Liebler"
-msgstr ""
+msgstr "改良的 Kullback-Liebler"
 
 #: rhythm_ferret.cc:65
 msgid "Split region"
-msgstr ""
+msgstr "拆分区域"
 
 #: rhythm_ferret.cc:66
 msgid "Snap regions"
-msgstr ""
+msgstr "吸附区域"
 
 #: rhythm_ferret.cc:67
 msgid "Conform regions"
-msgstr ""
+msgstr "适应区域"
 
 #: rhythm_ferret.cc:72
 msgid "Rhythm Ferret"
-msgstr "节奏搜索"
+msgstr "节奏探测"
 
 #: rhythm_ferret.cc:78
 msgid "Analyze"
@@ -9919,15 +10171,15 @@ msgstr "触发间隙"
 
 #: rhythm_ferret.cc:122 strip_silence_dialog.cc:64
 msgid "Threshold"
-msgstr "阈值"
+msgstr "临界值"
 
 #: rhythm_ferret.cc:127
 msgid "Peak threshold"
-msgstr "峰阈值"
+msgstr "峰值临界值"
 
 #: rhythm_ferret.cc:132
 msgid "Silence threshold"
-msgstr "无声阈值"
+msgstr "无声临界值"
 
 #: rhythm_ferret.cc:137
 msgid "Sensitivity"
@@ -9939,11 +10191,11 @@ msgstr "操作"
 
 #: rhythm_ferret.cc:355
 msgid "split regions (rhythm ferret)"
-msgstr "分离区域 (节奏搜索)"
+msgstr "拆分区域(节奏探测)"
 
 #: route_group_dialog.cc:42
 msgid "Track/bus Group"
-msgstr ""
+msgstr "音轨/总线分组"
 
 #: route_group_dialog.cc:47
 msgid "Relative"
@@ -9955,11 +10207,11 @@ msgstr "静音中"
 
 #: route_group_dialog.cc:50
 msgid "Record enable"
-msgstr "启用录音"
+msgstr "启用录制"
 
 #: route_group_dialog.cc:52
 msgid "Active state"
-msgstr ""
+msgstr "激活状态"
 
 #: route_group_dialog.cc:53 route_group_dialog.cc:82 theme_manager.cc:90
 msgid "Color"
@@ -9967,7 +10219,7 @@ msgstr "颜色"
 
 #: route_group_dialog.cc:59
 msgid "RouteGroupDialog"
-msgstr ""
+msgstr "路由分组对话框"
 
 #: route_group_dialog.cc:100
 msgid "<b>Sharing</b>"
@@ -9975,7 +10227,7 @@ msgstr "<b>共享中</b>"
 
 #: route_group_dialog.cc:200
 msgid "The group name is not unique. Please use a different name."
-msgstr ""
+msgstr "分组名称有重复。请使用另一个名称。"
 
 #: route_params_ui.cc:84
 msgid "Tracks/Busses"
@@ -9991,16 +10243,16 @@ msgstr "输出"
 
 #: route_params_ui.cc:105
 msgid "Plugins, Inserts & Sends"
-msgstr ""
+msgstr "插件,插入和发送"
 
 #: route_params_ui.cc:209
 msgid "route display list item for renamed route not found!"
-msgstr ""
+msgstr "未找到已重命名路由的路由显示列表条目!"
 
 #: route_params_ui.cc:279 route_params_ui.cc:307
 #, c-format
 msgid "Playback delay: %<PRId64> samples"
-msgstr "回放延迟: %<PRId64> 采样"
+msgstr "回放延迟: %<PRId64> 采样"
 
 #: route_params_ui.cc:499
 msgid "NO TRACK"
@@ -10008,11 +10260,11 @@ msgstr "没有音轨"
 
 #: route_params_ui.cc:637 route_params_ui.cc:638
 msgid "No Track or Bus Selected"
-msgstr "没有选择音轨或总线"
+msgstr "没有音轨或总线被选中"
 
 #: route_time_axis.cc:181
 msgid "Record (Right-click for Step Edit)"
-msgstr "录音(右键单步调整)"
+msgstr "录制(右键点击步进编辑)"
 
 #: route_time_axis.cc:184
 msgid "Record"
@@ -10020,11 +10272,11 @@ msgstr "录制"
 
 #: route_time_axis.cc:254
 msgid "Route Group"
-msgstr ""
+msgstr "路由分组"
 
 #: route_time_axis.cc:264
 msgid "MIDI Controllers and Automation"
-msgstr ""
+msgstr "MIDI 控制器和自动化"
 
 #: route_time_axis.cc:495
 msgid "Show All Automation"
@@ -10040,15 +10292,15 @@ msgstr "隐藏所有自动化"
 
 #: route_time_axis.cc:510
 msgid "Processor automation"
-msgstr ""
+msgstr "处理器自动化"
 
 #: route_time_axis.cc:517
 msgid "Fader"
-msgstr ""
+msgstr "淡化"
 
 #: route_time_axis.cc:535
 msgid "Pan"
-msgstr ""
+msgstr "平移"
 
 #: route_time_axis.cc:626
 msgid "Overlaid"
@@ -10056,7 +10308,7 @@ msgstr "重叠"
 
 #: route_time_axis.cc:632
 msgid "Stacked"
-msgstr ""
+msgstr "堆栈"
 
 #: route_time_axis.cc:640
 msgid "Layers"
@@ -10064,19 +10316,19 @@ msgstr "层"
 
 #: route_time_axis.cc:709
 msgid "Automatic (based on I/O connections)"
-msgstr "自动的(基于I/O连接)"
+msgstr "自动的(基于输入/输出连接)"
 
 #: route_time_axis.cc:718
 msgid "(Currently: Existing Material)"
-msgstr "(当前:现有材料)"
+msgstr "(当前:现有材料)"
 
 #: route_time_axis.cc:721
 msgid "(Currently: Capture Time)"
-msgstr "(当前:捕获时间)"
+msgstr "(当前:捕获时间)"
 
 #: route_time_axis.cc:729
 msgid "Align With Existing Material"
-msgstr "与已有材料对齐"
+msgstr "与现有材料对齐"
 
 #: route_time_axis.cc:734
 msgid "Align With Capture Time"
@@ -10088,7 +10340,7 @@ msgstr "对齐"
 
 #: route_time_axis.cc:774
 msgid "Normal Mode"
-msgstr "一般模式"
+msgstr "正常模式"
 
 #: route_time_axis.cc:780
 msgid "Tape Mode"
@@ -10096,11 +10348,11 @@ msgstr "磁带模式"
 
 #: route_time_axis.cc:786
 msgid "Non-Layered Mode"
-msgstr "非底层模式"
+msgstr "不分层模式"
 
 #: route_time_axis.cc:792
 msgid "Record Mode"
-msgstr ""
+msgstr "录制模式"
 
 #: route_time_axis.cc:799 route_time_axis.cc:1789
 msgid "Playlist"
@@ -10112,35 +10364,35 @@ msgstr "重命名播放列表"
 
 #: route_time_axis.cc:1098
 msgid "New name for playlist:"
-msgstr "新的播放列表名称"
+msgstr "播放列表的新名称:"
 
 #: route_time_axis.cc:1183
 msgid "New Copy Playlist"
-msgstr "新拷贝播放列表"
+msgstr "新建播放列表拷贝"
 
 #: route_time_axis.cc:1184 route_time_axis.cc:1237
 msgid "Name for new playlist:"
-msgstr "新播放列表名"
+msgstr "新播放列表名称:"
 
 #: route_time_axis.cc:1236
 msgid "New Playlist"
-msgstr "新的播放列表"
+msgstr "新建播放列表"
 
 #: route_time_axis.cc:1436
 msgid "You cannot create a track with that name as it is reserved for %1"
-msgstr "无法创建音轨,因为"
+msgstr "无法以此名称创建音轨,因为它被 %1 保留使用"
 
 #: route_time_axis.cc:1678
 msgid "New Copy..."
-msgstr "新拷贝"
+msgstr "新建拷贝…"
 
 #: route_time_axis.cc:1682
 msgid "New Take"
-msgstr ""
+msgstr "新建磁带"
 
 #: route_time_axis.cc:1683
 msgid "Copy Take"
-msgstr ""
+msgstr "拷贝磁带"
 
 #: route_time_axis.cc:1688
 msgid "Clear Current"
@@ -10148,15 +10400,15 @@ msgstr "清除当前"
 
 #: route_time_axis.cc:1691
 msgid "Select From All..."
-msgstr "选择所有"
+msgstr "选择所有…"
 
 #: route_time_axis.cc:1779
 msgid "Take: %1.%2"
-msgstr ""
+msgstr "磁带:%1.%2"
 
 #: route_time_axis.cc:2169 selection.cc:1007 selection.cc:1061
 msgid "programming error: "
-msgstr "程序错误:"
+msgstr "程序错误:"
 
 #: route_time_axis.cc:2585
 msgid "Underlays"
@@ -10168,15 +10420,15 @@ msgstr "移除 \"%1\""
 
 #: route_time_axis.cc:2638 route_time_axis.cc:2675
 msgid "programming error: underlay reference pointer pairs are inconsistent!"
-msgstr "程序错误:底层参考指针对不一致"
+msgstr "程序错误:底层参考指针搭配不一致!"
 
 #: route_time_axis.cc:2702
 msgid "After-fade listen (AFL)"
-msgstr ""
+msgstr "后置淡化试听(AFL)"
 
 #: route_time_axis.cc:2706
 msgid "Pre-fade listen (PFL)"
-msgstr ""
+msgstr "前置淡化试听(PFL)"
 
 #: route_ui.cc:140
 msgid "Mute this track"
@@ -10184,103 +10436,103 @@ msgstr "静音此音轨"
 
 #: route_ui.cc:144
 msgid "Mute other (non-soloed) tracks"
-msgstr "静音其他(非solo的)音轨"
+msgstr "静音其它(非独奏)音轨"
 
 #: route_ui.cc:150
 msgid "Enable recording on this track"
-msgstr "在此音轨启用录音"
+msgstr "在此音轨启用录制"
 
 #: route_ui.cc:158
 msgid "make mixer strips show sends to this bus"
-msgstr ""
+msgstr "让混音器栏显示发送到该总线"
 
 #: route_ui.cc:163
 msgid "Monitor input"
-msgstr "监听输入"
+msgstr "监控输入"
 
 #: route_ui.cc:169
 msgid "Monitor playback"
-msgstr "监听回放"
+msgstr "监控回放"
 
 #: route_ui.cc:676
 msgid "Not connected to AudioEngine - cannot engage record"
-msgstr ""
+msgstr "未连接到音频引擎——无法从事录制"
 
 #: route_ui.cc:875
 msgid "Step Entry"
-msgstr ""
+msgstr "步进入口"
 
 #: route_ui.cc:948
 msgid "Assign all tracks (prefader)"
-msgstr ""
+msgstr "指定所有音轨(前置淡化)"
 
 #: route_ui.cc:952
 msgid "Assign all tracks and buses (prefader)"
-msgstr ""
+msgstr "指定所有音轨和总线(前置淡化)"
 
 #: route_ui.cc:956
 msgid "Assign all tracks (postfader)"
-msgstr ""
+msgstr "指定所有音轨(后置淡化)"
 
 #: route_ui.cc:960
 msgid "Assign all tracks and buses (postfader)"
-msgstr ""
+msgstr "指定所有音轨和总线(后置淡化)"
 
 #: route_ui.cc:964
 msgid "Assign selected tracks (prefader)"
-msgstr ""
+msgstr "指定已选中的音轨(前置淡化)"
 
 #: route_ui.cc:968
 msgid "Assign selected tracks and buses (prefader)"
-msgstr ""
+msgstr "指定已选中的音轨和总线(前置淡化)"
 
 #: route_ui.cc:971
 msgid "Assign selected tracks (postfader)"
-msgstr ""
+msgstr "指定已选中的音轨(后置淡化)"
 
 #: route_ui.cc:975
 msgid "Assign selected tracks and buses (postfader)"
-msgstr ""
+msgstr "指定已选中的音轨和总线(后置淡化)"
 
 #: route_ui.cc:978
 msgid "Copy track/bus gains to sends"
-msgstr ""
+msgstr "复制音轨/总线增益到发送"
 
 #: route_ui.cc:979
 msgid "Set sends gain to -inf"
-msgstr ""
+msgstr "设置发送增益到 -inf"
 
 #: route_ui.cc:980
 msgid "Set sends gain to 0dB"
-msgstr ""
+msgstr "设置发送增益到 0dB"
 
 #: route_ui.cc:1300
 msgid "Solo Isolate"
-msgstr "Solo隔离"
+msgstr "独奏隔离"
 
 #: route_ui.cc:1307
 msgid "Solo Safe"
-msgstr "Solo安全"
+msgstr "独奏安全"
 
 #: route_ui.cc:1329
 msgid "Pre Fader Sends"
-msgstr ""
+msgstr "前置淡化发送"
 
 #: route_ui.cc:1335
 msgid "Post Fader Sends"
-msgstr ""
+msgstr "后置淡化发送"
 
 #: route_ui.cc:1341
 msgid "Control Outs"
-msgstr ""
+msgstr "控制输出"
 
 #: route_ui.cc:1347
 msgid "Main Outs"
-msgstr ""
+msgstr "主要输出"
 
 #: route_ui.cc:1479
 msgid "Color Selection"
-msgstr "颜色选择"
+msgstr "颜色已选择部分"
 
 #: route_ui.cc:1564
 msgid ""
@@ -10290,11 +10542,11 @@ msgid ""
 "\n"
 "(This action cannot be undone, and the session file will be overwritten)"
 msgstr ""
-"你确定移除音轨 \"%1\"?\n"
+"您是否真的要移除音轨 \"%1\"?\n"
 "\n"
-"这样你可能会失去使用此音轨的播放列表.\n"
+"您也可能会失去使用此音轨使用的播放列表。\n"
 "\n"
-"(此动作不可撤销, 而且此会话文件将会被重新写入!)"
+"(此操作不可撤销,而且此会话文件将会被重写覆盖)"
 
 #: route_ui.cc:1566
 msgid ""
@@ -10302,9 +10554,9 @@ msgid ""
 "\n"
 "(This action cannot be undone, and the session file will be overwritten)"
 msgstr ""
-"你确定移除总线\"%1\" ?\n"
+"您是否真的要移除总线\"%1\" ?\n"
 "\n"
-"(此动作不可撤销, 而且此会话文件将会被重新写入!)"
+"(此操作不可撤销,而且此会话文件将会被重写覆盖)"
 
 #: route_ui.cc:1574
 msgid "Remove track"
@@ -10319,8 +10571,8 @@ msgid ""
 "The use of colons (':') is discouraged in track and bus names.\n"
 "Do you want to use this new name?"
 msgstr ""
-"不建议使用 ':' 作为音轨和总线名称.\n"
-"你确定使用这个名称?"
+"建议不要在音轨和总线名称中使用冒号(“ : ”)。\n"
+"您是否确定使用这个新名称?"
 
 #: route_ui.cc:1608
 msgid "Use the new name"
@@ -10340,15 +10592,15 @@ msgstr "重命名总线"
 
 #: route_ui.cc:1692
 msgid ": comment editor"
-msgstr ": 注释编辑器"
+msgstr ":注释编辑器"
 
 #: route_ui.cc:1858
 msgid " latency"
-msgstr " 延迟"
+msgstr "延迟"
 
 #: route_ui.cc:1871
 msgid "Cannot create route template directory %1"
-msgstr "无法创建模板根目录%1"
+msgstr "无法创建路由模板目录 %1"
 
 #: route_ui.cc:1877
 msgid "Save As Template"
@@ -10356,15 +10608,15 @@ msgstr "另存为模板"
 
 #: route_ui.cc:1878
 msgid "Template name:"
-msgstr "模板名称:"
+msgstr "模板名称:"
 
 #: route_ui.cc:1959
 msgid "Remote Control ID"
-msgstr "移除控制ID"
+msgstr "移除控制 ID"
 
 #: route_ui.cc:1969
 msgid "Remote control ID:"
-msgstr "移除控制ID:"
+msgstr "移除控制 ID:"
 
 #: route_ui.cc:1983
 msgid ""
@@ -10373,14 +10625,18 @@ msgid ""
 "\n"
 "The remote control ID of %3 cannot be changed."
 msgstr ""
+" %1 的远程控制 ID 是:%2\n"
+"\n"
+"\n"
+"%3 的远程控制 ID 无法改变。"
 
 #: route_ui.cc:1987
 msgid "the master bus"
-msgstr ""
+msgstr "主控总线"
 
 #: route_ui.cc:1987
 msgid "the monitor bus"
-msgstr ""
+msgstr "监控总线"
 
 #: route_ui.cc:1989
 msgid ""
@@ -10389,31 +10645,37 @@ msgid ""
 "\n"
 "Remote Control IDs are currently determined by track/bus ordering in %6.\n"
 "\n"
-"%3Use the User Interaction tab of the Preferences window if you want to "
-"change this%4"
+"%3Use the User Interaction tab of the Preferences window if you want to change this"
+"%4"
 msgstr ""
+"%5 的远程控制 ID 是:%2\n"
+"\n"
+"\n"
+"远程控制 IDs 是由当前音轨/总线在 %6 里的排序所决定的。\n"
+"\n"
+"如果您想改变 %4,%3 使用首选项窗口的用户交互选项卡"
 
 #: route_ui.cc:2046
 msgid ""
-"Left-click to invert (phase reverse) channel %1 of this track.  Right-click "
-"to show menu."
-msgstr ""
+"Left-click to invert (phase reverse) channel %1 of this track.  Right-click to "
+"show menu."
+msgstr "左键点击反转(相位反转)该音轨的声道 %1 。右键点击显示菜单。"
 
 #: route_ui.cc:2048
 msgid "Click to show a menu of channels for inversion (phase reverse)"
-msgstr ""
+msgstr "点击显示声道反转(相位反转)菜单"
 
 #: search_path_option.cc:35
 msgid "Select folder to search for media"
-msgstr ""
+msgstr "选择目录以便搜索媒体"
 
 #: search_path_option.cc:44
 msgid "Click to add a new location"
-msgstr ""
+msgstr "点击添加一个新位置"
 
 #: search_path_option.cc:51
 msgid "the session folder"
-msgstr ""
+msgstr "会话文件夹"
 
 #: send_ui.cc:134
 msgid "Send "
@@ -10421,31 +10683,31 @@ msgstr "发送"
 
 #: session_dialog.cc:61
 msgid "Session Setup"
-msgstr ""
+msgstr "发送设置"
 
 #: session_dialog.cc:66
 msgid "Advanced options ..."
-msgstr ""
+msgstr "高级选项…"
 
 #: session_dialog.cc:263
 msgid "New Session"
-msgstr "新会话"
+msgstr "新建会话"
 
 #: session_dialog.cc:301
 msgid "Check the website for more..."
-msgstr ""
+msgstr "查询网站以得到更多…"
 
 #: session_dialog.cc:304
 msgid "Click to open the program website in your web browser"
-msgstr ""
+msgstr "点击以便在您的网页浏览器打开程序网站"
 
 #: session_dialog.cc:324
 msgid "Sample Rate"
-msgstr ""
+msgstr "采样率"
 
 #: session_dialog.cc:325
 msgid "Disk Format"
-msgstr ""
+msgstr "硬盘格式化"
 
 #: session_dialog.cc:343
 msgid "Select session file"
@@ -10453,23 +10715,23 @@ msgstr "选择会话文件"
 
 #: session_dialog.cc:358
 msgid "Other Sessions"
-msgstr ""
+msgstr "其它会话"
 
 #: session_dialog.cc:384
 msgid "Open"
-msgstr "打开 "
+msgstr "打开"
 
 #: session_dialog.cc:451
 msgid "Session name:"
-msgstr "会话名称:"
+msgstr "会话名称:"
 
 #: session_dialog.cc:473
 msgid "Create session folder in:"
-msgstr "在创建会话文件夹:"
+msgstr "创建会话文件夹在:"
 
 #: session_dialog.cc:496
 msgid "Select folder for session"
-msgstr "为会话选择一个文件夹"
+msgstr "为会话选择文件夹"
 
 #: session_dialog.cc:525
 msgid "Use this template"
@@ -10481,15 +10743,15 @@ msgstr "没有模板"
 
 #: session_dialog.cc:663 session_dialog.cc:699
 msgid "32 bit float"
-msgstr ""
+msgstr "32 位浮点"
 
 #: session_dialog.cc:666 session_dialog.cc:702
 msgid "24 bit"
-msgstr ""
+msgstr "24 位"
 
 #: session_dialog.cc:669 session_dialog.cc:705
 msgid "16 bit"
-msgstr ""
+msgstr "16 位"
 
 #: session_dialog.cc:747 session_dialog.cc:748 session_dialog.cc:749
 msgid "channels"
@@ -10513,7 +10775,7 @@ msgstr "创建主控总线"
 
 #: session_dialog.cc:783
 msgid "Automatically connect to physical inputs"
-msgstr ""
+msgstr "自动连接到物理输入"
 
 #: session_dialog.cc:790 session_dialog.cc:849
 msgid "Use only"
@@ -10525,11 +10787,11 @@ msgstr "自动连接到输出"
 
 #: session_dialog.cc:865
 msgid "... to master bus"
-msgstr "... 到主控总线"
+msgstr "…到主控总线"
 
 #: session_dialog.cc:875
 msgid "... to physical outputs"
-msgstr "... 到物理输出"
+msgstr "…到物理输出"
 
 #: session_import_dialog.cc:65
 msgid "Import from Session"
@@ -10541,11 +10803,11 @@ msgstr "元素"
 
 #: session_import_dialog.cc:111
 msgid "Cannot load XML for session from %1"
-msgstr "无法从 %1 为会话载入XML"
+msgstr "无法从 %1 为会话载入 XML"
 
 #: session_import_dialog.cc:128 session_import_dialog.cc:212
 msgid "Some elements had errors in them. Please see the log for details"
-msgstr "一些元素出错,请查看日志文件"
+msgstr "一些元素出错,详情请参阅日志文件"
 
 #: session_import_dialog.cc:164
 msgid "Import from session"
@@ -10553,51 +10815,51 @@ msgstr "从会话导入"
 
 #: session_import_dialog.cc:228
 msgid "This will select all elements of this type!"
-msgstr "这将选择所有此类型的所有元素"
+msgstr "这将选择此类型的所有元素!"
 
 #: session_metadata_dialog.cc:285
 msgid "EAN Check digit OK"
-msgstr ""
+msgstr "EAN 校验数位正常"
 
 #: session_metadata_dialog.cc:289
 msgid "EAN Check digit error"
-msgstr ""
+msgstr "EAN 校验数位出错"
 
 #: session_metadata_dialog.cc:289
 msgid "expected"
-msgstr ""
+msgstr "期望"
 
 #: session_metadata_dialog.cc:294
 msgid "EAN Length error"
-msgstr ""
+msgstr "EAN 长度错误"
 
 #: session_metadata_dialog.cc:423
 msgid "Field"
-msgstr ""
+msgstr "字段"
 
 #: session_metadata_dialog.cc:427
 msgid "Values (current value on top)"
-msgstr ""
+msgstr "数值(当前数值位于顶部)"
 
 #: session_metadata_dialog.cc:641
 msgid "User"
-msgstr ""
+msgstr "用户"
 
 #: session_metadata_dialog.cc:649
 msgid "Email"
-msgstr ""
+msgstr "电子邮件"
 
 #: session_metadata_dialog.cc:652
 msgid "Web"
-msgstr ""
+msgstr "网站"
 
 #: session_metadata_dialog.cc:655
 msgid "Organization"
-msgstr ""
+msgstr "组织"
 
 #: session_metadata_dialog.cc:658
 msgid "Country"
-msgstr ""
+msgstr "国家"
 
 #: session_metadata_dialog.cc:672
 msgid "Title"
@@ -10609,7 +10871,7 @@ msgstr "音轨序号"
 
 #: session_metadata_dialog.cc:678
 msgid "Subtitle"
-msgstr "子标题"
+msgstr "副标题"
 
 #: session_metadata_dialog.cc:681
 msgid "Grouping"
@@ -10645,35 +10907,35 @@ msgstr "专辑艺术家"
 
 #: session_metadata_dialog.cc:715
 msgid "Total Tracks"
-msgstr ""
+msgstr "音轨总数"
 
 #: session_metadata_dialog.cc:718
 msgid "Disc Subtitle"
-msgstr ""
+msgstr "光盘副标题"
 
 #: session_metadata_dialog.cc:721
 msgid "Disc Number"
-msgstr "Disc Number"
+msgstr "光盘编号"
 
 #: session_metadata_dialog.cc:724
 msgid "Total Discs"
-msgstr ""
+msgstr "光盘总数"
 
 #: session_metadata_dialog.cc:727
 msgid "Compilation"
-msgstr ""
+msgstr "编纂"
 
 #: session_metadata_dialog.cc:730
 msgid "ISRC"
-msgstr ""
+msgstr "ISRC 国际标准音像制品编码"
 
 #: session_metadata_dialog.cc:733
 msgid "EAN barcode"
-msgstr ""
+msgstr "EAN 条形码"
 
 #: session_metadata_dialog.cc:746
 msgid "People"
-msgstr ""
+msgstr "民族"
 
 #: session_metadata_dialog.cc:751
 msgid "Lyricist"
@@ -10681,11 +10943,11 @@ msgstr "作词"
 
 #: session_metadata_dialog.cc:754
 msgid "Composer"
-msgstr ""
+msgstr "作曲家"
 
 #: session_metadata_dialog.cc:757
 msgid "Conductor"
-msgstr ""
+msgstr "指挥家"
 
 #: session_metadata_dialog.cc:760
 msgid "Remixer"
@@ -10693,35 +10955,35 @@ msgstr "混音师"
 
 #: session_metadata_dialog.cc:763
 msgid "Arranger"
-msgstr ""
+msgstr "编曲者"
 
 #: session_metadata_dialog.cc:766
 msgid "Engineer"
-msgstr ""
+msgstr "工程师"
 
 #: session_metadata_dialog.cc:769
 msgid "Producer"
-msgstr ""
+msgstr "制片人"
 
 #: session_metadata_dialog.cc:772
 msgid "DJ Mixer"
-msgstr ""
+msgstr "DJ 混音器"
 
 #: session_metadata_dialog.cc:775
 msgid "Metadata|Mixer"
-msgstr ""
+msgstr "元数据|混音器"
 
 #: session_metadata_dialog.cc:783
 msgid "School"
-msgstr ""
+msgstr "院校"
 
 #: session_metadata_dialog.cc:788
 msgid "Instructor"
-msgstr ""
+msgstr "指导员"
 
 #: session_metadata_dialog.cc:791
 msgid "Course"
-msgstr ""
+msgstr "过程"
 
 #: session_metadata_dialog.cc:799
 msgid "Edit Session Metadata"
@@ -10729,25 +10991,27 @@ msgstr "标记会话元数据"
 
 #: session_metadata_dialog.cc:830
 msgid "Import session metadata"
-msgstr "载入会话元数据"
+msgstr "导入会话元数据"
 
 #: session_metadata_dialog.cc:851
 msgid "Choose session to import metadata from"
-msgstr ""
+msgstr "选择导入元数据的来源会话"
 
 #: session_metadata_dialog.cc:889
 msgid "This session file could not be read!"
-msgstr "此会话文件无法读入!"
+msgstr "此会话文件无法读取!"
 
 #: session_metadata_dialog.cc:899
 msgid ""
 "The session file didn't contain metadata!\n"
 "Maybe this is an old session format?"
 msgstr ""
+"此会话文件不包含元数据!\n"
+"也许这是一个旧的会话格式?"
 
 #: session_metadata_dialog.cc:918
 msgid "Import all from:"
-msgstr ""
+msgstr "导入所有从:"
 
 #: session_option_editor.cc:32
 msgid "Session Properties"
@@ -10759,15 +11023,15 @@ msgstr "时间码设置"
 
 #: session_option_editor.cc:45
 msgid "Timecode frames-per-second"
-msgstr "时间码 帧数/秒"
+msgstr "时间码帧数每秒"
 
 #: session_option_editor.cc:50
 msgid "23.976"
-msgstr "23.976"
+msgstr ""
 
 #: session_option_editor.cc:51
 msgid "24"
-msgstr "24"
+msgstr ""
 
 #: session_option_editor.cc:52
 msgid "24.975"
@@ -10775,129 +11039,125 @@ msgstr ""
 
 #: session_option_editor.cc:53
 msgid "25"
-msgstr "25"
+msgstr ""
 
 #: session_option_editor.cc:54
 msgid "29.97"
-msgstr "29.97"
+msgstr ""
 
 #: session_option_editor.cc:55
 msgid "29.97 drop"
-msgstr ""
+msgstr "29.97 丢帧"
 
 #: session_option_editor.cc:56
 msgid "30"
-msgstr "30"
+msgstr ""
 
 #: session_option_editor.cc:57
 msgid "30 drop"
-msgstr ""
+msgstr "30 丢帧"
 
 #: session_option_editor.cc:58
 msgid "59.94"
-msgstr "59.94"
+msgstr ""
 
 #: session_option_editor.cc:59
 msgid "60"
-msgstr "60"
+msgstr ""
 
 #: session_option_editor.cc:65
 msgid "Pull-up / pull-down"
-msgstr "上拉/下拉"
+msgstr "上拉 / 下拉"
 
 #: session_option_editor.cc:70
 msgid "4.1667 + 0.1%"
-msgstr "4.1667 + 0.1%"
+msgstr ""
 
 #: session_option_editor.cc:71
 msgid "4.1667"
-msgstr "4.1667"
+msgstr ""
 
 #: session_option_editor.cc:72
 msgid "4.1667 - 0.1%"
-msgstr "4.1667 - 0.1%"
+msgstr ""
 
 #: session_option_editor.cc:73
 msgid "0.1"
-msgstr "0.1"
+msgstr ""
 
 #: session_option_editor.cc:74
 msgid "none"
-msgstr ""
+msgstr "æ— "
 
 #: session_option_editor.cc:75
 msgid "-0.1"
-msgstr "-0.1"
+msgstr ""
 
 #: session_option_editor.cc:76
 msgid "-4.1667 + 0.1%"
-msgstr "-4.1667 + 0.1%"
+msgstr ""
 
 #: session_option_editor.cc:77
 msgid "-4.1667"
-msgstr "-4.1667"
+msgstr ""
 
 #: session_option_editor.cc:78
 msgid "-4.1667 - 0.1%"
-msgstr "-4.1667 - 0.1%"
+msgstr ""
 
 #: session_option_editor.cc:84
 msgid ""
-"Use Video File's FPS Instead of Timecode Value for Timeline and Video "
-"Monitor."
-msgstr ""
+"Use Video File's FPS Instead of Timecode Value for Timeline and Video Monitor."
+msgstr "为时间线和视频监控使用视频文件的 FPS 替代时间码数值。"
 
 #: session_option_editor.cc:91
 msgid ""
-"Apply Pull-Up/Down to Video Timeline and Video Monitor (Unless using JACK-"
-"sync)."
-msgstr ""
+"Apply Pull-Up/Down to Video Timeline and Video Monitor (Unless using JACK-sync)."
+msgstr "应用上拉/下拉到视频时间线和视频监控(除非使用 JACK-同步)"
 
 #: session_option_editor.cc:96
 msgid "Ext Timecode Offsets"
-msgstr ""
+msgstr "外部时间码偏移"
 
 #: session_option_editor.cc:100
 msgid "Slave Timecode offset"
-msgstr ""
+msgstr "从属时间码偏移"
 
 #: session_option_editor.cc:107
 msgid "The specified offset is added to the received timecode (MTC or LTC)."
-msgstr ""
+msgstr "指定的偏移已被添加到已接收的时间码(MTC 或 LTC)。"
 
 #: session_option_editor.cc:113
 msgid "Timecode Generator offset"
-msgstr ""
+msgstr "时间码生成器偏移"
 
 #: session_option_editor.cc:120
-msgid ""
-"Specify an offset which is added to the generated timecode (so far only LTC)."
-msgstr ""
+msgid "Specify an offset which is added to the generated timecode (so far only LTC)."
+msgstr "指定一个已被添加到通用时间码的偏移(迄今为止仅有 LTC)。"
 
 #: session_option_editor.cc:124
 msgid "JACK Transport/Time Settings"
-msgstr ""
+msgstr "JACK 播送/时间设置"
 
 #: session_option_editor.cc:128
-msgid ""
-"%1 is JACK Time Master (provides Bar|Beat|Tick and other information to JACK)"
-msgstr ""
+msgid "%1 is JACK Time Master (provides Bar|Beat|Tick and other information to JACK)"
+msgstr "%1 是 JACK 时间主控(提供小节|拍子|识别声以及其它信息给 JACK)"
 
 #: session_option_editor.cc:136
 msgid "destructive-xfade-seconds"
-msgstr ""
+msgstr "销毁前置后置淡化秒数"
 
 #: session_option_editor.cc:137
 msgid "Destructive crossfade length"
-msgstr "销毁交叉淡入淡出长度"
+msgstr "销毁交叉淡化长度"
 
 #: session_option_editor.cc:146
 msgid "Region fades active"
-msgstr "区域淡入淡出活动"
+msgstr "区域淡化激活"
 
 #: session_option_editor.cc:153
 msgid "Region fades visible"
-msgstr "区域淡入淡出可见"
+msgstr "区域淡化可见"
 
 #: session_option_editor.cc:160 session_option_editor.cc:173
 #: session_option_editor.cc:187
@@ -10914,15 +11174,15 @@ msgstr "采样格式"
 
 #: session_option_editor.cc:169
 msgid "32-bit floating point"
-msgstr "32位浮点"
+msgstr "32 位浮点"
 
 #: session_option_editor.cc:170
 msgid "24-bit integer"
-msgstr "24位整形"
+msgstr "24 位整数"
 
 #: session_option_editor.cc:171
 msgid "16-bit integer"
-msgstr "16位整形"
+msgstr "16 位整数"
 
 #: session_option_editor.cc:177
 msgid "File type"
@@ -10930,15 +11190,15 @@ msgstr "文件类型"
 
 #: session_option_editor.cc:182
 msgid "Broadcast WAVE"
-msgstr "广播WAVE(Broadcast WAVE)"
+msgstr "广播 WAVE"
 
 #: session_option_editor.cc:183
 msgid "WAVE"
-msgstr "WAVE"
+msgstr ""
 
 #: session_option_editor.cc:184
 msgid "WAVE-64"
-msgstr "WAVE-64"
+msgstr ""
 
 #: session_option_editor.cc:189
 msgid "File locations"
@@ -10946,50 +11206,48 @@ msgstr "文件位置"
 
 #: session_option_editor.cc:191
 msgid "Search for audio files in:"
-msgstr "音频文件搜索位置:"
+msgstr "搜索音频文件于:"
 
 #: session_option_editor.cc:197
 msgid "Search for MIDI files in:"
-msgstr "MIDI文件搜索文职:"
+msgstr "搜索 MIDI 文件于:"
 
 #: session_option_editor.cc:206 session_option_editor.cc:218
 #: session_option_editor.cc:228 session_option_editor.cc:239
 msgid "Filenames"
-msgstr ""
+msgstr "文件名"
 
 #: session_option_editor.cc:206
 msgid "File Naming"
-msgstr ""
+msgstr "文件命名"
 
 #: session_option_editor.cc:212
 msgid "Prefix Track number"
-msgstr ""
+msgstr "音轨编号前缀"
 
 #: session_option_editor.cc:217
-msgid ""
-"Adds the current track number to the beginning of the recorded file name."
-msgstr ""
+msgid "Adds the current track number to the beginning of the recorded file name."
+msgstr "添加当前音轨编号到已录制文件名的前端。"
 
 #: session_option_editor.cc:222
 msgid "Prefix Take Name"
-msgstr ""
+msgstr "磁带名称前缀"
 
 #: session_option_editor.cc:227
 msgid "Adds the Take Name to the beginning of the recorded file name."
-msgstr ""
+msgstr "添加磁带名称到已录制文件名的前端。"
 
 #: session_option_editor.cc:232
 msgid "Take Name"
-msgstr ""
+msgstr "磁带名称"
 
 #: session_option_editor.cc:245
-msgid ""
-"Track Input Monitoring automatically follows transport state (\"auto-input\")"
-msgstr ""
+msgid "Track Input Monitoring automatically follows transport state (\"auto-input\")"
+msgstr "音轨输入监控自动化跟随播送状态(“自动输入”)"
 
 #: session_option_editor.cc:252
 msgid "Use monitor section in this session"
-msgstr ""
+msgstr "在该会话中使用的监控面"
 
 #: session_option_editor.cc:257 session_option_editor.cc:259
 #: session_option_editor.cc:266 session_option_editor.cc:273
@@ -10998,65 +11256,65 @@ msgstr ""
 #: session_option_editor.cc:303 session_option_editor.cc:310
 #: session_option_editor.cc:312
 msgid "Meterbridge"
-msgstr ""
+msgstr "节拍桥接"
 
 #: session_option_editor.cc:257
 msgid "Route Display"
-msgstr ""
+msgstr "路由显示"
 
 #: session_option_editor.cc:261
 msgid "Show Midi Tracks"
-msgstr ""
+msgstr "显示 MIDI 音轨"
 
 #: session_option_editor.cc:268
 msgid "Show Busses"
-msgstr ""
+msgstr "显示总线"
 
 #: session_option_editor.cc:275
 msgid "Include Master Bus"
-msgstr ""
+msgstr "包括主控总线"
 
 #: session_option_editor.cc:280
 msgid "Button Area"
-msgstr ""
+msgstr "按钮区域"
 
 #: session_option_editor.cc:284
 msgid "Rec-enable Button"
-msgstr ""
+msgstr "可录制按钮"
 
 #: session_option_editor.cc:291
 msgid "Mute Button"
-msgstr ""
+msgstr "静音按钮"
 
 #: session_option_editor.cc:298
 msgid "Solo Button"
-msgstr ""
+msgstr "独奏按钮"
 
 #: session_option_editor.cc:305
 msgid "Monitor Buttons"
-msgstr ""
+msgstr "监控按钮"
 
 #: session_option_editor.cc:310
 msgid "Name Labels"
-msgstr ""
+msgstr "名称标签"
 
 #: session_option_editor.cc:314
 msgid "Track Name"
-msgstr ""
+msgstr "音轨名称"
 
 #: session_option_editor.cc:325
 msgid "MIDI region copies are independent"
-msgstr ""
+msgstr "MIDI 区域拷贝不受约束"
 
 #: session_option_editor.cc:332
 msgid ""
 "Policy for handling overlapping notes\n"
 " on the same MIDI channel"
-msgstr ""
+msgstr "处理位于同一个 MIDI 声道上的重叠音符的策略"
 
 #: session_option_editor.cc:337
 msgid "never allow them"
-msgstr "从不允许"
+msgstr "从不允许它们"
 
 #: session_option_editor.cc:338
 msgid "don't do anything in particular"
@@ -11076,47 +11334,47 @@ msgstr "缩短已存在的新音符"
 
 #: session_option_editor.cc:342
 msgid "replace both overlapping notes with a single note"
-msgstr "把重叠的音符替换为一个单音符"
+msgstr "把重叠的音符替换为一个单个音符"
 
 #: session_option_editor.cc:346
 msgid "Glue to bars and beats"
-msgstr ""
+msgstr "粘连到小节和拍子"
 
 #: session_option_editor.cc:350
 msgid "Glue new markers to bars and beats"
-msgstr ""
+msgstr "粘连新的标记到小节和拍子"
 
 #: session_option_editor.cc:357
 msgid "Glue new regions to bars and beats"
-msgstr ""
+msgstr "粘连新的区域到小节和拍子"
 
 #: session_option_editor.cc:362
 msgid "Defaults"
-msgstr ""
+msgstr "默认"
 
 #: session_option_editor.cc:364
 msgid "Use these settings as defaults"
-msgstr ""
+msgstr "使用这些设置作为默认"
 
 #: sfdb_ui.cc:90 sfdb_ui.cc:110 sfdb_ui.cc:119
 msgid "as new tracks"
-msgstr ""
+msgstr "作为新的音轨"
 
 #: sfdb_ui.cc:92 sfdb_ui.cc:112
 msgid "to selected tracks"
-msgstr ""
+msgstr "到已选中的音轨"
 
 #: sfdb_ui.cc:94 sfdb_ui.cc:114
 msgid "to region list"
-msgstr ""
+msgstr "到区域列表"
 
 #: sfdb_ui.cc:96 sfdb_ui.cc:116
 msgid "as new tape tracks"
-msgstr ""
+msgstr "作为新的磁带音轨"
 
 #: sfdb_ui.cc:100
 msgid "programming error: unknown import mode string %1"
-msgstr "程序错误: 未知的导入模式字符串 %1"
+msgstr "程序错误:未知的导入模式字符串 %1"
 
 #: sfdb_ui.cc:127
 msgid "Auto-play"
@@ -11128,31 +11386,31 @@ msgstr "<b>声音文件信息</b>"
 
 #: sfdb_ui.cc:147
 msgid "Timestamp:"
-msgstr "时间戳:"
+msgstr "时间戳:"
 
 #: sfdb_ui.cc:149
 msgid "Format:"
-msgstr "格式:"
+msgstr "格式:"
 
 #: sfdb_ui.cc:188 sfdb_ui.cc:653
 msgid "Tags:"
-msgstr "标签:"
+msgstr "标签:"
 
 #: sfdb_ui.cc:293 sfdb_ui.cc:409
 msgid "Could not read file: %1 (%2)."
-msgstr "无法读取文件: %1 (%2)."
+msgstr "无法读取文件: %1 (%2)."
 
 #: sfdb_ui.cc:297
 msgid "<b>Midi File Information</b>"
-msgstr ""
+msgstr "<b>Midi 文件信息</b>"
 
 #: sfdb_ui.cc:458
 msgid "Could not access soundfile: "
-msgstr "无法访问声音文件: "
+msgstr "无法访问声音文件: "
 
 #: sfdb_ui.cc:530
 msgid "SoundFileBox: Could not tokenize string: "
-msgstr ""
+msgstr "声音文件盒:无法令牌化字符串: "
 
 #: sfdb_ui.cc:550 sfdb_ui.cc:552
 msgid "Search"
@@ -11160,7 +11418,7 @@ msgstr "搜索"
 
 #: sfdb_ui.cc:576
 msgid "Audio and MIDI files"
-msgstr ""
+msgstr "音频和 MIDI 文件"
 
 #: sfdb_ui.cc:579
 msgid "Audio files"
@@ -11168,7 +11426,7 @@ msgstr "音频文件"
 
 #: sfdb_ui.cc:582
 msgid "MIDI files"
-msgstr "MIDI文件"
+msgstr "MIDI 文件"
 
 #: sfdb_ui.cc:585 add_video_dialog.cc:123
 msgid "All files"
@@ -11188,47 +11446,47 @@ msgstr "搜索标签"
 
 #: sfdb_ui.cc:658
 msgid "Sort:"
-msgstr ""
+msgstr "排序:"
 
 #: sfdb_ui.cc:666
 msgid "Longest"
-msgstr ""
+msgstr "最长"
 
 #: sfdb_ui.cc:667
 msgid "Shortest"
-msgstr ""
+msgstr "最短"
 
 #: sfdb_ui.cc:668
 msgid "Newest"
-msgstr ""
+msgstr "最新"
 
 #: sfdb_ui.cc:669
 msgid "Oldest"
-msgstr ""
+msgstr "最旧"
 
 #: sfdb_ui.cc:670
 msgid "Most downloaded"
-msgstr ""
+msgstr "最多下载"
 
 #: sfdb_ui.cc:671
 msgid "Least downloaded"
-msgstr ""
+msgstr "最新下载"
 
 #: sfdb_ui.cc:672
 msgid "Highest rated"
-msgstr ""
+msgstr "最高评价"
 
 #: sfdb_ui.cc:673
 msgid "Lowest rated"
-msgstr ""
+msgstr "最低评价"
 
 #: sfdb_ui.cc:678
 msgid "More"
-msgstr ""
+msgstr "更多"
 
 #: sfdb_ui.cc:682
 msgid "Similar"
-msgstr ""
+msgstr "类似的"
 
 #: sfdb_ui.cc:694
 msgid "ID"
@@ -11236,53 +11494,52 @@ msgstr ""
 
 #: sfdb_ui.cc:695 add_video_dialog.cc:83
 msgid "Filename"
-msgstr ""
+msgstr "文件名"
 
 #: sfdb_ui.cc:697
 msgid "Duration"
-msgstr ""
+msgstr "音长"
 
 #: sfdb_ui.cc:698
 msgid "Size"
-msgstr ""
+msgstr "尺寸"
 
 #: sfdb_ui.cc:699
 msgid "Samplerate"
-msgstr ""
+msgstr "采样率"
 
 #: sfdb_ui.cc:700
 msgid "License"
-msgstr ""
+msgstr "许可证"
 
 #: sfdb_ui.cc:718
 msgid "Search Freesound"
-msgstr "寻找自由的声音"
+msgstr "搜索自由声音"
 
 #: sfdb_ui.cc:738
 msgid "Press to import selected files and close this window"
-msgstr ""
+msgstr "按下插入已选中的文件并且关闭此窗口"
 
 #: sfdb_ui.cc:739
 msgid "Press to import selected files and leave this window open"
-msgstr ""
+msgstr "按下插入已选中的文件并且保留此窗口"
 
 #: sfdb_ui.cc:740
 msgid "Press to close this window without importing any files"
-msgstr ""
+msgstr "按下关闭此窗口并且不插入任何文件"
 
 #: sfdb_ui.cc:936
 msgid "SoundFileBrowser: Could not tokenize string: "
-msgstr "SoundFileBrowser: 无法标记化字符串"
+msgstr "声音文件浏览器:无法令牌化字符串: "
 
 #: sfdb_ui.cc:1136
 msgid "%1 more page of 100 results available"
 msgid_plural "%1 more pages of 100 results available"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%1 有 100 多页结果可用"
 
 #: sfdb_ui.cc:1141
 msgid "No more results available"
-msgstr ""
+msgstr "无更多结果可用"
 
 #: sfdb_ui.cc:1205
 msgid "B"
@@ -11302,15 +11559,15 @@ msgstr ""
 
 #: sfdb_ui.cc:1425 sfdb_ui.cc:1738 sfdb_ui.cc:1801 sfdb_ui.cc:1819
 msgid "one track per file"
-msgstr "1音轨/1文件"
+msgstr "每个文件一个音轨"
 
 #: sfdb_ui.cc:1428 sfdb_ui.cc:1802 sfdb_ui.cc:1820
 msgid "one track per channel"
-msgstr "1音轨/1声道"
+msgstr "每个声道一个音轨"
 
 #: sfdb_ui.cc:1436 sfdb_ui.cc:1804 sfdb_ui.cc:1821
 msgid "sequence files"
-msgstr "顺序文件"
+msgstr "序列文件"
 
 #: sfdb_ui.cc:1439 sfdb_ui.cc:1809
 msgid "all files in one track"
@@ -11322,22 +11579,22 @@ msgstr "合并文件"
 
 #: sfdb_ui.cc:1446 sfdb_ui.cc:1806
 msgid "one region per file"
-msgstr "1区域/1文件"
+msgstr "每个文件一个区域"
 
 #: sfdb_ui.cc:1449 sfdb_ui.cc:1807
 msgid "one region per channel"
-msgstr "1区域/1声道"
+msgstr "每个声道一个区域"
 
 #: sfdb_ui.cc:1454 sfdb_ui.cc:1808 sfdb_ui.cc:1822
 msgid "all files in one region"
-msgstr "所有文件在一个区域"
+msgstr "所有文件在一个区域里"
 
 #: sfdb_ui.cc:1521
 msgid ""
 "One or more of the selected files\n"
 "cannot be used by %1"
 msgstr ""
-"一个或多个所选文件\n"
+"一个或多个已选中的文件\n"
 "不能被用于 %1"
 
 #: sfdb_ui.cc:1665
@@ -11354,43 +11611,43 @@ msgstr "编辑点"
 
 #: sfdb_ui.cc:1684 sfdb_ui.cc:1863
 msgid "playhead"
-msgstr "播放头"
+msgstr "指针"
 
 #: sfdb_ui.cc:1685
 msgid "session start"
-msgstr "开始会话"
+msgstr "会话起点"
 
 #: sfdb_ui.cc:1691
 msgid "<b>Add files as ...</b>"
-msgstr ""
+msgstr "<b>添加文件为…</b>"
 
 #: sfdb_ui.cc:1713
 msgid "<b>Insert at</b>"
-msgstr ""
+msgstr "<b>插入于</b>"
 
 #: sfdb_ui.cc:1726
 msgid "<b>Mapping</b>"
-msgstr ""
+msgstr "<b>映射</b>"
 
 #: sfdb_ui.cc:1744
 msgid "<b>Conversion quality</b>"
-msgstr ""
+msgstr "<b>转换质量</b>"
 
 #: sfdb_ui.cc:1756
 msgid "<b>Instrument</b>"
-msgstr ""
+msgstr "<b>乐器</b>"
 
 #: sfdb_ui.cc:1768 sfdb_ui.cc:1875
 msgid "Best"
-msgstr "最佳质量"
+msgstr "最佳"
 
 #: sfdb_ui.cc:1769 sfdb_ui.cc:1877
 msgid "Good"
-msgstr "高质量"
+msgstr "好"
 
 #: sfdb_ui.cc:1770 sfdb_ui.cc:1879
 msgid "Quick"
-msgstr "速度优先"
+msgstr "å¿«"
 
 #: sfdb_ui.cc:1772
 msgid "Fastest"
@@ -11398,31 +11655,31 @@ msgstr "最快"
 
 #: shuttle_control.cc:56
 msgid "Shuttle speed control (Context-click for options)"
-msgstr ""
+msgstr "往复速度控制(右键点击查看更多选项)"
 
 #: shuttle_control.cc:174
 msgid "Percent"
-msgstr "百分比 '%'"
+msgstr "百分比"
 
 #: shuttle_control.cc:182
 msgid "Units"
-msgstr "单元"
+msgstr "单位"
 
 #: shuttle_control.cc:188 shuttle_control.cc:609
 msgid "Sprung"
-msgstr ""
+msgstr "弹动"
 
 #: shuttle_control.cc:192 shuttle_control.cc:612
 msgid "Wheel"
-msgstr ""
+msgstr "轮转"
 
 #: shuttle_control.cc:226
 msgid "Maximum speed"
-msgstr "速度最大化"
+msgstr "最大速度"
 
 #: shuttle_control.cc:568
 msgid "Playing"
-msgstr "正在播放"
+msgstr "播放中"
 
 #: shuttle_control.cc:583
 #, c-format
@@ -11432,7 +11689,7 @@ msgstr "<<< %+d 半音"
 #: shuttle_control.cc:585
 #, c-format
 msgid ">>> %+d semitones"
-msgstr ">>> %+d semitones"
+msgstr ">>> %+d 半音"
 
 #: shuttle_control.cc:590
 msgid "Stopped"
@@ -11440,31 +11697,31 @@ msgstr "已停止"
 
 #: soundcloud_export_selector.cc:44
 msgid "User Email"
-msgstr ""
+msgstr "用户电子信箱"
 
 #: soundcloud_export_selector.cc:45
 msgid "Password"
-msgstr ""
+msgstr "密码"
 
 #: soundcloud_export_selector.cc:46
 msgid "Make files public"
-msgstr ""
+msgstr "文件公开"
 
 #: soundcloud_export_selector.cc:47
 msgid "Open uploaded files in browser"
-msgstr ""
+msgstr "在浏览器里打开已上传的文件"
 
 #: soundcloud_export_selector.cc:48
 msgid "Make files downloadable"
-msgstr ""
+msgstr "文件可下载"
 
 #: soundcloud_export_selector.cc:107
 msgid "%1: %2 of %3 bytes uploaded"
-msgstr ""
+msgstr "%1: %2 的 %3 字节已上传"
 
 #: splash.cc:73
 msgid "%1 loading ..."
-msgstr "载入%1..."
+msgstr "%1 载入中…"
 
 #: speaker_dialog.cc:40
 msgid "Add Speaker"
@@ -11472,35 +11729,41 @@ msgstr "添加扬声器"
 
 #: speaker_dialog.cc:41
 msgid "Remove Speaker"
-msgstr "起初扬声器"
+msgstr "移除扬声器"
 
 #: speaker_dialog.cc:63
 msgid "Azimuth:"
-msgstr ""
+msgstr "方位角:"
 
 #: startup.cc:67
 msgid ""
 "Use an external mixer or the hardware mixer of your audio interface.\n"
 "%1 will play NO role in monitoring"
 msgstr ""
+"使用一个外部混音器或您的音频接口硬件混音器。\n"
+"%1 将不会出现在监控中"
 
 #: startup.cc:69
 msgid "Ask %1 to play back material as it is being recorded"
-msgstr ""
+msgstr "当 %1 被录制时请求其回放材料"
 
 #: startup.cc:142
 msgid ""
-"<span size=\"larger\">%1 is a digital audio workstation. You can use it to "
-"record, edit and mix multi-track audio. You can produce your own CDs, mix "
-"video soundtracks, or experiment with new ideas about music and sound. \n"
+"<span size=\"larger\">%1 is a digital audio workstation. You can use it to record, "
+"edit and mix multi-track audio. You can produce your own CDs, mix video "
+"soundtracks, or experiment with new ideas about music and sound. \n"
 "\n"
 "There are a few things that need to be configured before you start using the "
 "program.</span> "
 msgstr ""
+"<span size=\"larger\">%1 是一个数字音频工作站。您可以用它录制、编辑并混合多声道音"
+"频。您可以创作自己的CD光盘、混合视频音轨、或者试验与音乐和声音有关的新想法。\n"
+"\n"
+"在您开始使用这个程序之前,需要完成一些配置。</span> "
 
 #: startup.cc:168
 msgid "Welcome to %1"
-msgstr "欢迎进入 %1"
+msgstr "欢迎使用 %1"
 
 #: startup.cc:191
 msgid "Default folder for %1 sessions"
@@ -11515,16 +11778,16 @@ msgid ""
 "\n"
 "<i>(You can put new sessions anywhere, this is just a default)</i>"
 msgstr ""
-"您在 %1 工作的每个项目都有各自的文件夹.\n"
-"当你在录音的时候可能需要大量的磁盘空间.\n"
+"您在 %1 工作的每个项目都有它各自的文件夹。\n"
+"当您在录制音频时,可能需要大量的磁盘空间。\n"
 "\n"
-"你希望新的 %1 会话被默认存放在哪儿?\n"
+"您希望新的 %1 会话被默认存放在哪儿?\n"
 "\n"
-"<i>(你可以把新的会话存放在任何位置, 这只是默认的文件夹)</i>"
+"<i>(您可以把新的会话存放在任何位置,这里只是默认文件夹)</i>"
 
 #: startup.cc:220
 msgid "Default folder for new sessions"
-msgstr "会话文件默认的文件夹"
+msgstr "新会话的默认文件夹"
 
 #: startup.cc:241
 msgid ""
@@ -11534,37 +11797,45 @@ msgid ""
 "configuration of that equipment. The two most common are presented here.\n"
 "Please choose whichever one is right for your setup.\n"
 "\n"
-"<i>(You can change this preference at any time, via the Preferences dialog)</"
-"i>\n"
+"<i>(You can change this preference at any time, via the Preferences dialog)</i>\n"
 "\n"
 "<i>If you do not understand what this is about, just accept the default.</i>"
 msgstr ""
+"当录制乐器或人声时,您可能希望在录制的同时听到信号。\n"
+"这被称为“监控”。\n"
+"有不同的方法可以做到这一点,这取决于您所拥有的设备以及这些设备的配置。\n"
+"这里有两个最常见的方式。\n"
+"请选择最适合您的设置的那一个。\n"
+"\n"
+"<i>(您可以在任何时候改变这个首选项,就在首选项对话框里)</i>\n"
+"\n"
+"<i>如果您不大了解这方面的信息,保持默认即可。</i>"
 
 #: startup.cc:262
 msgid "Monitoring Choices"
-msgstr "检控选择"
+msgstr "监控选择"
 
 #: startup.cc:285
 msgid "Use a Master bus directly"
-msgstr "直接用主控总线"
+msgstr "直接使用主控总线"
 
 #: startup.cc:287
 msgid ""
-"Connect the Master bus directly to your hardware outputs. This is preferable "
-"for simple usage."
-msgstr ""
+"Connect the Master bus directly to your hardware outputs. This is preferable for "
+"simple usage."
+msgstr "直接连接主控总线到您的硬件输出。这可能更简单易用。"
 
 #: startup.cc:296
 msgid "Use an additional Monitor bus"
-msgstr "用一个额外的主控总线"
+msgstr "使用一个额外的监控总线"
 
 #: startup.cc:299
 msgid ""
 "Use a Monitor bus between Master bus and hardware outputs for \n"
 "greater control in monitoring without affecting the mix."
 msgstr ""
-"用一个监控总线\n"
-"监控时有更好的控制, 不影响混音"
+"在主控总线和硬件输入之间使用一个监控总线\n"
+"监控时可更好的控制,不会影响混音。"
 
 #: startup.cc:321
 msgid ""
@@ -11573,46 +11844,50 @@ msgid ""
 "\n"
 "<i>If you do not understand what this is about, just accept the default.</i>"
 msgstr ""
+"<i>您可以在任何时候改变这个首选项,就在首选项对话框里。\n"
+"您也可以添加监控面到任何会话,或着从任何会话移除监控面。</i>\n"
+"\n"
+"<i>如果您不大了解这方面的信息,保持默认即可。</i>"
 
 #: startup.cc:332
 msgid "Monitor Section"
-msgstr "监控部分"
+msgstr "监控面"
 
 #: step_entry.cc:60
 msgid "Step Entry: %1"
-msgstr ""
+msgstr "步进入口:%1"
 
 #: step_entry.cc:65
 msgid ">beat"
-msgstr ""
+msgstr ">拍子"
 
 #: step_entry.cc:66
 msgid ">bar"
-msgstr ""
+msgstr ">小节"
 
 #: step_entry.cc:67
 msgid ">EP"
-msgstr ""
+msgstr ">采样"
 
 #: step_entry.cc:68
 msgid "sustain"
-msgstr ""
+msgstr "持续"
 
 #: step_entry.cc:69
 msgid "rest"
-msgstr ""
+msgstr "休止"
 
 #: step_entry.cc:70
 msgid "g-rest"
-msgstr ""
+msgstr "g-休止"
 
 #: step_entry.cc:71
 msgid "back"
-msgstr ""
+msgstr "后退"
 
 #: step_entry.cc:82 step_entry.cc:85
 msgid "+"
-msgstr "+"
+msgstr ""
 
 #: step_entry.cc:191
 msgid "Set note length to a whole note"
@@ -11620,7 +11895,7 @@ msgstr "设置音符长度为全音符"
 
 #: step_entry.cc:192
 msgid "Set note length to a half note"
-msgstr "设置音符长度为半分音符"
+msgstr "设置音符长度为半音符"
 
 #: step_entry.cc:193
 msgid "Set note length to a quarter note"
@@ -11644,91 +11919,91 @@ msgstr "设置音符长度为六十四分音符"
 
 #: step_entry.cc:276
 msgid "Set volume (velocity) to pianississimo"
-msgstr "设置音量(力度)为最弱音"
+msgstr "设置音量(力度)为最弱音"
 
 #: step_entry.cc:277
 msgid "Set volume (velocity) to pianissimo"
-msgstr "设置音量(力度)为极弱音"
+msgstr "设置音量(力度)为极弱音"
 
 #: step_entry.cc:278
 msgid "Set volume (velocity) to piano"
-msgstr "设置音量(力度)为弱音"
+msgstr "设置音量(力度)为弱音"
 
 #: step_entry.cc:279
 msgid "Set volume (velocity) to mezzo-piano"
-msgstr "设置音量(力度)为中弱音"
+msgstr "设置音量(力度)为中弱音"
 
 #: step_entry.cc:280
 msgid "Set volume (velocity) to mezzo-forte"
-msgstr "设置音量(力度)为中强音"
+msgstr "设置音量(力度)为中强音"
 
 #: step_entry.cc:281
 msgid "Set volume (velocity) to forte"
-msgstr "设置音量(力度)为强音"
+msgstr "设置音量(力度)为强音"
 
 #: step_entry.cc:282
 msgid "Set volume (velocity) to fortissimo"
-msgstr ""
+msgstr "设置音量(力度)为极强音"
 
 #: step_entry.cc:283
 msgid "Set volume (velocity) to fortississimo"
-msgstr ""
+msgstr "设置音量(力度)为最强音"
 
 #: step_entry.cc:331
 msgid "Stack inserted notes to form a chord"
-msgstr "堆叠插入音符形成一个和弦"
+msgstr "堆栈已插入的音符形成一个和弦"
 
 #: step_entry.cc:332
 msgid "Extend selected notes by note length"
-msgstr "延伸所选音符的长度"
+msgstr "通过音符长度延伸已选择的音符"
 
 #: step_entry.cc:333
 msgid "Use undotted note lengths"
-msgstr "使用不带点长度的音符"
+msgstr "使用不带点音符长度"
 
 #: step_entry.cc:334
 msgid "Use dotted (* 1.5) note lengths"
-msgstr "使用带点(*1.5)长度的音符"
+msgstr "使用带点(*1.5)音符长度"
 
 #: step_entry.cc:335
 msgid "Use double-dotted (* 1.75) note lengths"
-msgstr "使用带双点(*1.75)长度的音符"
+msgstr "使用带双点(*1.75)音符长度"
 
 #: step_entry.cc:336
 msgid "Use triple-dotted (* 1.875) note lengths"
-msgstr "使用带三点(*1.75)长度的音符"
+msgstr "使用带三点(* 1.875)音符长度"
 
 #: step_entry.cc:337
 msgid "Insert a note-length's rest"
-msgstr "插入一个全休止符"
+msgstr "插入一个音符长度的休止符"
 
 #: step_entry.cc:338
 msgid "Insert a grid-unit's rest"
-msgstr "添加一个单元格的休止符"
+msgstr "插入一个网格单位的休止符"
 
 #: step_entry.cc:339
 msgid "Insert a rest until the next beat"
-msgstr "添加一个直到下一拍的休止符"
+msgstr "插入一个休止符直到下一拍"
 
 #: step_entry.cc:340
 msgid "Insert a rest until the next bar"
-msgstr "添加一个直到下一小节的休止符"
+msgstr "插入一个休止符直到下一小节"
 
 #: step_entry.cc:341
 msgid "Insert a bank change message"
-msgstr ""
+msgstr "插入一个库变换信息"
 
 #: step_entry.cc:342
 msgid "Insert a program change message"
-msgstr ""
+msgstr "插入一个程式变换信息"
 
 #: step_entry.cc:343 step_entry.cc:700
 msgid "Move Insert Position Back by Note Length"
-msgstr "把插入位置向前移动一个音符的长度"
+msgstr "按音符长度向后移动插入位置"
 
 #: step_entry.cc:344 step_entry.cc:698
 msgid "Move Insert Position to Edit Point"
-msgstr "把插入位置移移至编辑位置"
+msgstr "移动插入位置到编辑位置"
 
 #: step_entry.cc:401
 msgid "1/Note"
@@ -11792,7 +12067,7 @@ msgstr "插入一个全休止符"
 
 #: step_entry.cc:612
 msgid "Insert a Snap-length Rest"
-msgstr "插入一个锁定长度的休止符"
+msgstr "插入一个吸附长度的休止符"
 
 #: step_entry.cc:614 step_entry.cc:615
 msgid "Move to next octave"
@@ -11800,11 +12075,11 @@ msgstr "移动到下一个八度"
 
 #: step_entry.cc:617
 msgid "Move to Next Note Length"
-msgstr "向后移动一个音符"
+msgstr "移动到下一个音符长度"
 
 #: step_entry.cc:618
 msgid "Move to Previous Note Length"
-msgstr "向前移动一个音符"
+msgstr "移动到上一个音符长度"
 
 #: step_entry.cc:620
 msgid "Increase Note Length"
@@ -11812,7 +12087,7 @@ msgstr "增加音符长度"
 
 #: step_entry.cc:621
 msgid "Decrease Note Length"
-msgstr "降低音符长度"
+msgstr "减少音符长度"
 
 #: step_entry.cc:623
 msgid "Move to Next Note Velocity"
@@ -11828,7 +12103,7 @@ msgstr "增加音符力度"
 
 #: step_entry.cc:627
 msgid "Decrease Note Velocity"
-msgstr "降低音符力度"
+msgstr "减少音符力度"
 
 #: step_entry.cc:629
 msgid "Switch to the 1st octave"
@@ -11936,48 +12211,48 @@ msgstr "设置音符力度为最强音"
 
 #: step_entry.cc:679
 msgid "Toggle Triple Notes"
-msgstr ""
+msgstr "切换三分音符"
 
 #: step_entry.cc:684
 msgid "No Dotted Notes"
-msgstr ""
+msgstr "无带点音符"
 
 #: step_entry.cc:686
 msgid "Toggled Dotted Notes"
-msgstr ""
+msgstr "切换带点音符"
 
 #: step_entry.cc:688
 msgid "Toggled Double-Dotted Notes"
-msgstr ""
+msgstr "切换带双点音符"
 
 #: step_entry.cc:690
 msgid "Toggled Triple-Dotted Notes"
-msgstr ""
+msgstr "切换带三点音符"
 
 #: step_entry.cc:693
 msgid "Toggle Chord Entry"
-msgstr ""
+msgstr "切换和弦入口"
 
 #: step_entry.cc:695
 msgid "Sustain Selected Notes by Note Length"
-msgstr "通过音符长度保持选择音符"
+msgstr "通过音符长度持续已选择的音符"
 
 #: stereo_panner.cc:133
 #, c-format
 msgid "L:%3d R:%3d Width:%d%%"
-msgstr ""
+msgstr "左:%3d 右:%3d 宽度:%d%%"
 
 #: stereo_panner_editor.cc:35
 msgid "Stereo Panner"
-msgstr ""
+msgstr "立体声面板"
 
 #: stereo_panner_editor.cc:49
 msgid "Width"
-msgstr ""
+msgstr "宽度"
 
 #: strip_silence_dialog.cc:44
 msgid "Strip Silence"
-msgstr "剥去沉默"
+msgstr "片段无声"
 
 #: strip_silence_dialog.cc:75
 msgid "Minimum length"
@@ -11985,104 +12260,95 @@ msgstr "最小长度"
 
 #: strip_silence_dialog.cc:83
 msgid "Fade length"
-msgstr ""
+msgstr "淡化长度"
 
 #: tempo_dialog.cc:41 tempo_dialog.cc:57
 msgid "bar:"
-msgstr "小节:"
+msgstr "小节:"
 
 #: tempo_dialog.cc:42 tempo_dialog.cc:58
 msgid "beat:"
-msgstr "拍子:"
+msgstr "拍子:"
 
 #: tempo_dialog.cc:43 tempo_dialog.cc:59
 msgid "Pulse note"
-msgstr ""
+msgstr "脉冲音符"
 
 #: tempo_dialog.cc:44 tempo_dialog.cc:60
 msgid "Tap tempo"
-msgstr ""
+msgstr "节拍节奏"
 
 #: tempo_dialog.cc:54
 msgid "Edit Tempo"
-msgstr ""
+msgstr "编辑节奏"
 
-#: tempo_dialog.cc:77 tempo_dialog.cc:78 tempo_dialog.cc:324
-#: tempo_dialog.cc:325
+#: tempo_dialog.cc:77 tempo_dialog.cc:78 tempo_dialog.cc:324 tempo_dialog.cc:325
 msgid "whole"
-msgstr ""
+msgstr "å…¨"
 
-#: tempo_dialog.cc:79 tempo_dialog.cc:80 tempo_dialog.cc:326
-#: tempo_dialog.cc:327
+#: tempo_dialog.cc:79 tempo_dialog.cc:80 tempo_dialog.cc:326 tempo_dialog.cc:327
 msgid "second"
-msgstr ""
+msgstr "二分之一"
 
-#: tempo_dialog.cc:81 tempo_dialog.cc:82 tempo_dialog.cc:328
-#: tempo_dialog.cc:329
+#: tempo_dialog.cc:81 tempo_dialog.cc:82 tempo_dialog.cc:328 tempo_dialog.cc:329
 msgid "third"
-msgstr ""
+msgstr "三分之一"
 
-#: tempo_dialog.cc:83 tempo_dialog.cc:84 tempo_dialog.cc:330
-#: tempo_dialog.cc:331
+#: tempo_dialog.cc:83 tempo_dialog.cc:84 tempo_dialog.cc:330 tempo_dialog.cc:331
 msgid "quarter"
-msgstr ""
+msgstr "四分之一"
 
-#: tempo_dialog.cc:85 tempo_dialog.cc:86 tempo_dialog.cc:332
-#: tempo_dialog.cc:333
+#: tempo_dialog.cc:85 tempo_dialog.cc:86 tempo_dialog.cc:332 tempo_dialog.cc:333
 msgid "eighth"
-msgstr ""
+msgstr "八分之一"
 
-#: tempo_dialog.cc:87 tempo_dialog.cc:88 tempo_dialog.cc:334
-#: tempo_dialog.cc:335
+#: tempo_dialog.cc:87 tempo_dialog.cc:88 tempo_dialog.cc:334 tempo_dialog.cc:335
 msgid "sixteenth"
-msgstr ""
+msgstr "十六分之一"
 
-#: tempo_dialog.cc:89 tempo_dialog.cc:90 tempo_dialog.cc:336
-#: tempo_dialog.cc:337
+#: tempo_dialog.cc:89 tempo_dialog.cc:90 tempo_dialog.cc:336 tempo_dialog.cc:337
 msgid "thirty-second"
-msgstr ""
+msgstr "三十二分之一"
 
-#: tempo_dialog.cc:91 tempo_dialog.cc:92 tempo_dialog.cc:338
-#: tempo_dialog.cc:339
+#: tempo_dialog.cc:91 tempo_dialog.cc:92 tempo_dialog.cc:338 tempo_dialog.cc:339
 msgid "sixty-fourth"
-msgstr ""
+msgstr "六十四分之一"
 
-#: tempo_dialog.cc:93 tempo_dialog.cc:94 tempo_dialog.cc:340
-#: tempo_dialog.cc:341
+#: tempo_dialog.cc:93 tempo_dialog.cc:94 tempo_dialog.cc:340 tempo_dialog.cc:341
 msgid "one-hundred-twenty-eighth"
-msgstr ""
+msgstr "一百二十八分之一"
 
 #: tempo_dialog.cc:121
 msgid "Beats per minute:"
-msgstr "每分钟拍数:"
+msgstr "每分钟拍子数:"
 
 #: tempo_dialog.cc:155
 msgid "Tempo begins at"
-msgstr "节奏开始于"
+msgstr "节奏开始位于"
 
 #: tempo_dialog.cc:251
 msgid "incomprehensible pulse note type (%1)"
-msgstr ""
+msgstr "不可理解的脉冲音符类型(%1)"
 
 #: tempo_dialog.cc:307
 msgid "Edit Meter"
-msgstr ""
+msgstr "编辑节拍"
 
 #: tempo_dialog.cc:356
 msgid "Note value:"
-msgstr "音符值:"
+msgstr "音符值:"
 
 #: tempo_dialog.cc:357
 msgid "Beats per bar:"
-msgstr "每小节拍数:"
+msgstr "每小节拍子数:"
 
 #: tempo_dialog.cc:371
 msgid "Meter begins at bar:"
-msgstr "标尺开始小节在:"
+msgstr "节拍开始位于小节:"
 
 #: tempo_dialog.cc:484
 msgid "incomprehensible meter note type (%1)"
-msgstr ""
+msgstr "不可理解的节拍音符类型(%1)"
 
 #: theme_manager.cc:65
 msgid "Dark Theme"
@@ -12094,92 +12360,95 @@ msgstr "明亮主题"
 
 #: theme_manager.cc:67
 msgid "Restore Defaults"
-msgstr "重新储存预设"
+msgstr "重置恢复默认值"
 
 #: theme_manager.cc:68
 msgid "Draw \"flat\" buttons"
-msgstr ""
+msgstr "描绘“降调”按钮"
 
 #: theme_manager.cc:69
 msgid "Blink Rec-Arm buttons"
-msgstr ""
+msgstr "闪光录制臂按钮"
 
 #: theme_manager.cc:70
 msgid "Color regions using their track's color"
-msgstr ""
+msgstr "使用区域的音轨颜色作为区域色"
 
 #: theme_manager.cc:71
 msgid "Show waveform clipping"
-msgstr ""
+msgstr "显示波形截波"
 
 #: theme_manager.cc:73
 msgid "Waveforms color gradient depth"
-msgstr ""
+msgstr "波形颜色梯度深度"
 
 #: theme_manager.cc:75
 msgid "Timeline item gradient depth"
-msgstr ""
+msgstr "时间线条目梯度深度"
 
 #: theme_manager.cc:76
 msgid "All floating windows are dialogs"
-msgstr ""
+msgstr "所有浮动窗口都是对话框"
 
 #: theme_manager.cc:77
 msgid "Transient windows follow front window."
-msgstr ""
+msgstr "临时窗口跟随前方窗口。"
 
 #: theme_manager.cc:78
 msgid "Icon Set"
-msgstr ""
+msgstr "图标集"
 
 #: theme_manager.cc:87
 msgid "Object"
-msgstr "对象"
+msgstr "对象物体"
 
 #: theme_manager.cc:163
 msgid "Items"
-msgstr ""
+msgstr "条目"
 
 #: theme_manager.cc:164
 msgid "Palette"
-msgstr ""
+msgstr "调色板"
 
 #: theme_manager.cc:165
 msgid "Transparency"
-msgstr ""
+msgstr "透明度"
 
 #: theme_manager.cc:195
 msgid ""
-"Mark all floating windows to be type \"Dialog\" rather than using \"Utility"
-"\" for some.\n"
-"This may help with some window managers. This requires a restart of %1 to "
-"take effect"
+"Mark all floating windows to be type \"Dialog\" rather than using \"Utility\" for "
+"some.\n"
+"This may help with some window managers. This requires a restart of %1 to take "
+"effect"
 msgstr ""
+"标记所有窗口类型为“对话框”,而不是把某些窗口标记为“工具”。\n"
+"这也许对于某些窗口管理有所帮助。这需要重新启动 %1以生效。"
 
 #: theme_manager.cc:199
 msgid ""
-"Make transient windows follow the front window when toggling between the "
-"editor and mixer.\n"
+"Make transient windows follow the front window when toggling between the editor "
+"and mixer.\n"
 "This requires a restart of %1 to take effect"
 msgstr ""
+"在编辑器和混音器之间切换时,让临时窗口跟随前方窗口。\n"
+"这需要重新启动 %1以生效。"
 
 #: theme_manager.cc:620
 msgid "Color Palette"
-msgstr ""
+msgstr "颜料调色板"
 
 #: time_axis_view.cc:148
 msgid "Track/Bus name (double click to edit)"
-msgstr ""
+msgstr "音轨/总线名称(双击即可编辑)"
 
 #: time_axis_view_item.cc:345
 msgid "new duration %1 frame is out of bounds for %2"
 msgid_plural "new duration of %1 frames is out of bounds for %2"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "新的音长 %1 帧超出了 %2 的边界"
 
 #: time_fx_dialog.cc:62
 msgid "Quick but Ugly"
-msgstr "快速(但是丑陋)"
+msgstr "快速(但不优美)"
 
 #: time_fx_dialog.cc:63
 msgid "Skip Anti-aliasing"
@@ -12187,11 +12456,11 @@ msgstr "跳过自动对齐"
 
 #: time_fx_dialog.cc:64
 msgid "Contents:"
-msgstr "内容:"
+msgstr "内容:"
 
 #: time_fx_dialog.cc:65
 msgid "Minimize time distortion"
-msgstr ""
+msgstr "减少时间扭曲"
 
 #: time_fx_dialog.cc:66
 msgid "Preserve Formants"
@@ -12199,11 +12468,11 @@ msgstr "保持共振峰"
 
 #: time_fx_dialog.cc:71
 msgid "TimeFXDialog"
-msgstr ""
+msgstr "时间特效对话框"
 
 #: time_fx_dialog.cc:74
 msgid "Pitch Shift Audio"
-msgstr "音调移动音频"
+msgstr "音高替换音频"
 
 #: time_fx_dialog.cc:76
 msgid "Time Stretch Audio"
@@ -12211,27 +12480,27 @@ msgstr "时间延伸音频"
 
 #: time_fx_dialog.cc:104 transpose_dialog.cc:41
 msgid "Octaves:"
-msgstr "八度:"
+msgstr "八度:"
 
 #: time_fx_dialog.cc:109 transpose_dialog.cc:46
 msgid "Semitones:"
-msgstr "半音:"
+msgstr "半音:"
 
 #: time_fx_dialog.cc:114
 msgid "Cents:"
-msgstr ""
+msgstr "音分:"
 
 #: time_fx_dialog.cc:122
 msgid "Time|Shift"
-msgstr ""
+msgstr "时间|替换"
 
 #: time_fx_dialog.cc:146 time_fx_dialog.cc:149
 msgid "TimeFXButton"
-msgstr ""
+msgstr "时间特效按钮"
 
 #: time_fx_dialog.cc:154
 msgid "Stretch/Shrink"
-msgstr "伸展/收缩"
+msgstr "延伸/收缩"
 
 #: time_fx_dialog.cc:164
 msgid "<b>Progress</b>"
@@ -12239,75 +12508,75 @@ msgstr "<b>进程</b>"
 
 #: time_info_box.cc:124
 msgid "Start recording at auto-punch start"
-msgstr "开始在自动Punch点录音"
+msgstr "在自动切换起点开始录制"
 
 #: time_info_box.cc:125
 msgid "Stop recording at auto-punch end"
-msgstr "在自动Punch点停止录音"
+msgstr "在自动切换终点停止录制"
 
 #: time_selection.cc:40
 msgid "programming error: request for non-existent audio range (%1)!"
-msgstr "程序错误: 要求不存在的音频范围(%1)!"
+msgstr "程序错误: 需要的音频范围(%1)不存在!"
 
 #: transform_dialog.cc:39
 msgid "this note's"
-msgstr ""
+msgstr "这个音符的"
 
 #: transform_dialog.cc:40
 msgid "the previous note's"
-msgstr ""
+msgstr "上一个音符的"
 
 #: transform_dialog.cc:41
 msgid "this note's index"
-msgstr ""
+msgstr "这个音符的索引"
 
 #: transform_dialog.cc:42
 msgid "the number of notes"
-msgstr ""
+msgstr "音符的数目"
 
 #: transform_dialog.cc:43
 msgid "exactly"
-msgstr ""
+msgstr "精确地"
 
 #: transform_dialog.cc:44
 msgid "a random number from"
-msgstr ""
+msgstr "一个随机数来自于"
 
 #: transform_dialog.cc:55
 msgid "equal steps from"
-msgstr ""
+msgstr "相同步长来自于"
 
 #: transform_dialog.cc:58
 msgid "note number"
-msgstr ""
+msgstr "音符编号"
 
 #: transform_dialog.cc:59
 msgid "velocity"
-msgstr ""
+msgstr "力度"
 
 #: transform_dialog.cc:60
 msgid "start time"
-msgstr ""
+msgstr "起点时间"
 
 #: transform_dialog.cc:61
 msgid "length"
-msgstr ""
+msgstr "长度"
 
 #: transform_dialog.cc:82 transform_dialog.cc:113
 msgid "Transform"
-msgstr ""
+msgstr "变换"
 
 #: transform_dialog.cc:91
 msgid "Set "
-msgstr ""
+msgstr "集"
 
 #: transpose_dialog.cc:30
 msgid "Transpose MIDI"
-msgstr ""
+msgstr "变调 MIDI"
 
 #: transpose_dialog.cc:55
 msgid "Transpose"
-msgstr ""
+msgstr "变调"
 
 #: ui_config.cc:163 ui_config.cc:300
 msgid "Loading default ui configuration file %1"
@@ -12315,39 +12584,39 @@ msgstr "载入默认用户界面配置文件 %1"
 
 #: ui_config.cc:166 ui_config.cc:303
 msgid "cannot read default ui configuration file \"%1\""
-msgstr "无法读取默认用户界面配置文件\"%1\""
+msgstr "无法读取默认用户界面配置文件 \"%1\""
 
 #: ui_config.cc:169 ui_config.cc:308
 msgid "default ui configuration file \"%1\" not loaded successfully."
-msgstr "默认用户界面配置文件 \"%1\" 载入不成功"
+msgstr "默认用户界面配置文件 \"%1\" 载入不成功。"
 
 #: ui_config.cc:177
 msgid "Could not find default UI configuration file %1"
-msgstr ""
+msgstr "无法找到默认用户界面配置文件\"%1\""
 
 #: ui_config.cc:219
 msgid "Loading color file %1"
-msgstr ""
+msgstr "载入颜色文件 %1"
 
 #: ui_config.cc:222
 msgid "cannot read color file \"%1\""
-msgstr ""
+msgstr "无法读取颜色文件 %1"
 
 #: ui_config.cc:227
 msgid "color file \"%1\" not loaded successfully."
-msgstr ""
+msgstr "颜色文件 %1载入不成功"
 
 #: ui_config.cc:233
 msgid "Color file %1 not found"
-msgstr ""
+msgstr "找不到颜色文件 %1"
 
 #: ui_config.cc:282 ui_config.cc:361
 msgid "Color file %1 not saved"
-msgstr ""
+msgstr "尚未保存颜色文件 %1"
 
 #: ui_config.cc:317
 msgid "Loading user ui configuration file %1"
-msgstr "载入用户界面配置文件%1"
+msgstr "载入用户界面配置文件 %1"
 
 #: ui_config.cc:320
 msgid "cannot read ui configuration file \"%1\""
@@ -12355,87 +12624,87 @@ msgstr "无法读取用户界面配置文件 \"%1\""
 
 #: ui_config.cc:325
 msgid "user ui configuration file \"%1\" not loaded successfully."
-msgstr "用户的用户界面配置文件 \"%1\" 载入不成功"
+msgstr "用户的用户界面配置文件 \"%1\" 载入不成功。"
 
 #: ui_config.cc:333
 msgid "could not find any ui configuration file, canvas will look broken."
-msgstr "找不到任何用户界面配置文件, 画布看起来会破破的."
+msgstr "找不到任何用户界面配置文件,版面看起来将不大美观。"
 
 #: ui_config.cc:351
 msgid "Config file %1 not saved"
-msgstr "配置文件 %1 还没保存"
+msgstr "尚未保存配置文件 %1"
 
 #: ui_config.cc:592
 msgid "Color %1 not found"
-msgstr ""
+msgstr "找不到颜色 %1"
 
 #: ui_config.cc:662
 msgid "Unable to find UI style file %1 in search path %2. %3 will look strange"
-msgstr "在搜索路径 %2 下找不到用户界面样式文件 %1 . %3 看起来会怪怪地"
+msgstr "在搜索路径 %2 下找不到用户界面样式文件 %1。%3 看起来将不大美观。"
 
 #: utils.cc:117 utils.cc:160
 msgid "bad XPM header %1"
-msgstr ""
+msgstr "损坏的 XPM 报头 %1"
 
 #: utils.cc:577
 msgid "cannot find XPM file for %1"
-msgstr ""
+msgstr "找不到 XPM 文件提供给 %1"
 
 #: utils.cc:597 utils.cc:627 utils.cc:641
 msgid "default"
-msgstr ""
+msgstr "默认"
 
 #: utils.cc:642
 msgid "icon \"%1\" not found for icon set \"%2\", fallback to default"
-msgstr ""
+msgstr "找不到图标 \"%1\" 提供给图标集 \"%2\",退回默认状态"
 
 #: utils.cc:649
 msgid "cannot find icon image for %1 using %2"
-msgstr ""
+msgstr "找不到图标图像提供给 %1 使用 %2"
 
 #: utils.cc:666 utils.cc:682
 msgid "Caught exception while loading icon named %1"
-msgstr ""
+msgstr "载入命名为 %1 的图标时遇到异常"
 
 #: add_video_dialog.cc:54
 msgid "Set Video Track"
-msgstr ""
+msgstr "设置视频轨道"
 
 #: add_video_dialog.cc:62
 msgid "Open Video Monitor Window"
-msgstr ""
+msgstr "打开视频监控窗口"
 
 #: add_video_dialog.cc:63
 msgid "Adjust Session Framerate to Match Video Framerate"
-msgstr ""
+msgstr "调整会话帧率匹配视频帧率"
 
 #: add_video_dialog.cc:65
 msgid "Reload docroot"
-msgstr ""
+msgstr "重新载入文档根"
 
 #: add_video_dialog.cc:120
 msgid "Video files"
-msgstr ""
+msgstr "视频文件"
 
 #: add_video_dialog.cc:149
 msgid "<b>Video Information</b>"
-msgstr ""
+msgstr "<b>视频信息</b>"
 
 #: add_video_dialog.cc:152
 msgid "Start:"
-msgstr ""
+msgstr "起点:"
 
 #: add_video_dialog.cc:158
 msgid "Frame rate:"
-msgstr ""
+msgstr "帧率:"
 
 #: add_video_dialog.cc:161
 msgid "Aspect Ratio:"
-msgstr ""
+msgstr "长宽比:"
 
 #: add_video_dialog.cc:244
 msgid "VideoServerIndex"
-msgstr ""
+msgstr "视频服务索引"
 
 #: add_video_dialog.cc:675
 msgid " %1 fps"
@@ -12443,52 +12712,62 @@ msgstr ""
 
 #: video_timeline.cc:468
 msgid ""
-"Parsing video file info failed. Is the Video Server running? Is the file "
-"readable by the Video Server? Does the docroot match? Is it a video file?"
+"Parsing video file info failed. Is the Video Server running? Is the file readable "
+"by the Video Server? Does the docroot match? Is it a video file?"
 msgstr ""
+"解析视频文件信息失败。视频服务器是否正在运行吗?视频服务器是否可辨识该文件?文档根"
+"是否匹配?这是一个视频文件吗?"
 
 #: video_timeline.cc:506
 msgid ""
-"Failed to set session-framerate: '%1' does not have a corresponding option "
-"setting in %2."
-msgstr ""
+"Failed to set session-framerate: '%1' does not have a corresponding option setting "
+"in %2."
+msgstr "设置会话帧率失败:'%1' 的选项设置与在 %2 里的不一致。"
 
 #: video_timeline.cc:514
 msgid ""
-"Video file's framerate is not equal to %1 session timecode's framerate: '%2' "
-"vs '%3'"
-msgstr ""
+"Video file's framerate is not equal to %1 session timecode's framerate: '%2' vs "
+"'%3'"
+msgstr "视频文件的帧率不等于 %1 会话时间码帧率: '%2' vs '%3'"
 
 #: video_timeline.cc:587
 msgid ""
-"Video-server docroot mismatch. %1: '%2', video-server: '%3'. This usually "
-"means that the video server was not started by %1 and uses a different "
-"document-root."
+"Video-server docroot mismatch. %1: '%2', video-server: '%3'. This usually means "
+"that the video server was not started by %1 and uses a different document-root."
 msgstr ""
+"视频文件文档根不匹配。%1: '%2',视频服务器:'%3'。这通常意味着视频服务器未能通过 "
+"%1 启动,并且使用着一个不同的文档根。"
 
 #: video_timeline.cc:724
 msgid ""
-"Video-monitor 'xjadeo' was not found. Please install http://xjadeo.sf.net/ "
-"(a custom path to xjadeo can be specified by setting the XJREMOTE "
-"environment variable. It should point to an application compatible with "
-"xjadeo's remote-control interface 'xjremote').\n"
+"Video-monitor 'xjadeo' was not found. Please install http://xjadeo.sf.net/ (a "
+"custom path to xjadeo can be specified by setting the XJREMOTE environment "
+"variable. It should point to an application compatible with xjadeo's remote-"
+"control interface 'xjremote').\n"
 "\n"
 "see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
+"视频监控 'xjadeo' 未找到。请安装 http://xjadeo.sf.net/ (可以通过设置 XJREMOTE 环境"
+"变量来指定一个到 xjadeo 的定制路径。它应该指向一个兼容 xjadeo 遥控界面  'xjremote' "
+"的应用程序)。\n"
+"\n"
+"请参阅 http://manual.ardour.org/video-timeline/setup/"
 
 #: video_timeline.cc:739
 msgid "Video-monitor 'xjadeo' cannot be launched."
-msgstr ""
+msgstr "视频监控 'xjadeo' 无法启动。"
 
 #: video_timeline.cc:766
 msgid ""
-"Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.7.7 or "
-"later. http://xjadeo.sf.net/"
+"Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.7.7 or later. "
+"http://xjadeo.sf.net/"
 msgstr ""
+"视频监控 'xjadeo' 太过老旧。请安装 xjadeo 0.7.7 或者更新的版本。 http://xjadeo.sf."
+"net/"
 
 #: video_monitor.cc:285
 msgid "Video Monitor: File Not Found."
-msgstr ""
+msgstr "视频监控:找不到文件。"
 
 #: transcode_ffmpeg.cc:56
 msgid ""
@@ -12496,58 +12775,74 @@ msgid ""
 "Video import and export is not possible until you install those tools.\n"
 "%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
 "\n"
-"The tools are included with the %1 releases from ardour.org and also "
-"available with the video-server at http://x42.github.com/harvid/\n"
+"The tools are included with the %1 releases from ardour.org and also available "
+"with the video-server at http://x42.github.com/harvid/\n"
 "\n"
-"Important: the files need to be installed in $PATH and named ffmpeg_harvid "
-"and ffprobe_harvid.\n"
-"If you already have a suitable ffmpeg installation on your system, we "
-"recommend creating symbolic links from ffmpeg to ffmpeg_harvid and from "
-"ffprobe to ffprobe_harvid.\n"
+"Important: the files need to be installed in $PATH and named ffmpeg_harvid and "
+"ffprobe_harvid.\n"
+"If you already have a suitable ffmpeg installation on your system, we recommend "
+"creating symbolic links from ffmpeg to ffmpeg_harvid and from ffprobe to "
+"ffprobe_harvid.\n"
 "\n"
 "see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
+"在这个系统上没找到 ffprobe 或者 ffmpeg 可执行文件。\n"
+"视频导入和导出无法进行,除非您安装这些工具。\n"
+"%1 需要 ffmpeg 和 ffprobe,来自 ffmpeg.org 1.1 或者更新的版本。\n"
+"\n"
+"这工具包括来自 ardour.org 的 %1,并且也可用于 http://x42.github.com/harvid/  上的视"
+"频服务。\n"
+"\n"
+"注意:这些文件需要安装在 $PATH 并且命名为 ffmpeg_harvid 和 ffprobe_harvid 。\n"
+"如果您在您的系统上已经安装有一个合适的 ffmpeg,我们建议给 ffmpeg 创建符号链接为 "
+"ffmpeg_harvid,给 ffprobe 创建符号链接为  ffprobe_harvid 。\n"
+"\n"
+"请参阅 http://manual.ardour.org/video-timeline/setup/"
 
 #: transcode_video_dialog.cc:56
 msgid "Transcode/Import Video File "
-msgstr ""
+msgstr "转码/导入视频文件"
 
 #: transcode_video_dialog.cc:58
 msgid "Output File:"
-msgstr ""
+msgstr "导出文件:"
 
 #: transcode_video_dialog.cc:61 export_video_dialog.cc:85
 msgid "Abort"
-msgstr ""
+msgstr "中止"
 
 #: transcode_video_dialog.cc:63
 msgid "Height = "
-msgstr ""
+msgstr "高度 = "
 
 #: transcode_video_dialog.cc:66
 msgid "Manual Override"
-msgstr ""
+msgstr "手动覆盖"
 
 #: transcode_video_dialog.cc:70 export_video_dialog.cc:103
 msgid "Debug Mode: Print ffmpeg command and output to stdout."
-msgstr ""
+msgstr "调试模式:打印 ffmpeg 命令并输出到标准输出。"
 
 #: transcode_video_dialog.cc:107
 msgid "<b>File Information</b>"
-msgstr ""
+msgstr "<b>文件信息</b>"
 
 #: transcode_video_dialog.cc:113
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system. Video Import "
-"is not possible until you install those tools. See the Log window for more "
+"No ffprobe or ffmpeg executables could be found on this system. Video Import is "
+"not possible until you install those tools. See the Log window for more "
 "information."
 msgstr ""
+"在这个系统上没找到 ffprobe 或者 ffmpeg 可执行文件。视频导入无法进行,除非您安装这些"
+"工具。更多的信息请参阅日志窗口。"
 
 #: transcode_video_dialog.cc:120
 msgid ""
 "File-info can not be read. Most likely '%1' is not a valid video-file or an "
 "unsupported video codec or format."
 msgstr ""
+"无法读取文件信息。极有可能 '‘% 1' 不是一个有效的视频文件,或者是一个不支持的视频编"
+"解码器或格式。"
 
 #: transcode_video_dialog.cc:134
 msgid "FPS:"
@@ -12555,15 +12850,15 @@ msgstr ""
 
 #: transcode_video_dialog.cc:136
 msgid "Duration:"
-msgstr ""
+msgstr "音长:"
 
 #: transcode_video_dialog.cc:138
 msgid "Codec:"
-msgstr ""
+msgstr "编码:"
 
 #: transcode_video_dialog.cc:140
 msgid "Geometry:"
-msgstr ""
+msgstr "几何形状:"
 
 #: transcode_video_dialog.cc:155
 msgid "??"
@@ -12571,101 +12866,106 @@ msgstr ""
 
 #: transcode_video_dialog.cc:176
 msgid "<b>Import Settings</b>"
-msgstr ""
+msgstr "<b>导入设置</b>"
 
 #: transcode_video_dialog.cc:181
 msgid "Reference From Current Location (Previously Transcoded Files Only)"
-msgstr ""
+msgstr "从当前位置引用(仅上一个已转码文件)"
 
 #: transcode_video_dialog.cc:183
 msgid "Import/Transcode Video to Session"
-msgstr ""
+msgstr "导入/转码视频到会话"
 
 #: transcode_video_dialog.cc:191
 msgid "Do Not Import Video (Audio Import Only)"
-msgstr ""
+msgstr "不要导入视频(仅导入音频)"
 
 #: transcode_video_dialog.cc:200
 msgid "Scale Video: Width = "
-msgstr ""
+msgstr "缩放视频:宽度 = "
 
 #: transcode_video_dialog.cc:207
 msgid "Original Width"
-msgstr ""
+msgstr "原始宽度"
 
 #: transcode_video_dialog.cc:222
 msgid "Bitrate (KBit/s):"
-msgstr ""
+msgstr "比特率(码率 KBit/s):"
 
 #: transcode_video_dialog.cc:227
 msgid "Extract Audio:"
-msgstr ""
+msgstr "提取音频:"
 
 #: transcode_video_dialog.cc:232
 msgid "No Audio Track Present"
-msgstr ""
+msgstr "无音频轨道呈现"
 
 #: transcode_video_dialog.cc:235
 msgid "Do Not Extract Audio"
-msgstr ""
+msgstr "无法提取音频"
 
 #: transcode_video_dialog.cc:350
 msgid "Extracting Audio.."
-msgstr ""
+msgstr "音频提取中…"
 
 #: transcode_video_dialog.cc:353
 msgid "Audio Extraction Failed."
-msgstr ""
+msgstr "音频提取失败。"
 
 #: transcode_video_dialog.cc:379
 msgid "Transcoding Video.."
-msgstr ""
+msgstr "视频转码中…"
 
 #: transcode_video_dialog.cc:413
 msgid "Transcoding Failed."
-msgstr ""
+msgstr "转码失败。"
 
 #: transcode_video_dialog.cc:503
 msgid "Save Transcoded Video File"
-msgstr ""
+msgstr "保存已转码视频文件"
 
 #: video_server_dialog.cc:52
 msgid "Launch Video Server"
-msgstr ""
+msgstr "启动视频服务器"
 
 #: video_server_dialog.cc:53
 msgid "Server Executable:"
-msgstr ""
+msgstr "服务器可执行:"
 
 #: video_server_dialog.cc:55
 msgid "Server Docroot:"
-msgstr ""
+msgstr "服务器文档根:"
 
 #: video_server_dialog.cc:61
 msgid "Don't show this dialog again. (Reset in Edit->Preferences)."
-msgstr ""
+msgstr "不再显示这个对话框。(可在 编辑 -> 首选项 里重置)。"
 
 #: video_server_dialog.cc:97
 msgid ""
 "The external video server 'harvid' can not be found.\n"
-"The tool is included with the %1 releases from ardour.org, alternatively you "
-"can download it from http://x42.github.com/harvid/ or acquire it from your "
+"The tool is included with the %1 releases from ardour.org, alternatively you can "
+"download it from http://x42.github.com/harvid/ or acquire it from your "
 "distribution.\n"
 "\n"
 "see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
+"找不到外部视频服务器 'harvid' 。\n"
+"这工具包括来自 ardour.org 的 %1,另外您可以从 http://x42.github.com/harvid/ 下载"
+"它,或者从您的发行版获得它。\n"
+"\n"
+"请参阅 http://manual.ardour.org/video-timeline/setup/"
 
 #: video_server_dialog.cc:129
 msgid "Listen Address:"
-msgstr ""
+msgstr "试听地址:"
 
 #: video_server_dialog.cc:134
 msgid "Listen Port:"
-msgstr ""
+msgstr "试听端口:"
 
 #: video_server_dialog.cc:139
 msgid "Cache Size:"
-msgstr ""
+msgstr "缓存大小:"
 
 #: video_server_dialog.cc:145
 msgid ""
@@ -12673,235 +12973,242 @@ msgid ""
 "The server configured in Edit -> Preferences -> Video is not reachable.\n"
 "Do you want %1 to launch 'harvid' on this machine?"
 msgstr ""
+"%1 依赖于外部视频服务器以获取视频时间线。\n"
+"这个已配置在 编辑 -> 首选项 -> 视频 的服务器无法访问。\n"
+"您是否要 %1 在这台机器上启动 'harvid' ?"
 
 #: video_server_dialog.cc:189
 msgid "Set Video Server Executable"
-msgstr ""
+msgstr "设置视频服务器可执行"
 
 #: video_server_dialog.cc:209
 msgid "Server docroot"
-msgstr ""
+msgstr "服务器文档根"
 
 #: utils_videotl.cc:60
 msgid "Destination is outside Video Server's docroot. "
-msgstr ""
+msgstr "目的地是视频服务器的文档根之外。"
 
 #: utils_videotl.cc:61
 msgid ""
-"The destination file path is outside of the Video Server's docroot. The file "
-"will not be readable by the Video Server. Do you still want to continue?"
+"The destination file path is outside of the Video Server's docroot. The file will "
+"not be readable by the Video Server. Do you still want to continue?"
 msgstr ""
+"目的地文件路径是处在视频服务器文档根之外。这个文件将无法被视频服务器读取。您是否要"
+"继续?"
 
 #: utils_videotl.cc:64
 msgid "Continue"
-msgstr ""
+msgstr "继续"
 
 #: utils_videotl.cc:70
 msgid "Confirm Overwrite"
-msgstr ""
+msgstr "确认覆盖"
 
 #: utils_videotl.cc:71
 msgid "A file with the same name already exists.  Do you want to overwrite it?"
-msgstr ""
+msgstr "已有相同名称的文件存在。您是否要重写覆盖它?"
 
 #: utils_videotl.cc:81 utils_videotl.cc:97
 msgid "Cannot create video folder \"%1\" (%2)"
-msgstr ""
+msgstr "无法创建视频文件夹 \"%1\" (%2)"
 
 #: export_video_dialog.cc:71
 msgid "Export Video File "
-msgstr ""
+msgstr "导出视频文件"
 
 #: export_video_dialog.cc:82
 msgid "Video:"
-msgstr ""
+msgstr "视频:"
 
 #: export_video_dialog.cc:87
 msgid "Scale Video (W x H):"
-msgstr ""
+msgstr "缩放视频(宽 x 高):"
 
 #: export_video_dialog.cc:88
 msgid "Retain Aspect"
-msgstr ""
+msgstr "保持长宽比"
 
 #: export_video_dialog.cc:93
 msgid "Set Aspect Ratio:"
-msgstr ""
+msgstr "设置长宽比:"
 
 #: export_video_dialog.cc:94
 msgid "Normalize Audio"
-msgstr ""
+msgstr "规范化音频"
 
 #: export_video_dialog.cc:95
 msgid "2 Pass Encoding"
-msgstr ""
+msgstr "二次编码"
 
 #: export_video_dialog.cc:96
 msgid "Codec Optimizations:"
-msgstr ""
+msgstr "解码器优化:"
 
 #: export_video_dialog.cc:98
 msgid "Deinterlace"
-msgstr ""
+msgstr "反交错"
 
 #: export_video_dialog.cc:99
 msgid "Use [2] B-frames (MPEG 2 or 4 only)"
-msgstr ""
+msgstr "使用 [2] B-帧(仅 MPEG 2 或 4)"
 
 #: export_video_dialog.cc:100
 msgid "Override FPS (Default is to retain FPS from the input video file):"
-msgstr ""
+msgstr "覆盖 FPS(默认是覆盖到从输入视频文件保留的 FPS):"
 
 #: export_video_dialog.cc:101
 msgid "Include Session Metadata"
-msgstr ""
+msgstr "包括会话元数据"
 
 #: export_video_dialog.cc:119
 msgid ""
-"No ffprobe or ffmpeg executables could be found on this system. Video Export "
-"is not possible until you install those tools. See the Log window for more "
+"No ffprobe or ffmpeg executables could be found on this system. Video Export is "
+"not possible until you install those tools. See the Log window for more "
 "information."
 msgstr ""
+"在这个系统上没找到 ffprobe 或者 ffmpeg 可执行文件。视频导出无法进行,除非您安装这些"
+"工具。更多的信息请参阅日志窗口。"
 
 #: export_video_dialog.cc:130
 msgid "<b>Output:</b> (file extension defines format)"
-msgstr ""
+msgstr "<b>导出:</b>(以文件扩展名决定格式)"
 
 #: export_video_dialog.cc:140
 msgid "<b>Input Video:</b>"
-msgstr ""
+msgstr "<b>导入视频</b>"
 
 #: export_video_dialog.cc:151
 msgid "Audio:"
-msgstr ""
+msgstr "音频:"
 
 #: export_video_dialog.cc:153
 msgid "Master Bus"
-msgstr ""
+msgstr "主控总线"
 
 #: export_video_dialog.cc:158
 msgid "from the %1 session's start to the session's end"
-msgstr ""
+msgstr "从 %1 会话的起点到会话的终点"
 
 #: export_video_dialog.cc:161
 msgid "<b>Settings:</b>"
-msgstr ""
+msgstr "<b>设置</b>"
 
 #: export_video_dialog.cc:169
 msgid "Range:"
-msgstr ""
+msgstr "范围:"
 
 #: export_video_dialog.cc:172
 msgid "Preset:"
-msgstr ""
+msgstr "预设:"
 
 #: export_video_dialog.cc:175
 msgid "Video Codec:"
-msgstr ""
+msgstr "视频编码:"
 
 #: export_video_dialog.cc:178
 msgid "Video KBit/s:"
-msgstr ""
+msgstr "视频 KBit/s:"
 
 #: export_video_dialog.cc:181
 msgid "Audio Codec:"
-msgstr ""
+msgstr "音频编码:"
 
 #: export_video_dialog.cc:184
 msgid "Audio KBit/s:"
-msgstr ""
+msgstr "音频 KBit/s:"
 
 #: export_video_dialog.cc:187
 msgid "Audio Samplerate:"
-msgstr ""
+msgstr "音频采样率:"
 
-#: export_video_dialog.cc:222 export_video_dialog.cc:231
-#: export_video_dialog.cc:830 export_video_dialog.cc:833
+#: export_video_dialog.cc:222 export_video_dialog.cc:231 export_video_dialog.cc:830
+#: export_video_dialog.cc:833
 msgid "(default for format)"
-msgstr ""
+msgstr "(默认格式)"
 
-#: export_video_dialog.cc:242 export_video_dialog.cc:255
-#: export_video_dialog.cc:837 export_video_dialog.cc:846
+#: export_video_dialog.cc:242 export_video_dialog.cc:255 export_video_dialog.cc:837
+#: export_video_dialog.cc:846
 msgid "(default)"
-msgstr ""
+msgstr "(默认)"
 
 #: export_video_dialog.cc:256 export_video_dialog.cc:840
 msgid "(retain)"
-msgstr ""
+msgstr "(保留)"
 
 #: export_video_dialog.cc:348
 msgid "from 00:00:00:00 to the video's end"
-msgstr ""
+msgstr "从 00:00:00:00 到视频终点"
 
 #: export_video_dialog.cc:350
 msgid "from the video's start to the video's end"
-msgstr ""
+msgstr "从视频起点到视频终点"
 
 #: export_video_dialog.cc:353
 msgid "Selected range"
-msgstr ""
+msgstr "已选择的范围"
 
 #: export_video_dialog.cc:589
 msgid "Normalizing audio"
-msgstr ""
+msgstr "规范化音频"
 
 #: export_video_dialog.cc:593
 msgid "Exporting audio"
-msgstr ""
+msgstr "音频导出中"
 
 #: export_video_dialog.cc:648
 msgid "Exporting Audio..."
-msgstr ""
+msgstr "音频导出中…"
 
 #: export_video_dialog.cc:705
 msgid ""
-"Export Video: Cannot query duration of video-file, using duration from "
-"timeline instead."
-msgstr ""
+"Export Video: Cannot query duration of video-file, using duration from timeline "
+"instead."
+msgstr "导出视频:无法查询视频文件长度,视频时间线长度代替。"
 
 #: export_video_dialog.cc:735
 msgid "Export Video: export-range does not include video."
-msgstr ""
+msgstr "导出视频:导出范围无法包括视频。"
 
 #: export_video_dialog.cc:748
 msgid "Export Video: No Master Out Ports to Connect for Audio Export"
-msgstr ""
+msgstr "导出视频:没有主控输出端口可连接给音频导出"
 
 #: export_video_dialog.cc:790
 msgid "Encoding Video..."
-msgstr ""
+msgstr "视频编码中…"
 
 #: export_video_dialog.cc:810
 msgid "Export Video: Video input file cannot be read."
-msgstr ""
+msgstr "导出视频:无法读取视频导入文件。"
 
 #: export_video_dialog.cc:916
 msgid "Encoding Video.. Pass 1/2"
-msgstr ""
+msgstr "视频编码中…通过 1/2"
 
 #: export_video_dialog.cc:928
 msgid "Encoding Video.. Pass 2/2"
-msgstr ""
+msgstr "视频编码中…通过 2/2"
 
 #: export_video_dialog.cc:1031
 msgid "Transcoding failed."
-msgstr ""
+msgstr "转码失败。"
 
 #: export_video_dialog.cc:1267 export_video_dialog.cc:1287
 msgid "Save Exported Video File"
-msgstr ""
+msgstr "保存已导出的视频文件"
 
 #: export_video_infobox.cc:33
 msgid "Video Export Info"
-msgstr ""
+msgstr "视频导出信息"
 
 #: export_video_infobox.cc:34
 msgid "Do Not Show This Dialog Again (Reset in Edit > Preferences > Video)."
-msgstr ""
+msgstr "不再显示这个对话框。(可在 编辑 > 首选项 > 视频 里重置)。"
 
 #: export_video_infobox.cc:46
 msgid "<b>Video Export Info</b>"
-msgstr ""
+msgstr "<b>视频导出信息</b>"
 
 #: export_video_infobox.cc:51
 msgid ""
@@ -12911,6 +13218,11 @@ msgid ""
 "\n"
 "Open Manual in Browser? "
 msgstr ""
+"视频编码是一项带有许多细节的不简单的任务。\n"
+"\n"
+"请参阅手册,位于 %1/video-timeline/operations/#export 。\n"
+"\n"
+"在浏览器里打开手册?"
 
 #~ msgid "Track mode:"
 #~ msgstr "音轨模式:"
@@ -13277,11 +13589,9 @@ msgstr ""
 #~ msgstr "MIDI驱动:"
 
 #~ msgid ""
-#~ "No JACK server found anywhere on this system. Please install JACK and "
-#~ "restart"
+#~ "No JACK server found anywhere on this system. Please install JACK and restart"
 #~ msgstr ""
-#~ "No JACK server found anywhere on this system. Please install JACK and "
-#~ "restart"
+#~ "No JACK server found anywhere on this system. Please install JACK and restart"
 
 #~ msgid "Server:"
 #~ msgstr "服务器:"
@@ -13346,8 +13656,7 @@ msgstr ""
 #~ "  -c, --name <name>           Use a specific jack client name, default is "
 #~ "ardour\n"
 #~ msgstr ""
-#~ "  -c, --name <name>           用一个特殊的JACK用户名称, 默认名称是: "
-#~ "ardour\n"
+#~ "  -c, --name <name>           用一个特殊的JACK用户名称, 默认名称是: ardour\n"
 
 #~ msgid "follows order of editor"
 #~ msgstr "编辑器的如下顺序"
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 448a8d3..d02171a 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -30,9 +30,10 @@
 #include "ardour/io_processor.h"
 #include "ardour/midi_port.h"
 #include "ardour/midiport_manager.h"
+#include "ardour/port.h"
+#include "ardour/profile.h"
 #include "ardour/session.h"
 #include "ardour/user_bundle.h"
-#include "ardour/port.h"
 
 #include "control_protocol/control_protocol.h"
 
@@ -337,7 +338,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 	boost::shared_ptr<PortGroup> bus (new PortGroup (string_compose (_("%1 Busses"), PROGRAM_NAME)));
 	boost::shared_ptr<PortGroup> track (new PortGroup (string_compose (_("%1 Tracks"), PROGRAM_NAME)));
 	boost::shared_ptr<PortGroup> system (new PortGroup (_("Hardware")));
-	boost::shared_ptr<PortGroup> ardour (new PortGroup (string_compose (_("%1 Misc"), PROGRAM_NAME)));
+	boost::shared_ptr<PortGroup> program (new PortGroup (string_compose (_("%1 Misc"), PROGRAM_NAME)));
 	boost::shared_ptr<PortGroup> other (new PortGroup (_("Other")));
 
 	/* Find the IOs which have bundles for routes and their processors.  We store
@@ -420,39 +421,48 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 		}
 	}
 
-	/* Ardour stuff */
+	/* miscellany */
 
-	if (!inputs) {
-		ardour->add_bundle (session->the_auditioner()->output()->bundle());
-		ardour->add_bundle (session->click_io()->bundle());
-		/* Note: the LTC ports do not have the usual ":audio_out 1" postfix, so
-		 *  ardour->add_bundle (session->ltc_output_io()->bundle());
-		 *  won't work
-		 */
-		boost::shared_ptr<Bundle> ltc (new Bundle (_("LTC Out"), inputs));
-		ltc->add_channel (_("LTC Out"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_output_port()->name()));
-		ardour->add_bundle (ltc);
-	} else {
-		boost::shared_ptr<Bundle> ltc (new Bundle (_("LTC In"), inputs));
-		ltc->add_channel (_("LTC In"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_input_port()->name()));
-		ardour->add_bundle (ltc);
+	if (type == DataType::AUDIO || type == DataType::NIL) {
+		if (!inputs) {
+			program->add_bundle (session->the_auditioner()->output()->bundle());
+			program->add_bundle (session->click_io()->bundle());
+			/* Note: the LTC ports do not have the usual ":audio_out 1" postfix, so
+			 *  program->add_bundle (session->ltc_output_io()->bundle());
+			 *  won't work
+			 */
+			boost::shared_ptr<Bundle> ltc (new Bundle (_("LTC Out"), inputs));
+			ltc->add_channel (_("LTC Out"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_output_port()->name()));
+			program->add_bundle (ltc);
+		} else {
+			boost::shared_ptr<Bundle> ltc (new Bundle (_("LTC In"), inputs));
+			ltc->add_channel (_("LTC In"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_input_port()->name()));
+			program->add_bundle (ltc);
+		}
 	}
 
-	/* Ardour's control surfaces */
+	/* our control surfaces */
 
-	ControlProtocolManager& m = ControlProtocolManager::instance ();
-	for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
-		if ((*i)->protocol) {
-			list<boost::shared_ptr<Bundle> > b = (*i)->protocol->bundles ();
-			for (list<boost::shared_ptr<Bundle> >::iterator j = b.begin(); j != b.end(); ++j) {
-				if ((*j)->ports_are_inputs() == inputs) {
-					ardour->add_bundle (*j);
+	/* XXX assume for now that all control protocols with ports use
+	 * MIDI. If anyone created a control protocol that used audio ports,
+	 * this will break.
+	 */
+
+	if ((type == DataType::MIDI || type == DataType::NIL)) {
+		ControlProtocolManager& m = ControlProtocolManager::instance ();
+		for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
+			if ((*i)->protocol) {
+				list<boost::shared_ptr<Bundle> > b = (*i)->protocol->bundles ();
+				for (list<boost::shared_ptr<Bundle> >::iterator j = b.begin(); j != b.end(); ++j) {
+					if ((*j)->ports_are_inputs() == inputs) {
+						program->add_bundle (*j);
+					}
 				}
 			}
 		}
 	}
 
-	/* Ardour's sync ports */
+	/* our sync ports */
 
 	if ((type == DataType::MIDI || type == DataType::NIL)) {
 		boost::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs));
@@ -486,12 +496,13 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 				);
 		}
 
-		ardour->add_bundle (sync);
+		program->add_bundle (sync);
 	}
 
 	/* Now find all other ports that we haven't thought of yet */
 
 	std::vector<std::string> extra_system[DataType::num_types];
+	std::vector<std::string> extra_program[DataType::num_types];
 	std::vector<std::string> extra_other[DataType::num_types];
 
         string lpn (PROGRAM_NAME);
@@ -509,7 +520,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 			if (!system->has_port(p) &&
 			    !bus->has_port(p) &&
 			    !track->has_port(p) &&
-			    !ardour->has_port(p) &&
+			    !program->has_port(p) &&
 			    !other->has_port(p)) {
 
                                 /* special hack: ignore MIDI ports labelled Midi-Through. these
@@ -535,16 +546,29 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
                                         continue;
                                 }
 
-				/* can't use the audio engine for this as we are looking at non-Ardour ports */
+				/* can't use the audio engine for this as we
+				 * are looking at ports not owned by the
+				 * application, and the audio engine/port
+				 * manager doesn't seem them.
+				 */
 
 				PortEngine::PortHandle ph = AudioEngine::instance()->port_engine().get_port_by_name (p);
 				if (ph) {
 					DataType t (AudioEngine::instance()->port_engine().port_data_type (ph));
 					if (t != DataType::NIL) {
 						if (port_has_prefix (p, N_("system:")) ||
-                                                    port_has_prefix (p, N_("alsa_pcm")) ||
-                                                    port_has_prefix (p, lpnc)) {
+						    port_has_prefix (p, N_("alsa_pcm:")) ||
+						    port_has_prefix (p, N_("alsa_midi:"))) {
 							extra_system[t].push_back (p);
+						} else if (port_has_prefix (p, lpnc)) {
+							/* Hide scene ports from non-Tracks Live builds */
+							if (!ARDOUR::Profile->get_trx()) {
+								if (p.find (_("Scene ")) != string::npos) {
+									++s;
+									continue;
+								}
+							}
+							extra_program[t].push_back (p);
 						} else {
 							extra_other[t].push_back (p);
 						}
@@ -564,6 +588,15 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 	}
 
 	for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
+		if (!extra_program[*i].empty()) {
+			/* remove program name prefix from port name and use rest as bundle name */
+			std::string bundle_name = extra_program[*i].front().substr (lpnc.length());
+			boost::shared_ptr<Bundle> b = make_bundle_from_ports (extra_program[*i], *i, inputs, bundle_name);
+			program->add_bundle (b);
+		}
+	}
+
+	for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
 		if (extra_other[*i].empty()) continue;
 		std::string cp;
 		std::vector<std::string> nb;
@@ -593,20 +626,24 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 		add_group_if_not_empty (bus);
 	}
 	add_group_if_not_empty (track);
-	add_group_if_not_empty (ardour);
+	add_group_if_not_empty (program);
 	add_group_if_not_empty (system);
 
 	emit_changed ();
 }
 
 boost::shared_ptr<Bundle>
-PortGroupList::make_bundle_from_ports (std::vector<std::string> const & p, ARDOUR::DataType type, bool inputs) const
+PortGroupList::make_bundle_from_ports (std::vector<std::string> const & p, ARDOUR::DataType type, bool inputs, std::string const& bundle_name) const
 {
 	boost::shared_ptr<Bundle> b (new Bundle ("", inputs));
-
 	std::string const pre = common_prefix (p);
-	if (!pre.empty()) {
-		b->set_name (pre.substr (0, pre.length() - 1));
+
+	if (!bundle_name.empty()) {
+		b->set_name (bundle_name);
+	} else {
+		if (!pre.empty()) {
+			b->set_name (pre.substr (0, pre.length() - 1));
+		}
 	}
 
 	for (uint32_t j = 0; j < p.size(); ++j) {
@@ -796,4 +833,3 @@ PortGroupList::empty () const
 {
 	return _groups.empty ();
 }
-
diff --git a/gtk2_ardour/port_group.h b/gtk2_ardour/port_group.h
index a9dfc1a..d631f8a 100644
--- a/gtk2_ardour/port_group.h
+++ b/gtk2_ardour/port_group.h
@@ -142,7 +142,7 @@ class PortGroupList : public sigc::trackable
 	std::string common_prefix_before (std::vector<std::string> const &, std::string const &) const;
 	void emit_changed ();
 	void emit_bundle_changed (ARDOUR::Bundle::Change);
-	boost::shared_ptr<ARDOUR::Bundle> make_bundle_from_ports (std::vector<std::string> const &, ARDOUR::DataType, bool) const;
+	boost::shared_ptr<ARDOUR::Bundle> make_bundle_from_ports (std::vector<std::string> const &, ARDOUR::DataType, bool, std::string const& bundle_name = std::string()) const;
 	void maybe_add_processor_to_list (
 		boost::weak_ptr<ARDOUR::Processor>, std::list<boost::shared_ptr<ARDOUR::IO> > *, bool, std::set<boost::shared_ptr<ARDOUR::IO> > &
 		);
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index d8a872a..29e2309 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -75,6 +75,7 @@
 #include "send_ui.h"
 #include "timers.h"
 #include "tooltips.h"
+#include "new_plugin_preset_dialog.h"
 
 #include "i18n.h"
 
@@ -132,6 +133,12 @@ ProcessorEntry::ProcessorEntry (ProcessorBox* parent, boost::shared_ptr<Processo
 		_button.set_elements(ArdourButton::Element(_button.elements() & ~ArdourButton::Indicator));
 		_unknown_processor = true;
 	}
+	{
+		boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
+		if (pi && pi->plugin()) {
+			_plugin_preset_pointer = PluginPresetPtr (new PluginPreset (pi->plugin()->get_info()));
+		}
+	}
 	if (_processor) {
 
 		_vbox.pack_start (_routing_icon);
@@ -211,6 +218,60 @@ ProcessorEntry::drag_text () const
 {
 	return name (Wide);
 }
+bool
+ProcessorEntry::drag_data_get (Glib::RefPtr<Gdk::DragContext> const, Gtk::SelectionData &data)
+{
+	if (data.get_target() == "PluginPresetPtr") {
+		boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
+
+		if (!_plugin_preset_pointer || !pi) {
+			data.set (data.get_target(), 8, NULL, 0);
+			return true;
+		}
+
+		boost::shared_ptr<ARDOUR::Plugin> plugin = pi->plugin();
+		assert (plugin);
+
+		PluginManager& manager (PluginManager::instance());
+		bool fav = manager.get_status (_plugin_preset_pointer->_pip) == PluginManager::Favorite;
+
+		NewPluginPresetDialog d (plugin,
+				string_compose(_("New Favorite Preset for \"%1\""),_plugin_preset_pointer->_pip->name), !fav);
+
+		_plugin_preset_pointer->_preset.valid = false;
+
+		switch (d.run ()) {
+			case Gtk::RESPONSE_CANCEL:
+				data.set (data.get_target(), 8, NULL, 0);
+				return true;
+				break;
+
+			case Gtk::RESPONSE_NO:
+				break;
+
+			case Gtk::RESPONSE_ACCEPT:
+				if (d.name().empty()) {
+					break;
+				}
+
+				if (d.replace ()) {
+					plugin->remove_preset (d.name ());
+				}
+
+				Plugin::PresetRecord const r = plugin->save_preset (d.name());
+
+				if (!r.uri.empty ()) {
+					_plugin_preset_pointer->_preset.uri   = r.uri;
+					_plugin_preset_pointer->_preset.label = r.label;
+					_plugin_preset_pointer->_preset.user  = r.user;
+					_plugin_preset_pointer->_preset.valid = r.valid;
+				}
+		}
+		data.set (data.get_target(), 8, (const guchar *) &_plugin_preset_pointer, sizeof (PluginPresetPtr));
+		return true;
+	}
+	return false;
+}
 
 void
 ProcessorEntry::set_position (Position p, uint32_t num)
@@ -275,13 +336,39 @@ ProcessorEntry::set_enum_width (Width w)
 }
 
 void
-ProcessorEntry::led_clicked()
+ProcessorEntry::led_clicked(GdkEventButton *ev)
 {
+	bool ctrl_shift_pressed = false;
+	Keyboard::ModifierMask ctrl_shift_mask = Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier);
+
+	if (Keyboard::modifier_state_equals (ev->state, ctrl_shift_mask)) {
+		ctrl_shift_pressed = true;
+	}
+
 	if (_processor) {
 		if (_button.get_active ()) {
-			_processor->deactivate ();
+			if (ctrl_shift_pressed) {
+				_parent->all_visible_processors_active(false);
+
+				if (_position == Fader) {
+					_processor->deactivate ();
+				}
+			}
+			else {
+				_processor->deactivate ();
+			}
+
 		} else {
-			_processor->activate ();
+			if (ctrl_shift_pressed) {
+				_parent->all_visible_processors_active(true);
+
+				if (_position == Fader) {
+					_processor->activate ();
+				}
+			}
+			else {
+				_processor->activate ();
+			}
 		}
 	}
 }
@@ -328,7 +415,7 @@ ProcessorEntry::setup_tooltip ()
 			}
 			if (pi->plugin()->has_editor()) {
 				ARDOUR_UI_UTILS::set_tooltip (_button,
-						string_compose (_("<b>%1</b>\nDouble-click to show GUI.\nAlt+double-click to show generic GUI.%2"), name (Wide), postfix));
+						string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), name (Wide), Keyboard::primary_modifier_name (), postfix));
 			} else {
 				ARDOUR_UI_UTILS::set_tooltip (_button,
 						string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), name (Wide), postfix));
@@ -533,7 +620,7 @@ ProcessorEntry::Control::Control (boost::shared_ptr<AutomationControl> c, string
 		_button.show ();
 
 		_button.signal_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked));
-		_button.signal_led_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked));
+		_button.signal_led_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked_event));
 		// dup. currently timers are used :(
 		//c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
 
@@ -624,7 +711,7 @@ ProcessorEntry::Control::slider_adjusted ()
 		return;
 	}
 
-	c->set_value ( c->interface_to_internal(_adjustment.get_value ()) );
+	c->set_value ( c->interface_to_internal(_adjustment.get_value ()) , Controllable::NoGroup);
 	set_tooltip ();
 }
 
@@ -639,12 +726,20 @@ ProcessorEntry::Control::button_clicked ()
 
 	bool const n = _button.get_active ();
 
-	c->set_value (n ? 0 : 1);
+	c->set_value (n ? 0 : 1, Controllable::NoGroup);
 	_button.set_active (!n);
 	set_tooltip ();
 }
 
 void
+ProcessorEntry::Control::button_clicked_event (GdkEventButton *ev)
+{
+	(void) ev;
+
+	button_clicked ();
+}
+
+void
 ProcessorEntry::Control::control_changed ()
 {
 	boost::shared_ptr<AutomationControl> c = _control.lock ();
@@ -1007,6 +1102,30 @@ ProcessorEntry::RoutingIcon::on_expose_event (GdkEventExpose* ev)
 	return true;
 }
 
+static std::list<Gtk::TargetEntry> drop_targets()
+{
+	std::list<Gtk::TargetEntry> tmp;
+	tmp.push_back (Gtk::TargetEntry ("processor")); // from processor-box to processor-box
+	tmp.push_back (Gtk::TargetEntry ("PluginInfoPtr")); // from plugin-manager
+	tmp.push_back (Gtk::TargetEntry ("PluginPresetPtr")); // from sidebar
+	return tmp;
+}
+
+static std::list<Gtk::TargetEntry> drag_targets()
+{
+	std::list<Gtk::TargetEntry> tmp;
+	tmp.push_back (Gtk::TargetEntry ("PluginPresetPtr")); // to sidebar (optional preset)
+	tmp.push_back (Gtk::TargetEntry ("processor")); // to processor-box (copy)
+	return tmp;
+}
+
+static std::list<Gtk::TargetEntry> drag_targets_noplugin()
+{
+	std::list<Gtk::TargetEntry> tmp;
+	tmp.push_back (Gtk::TargetEntry ("processor")); // to processor box (sends, faders re-order)
+	return tmp;
+}
+
 ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelector*()> get_plugin_selector,
 			    RouteProcessorSelection& rsel, MixerStrip* parent, bool owner_is_mixer)
 	: _parent_strip (parent)
@@ -1016,6 +1135,7 @@ ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelecto
 	, _placement (-1)
 	, _visible_prefader_processors (0)
 	, _rr_selection(rsel)
+	, processor_display (drop_targets())
 	, _redisplay_pending (false)
 
 {
@@ -1043,6 +1163,7 @@ ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelecto
 
 	processor_display.Reordered.connect (sigc::mem_fun (*this, &ProcessorBox::reordered));
 	processor_display.DropFromAnotherBox.connect (sigc::mem_fun (*this, &ProcessorBox::object_drop));
+	processor_display.DropFromExternal.connect (sigc::mem_fun (*this, &ProcessorBox::plugin_drop));
 
 	processor_scroller.show ();
 	processor_display.show ();
@@ -1105,16 +1226,16 @@ ProcessorBox::route_going_away ()
 	_route.reset ();
 }
 
-void
-ProcessorBox::object_drop(DnDVBox<ProcessorEntry>* source, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
+boost::shared_ptr<Processor>
+ProcessorBox::find_drop_position (ProcessorEntry* position)
 {
 	boost::shared_ptr<Processor> p;
 	if (position) {
 		p = position->processor ();
 		if (!p) {
 			/* dropped on the blank entry (which will be before the
-			   fader), so use the first non-blank child as our
-			   `dropped on' processor */
+				 fader), so use the first non-blank child as our
+				 `dropped on' processor */
 			list<ProcessorEntry*> c = processor_display.children ();
 			list<ProcessorEntry*>::iterator i = c.begin ();
 
@@ -1123,6 +1244,97 @@ ProcessorBox::object_drop(DnDVBox<ProcessorEntry>* source, ProcessorEntry* posit
 			assert (p);
 		}
 	}
+	return p;
+}
+
+void
+ProcessorBox::_drop_plugin_preset (Gtk::SelectionData const &data, Route::ProcessorList &pl)
+{
+		const void * d = data.get_data();
+		const Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr>* tv = reinterpret_cast<const Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr>*>(d);
+
+		PluginPresetList nfos;
+		TreeView* source;
+		tv->get_object_drag_data (nfos, &source);
+
+		for (list<PluginPresetPtr>::const_iterator i = nfos.begin(); i != nfos.end(); ++i) {
+			PluginPresetPtr ppp = (*i);
+			PluginInfoPtr pip = ppp->_pip;
+			PluginPtr p = pip->load (*_session);
+			if (!p) {
+				continue;
+			}
+
+			if (ppp->_preset.valid) {
+				p->load_preset (ppp->_preset);
+			}
+
+			boost::shared_ptr<Processor> processor (new PluginInsert (*_session, p));
+			if (Config->get_new_plugins_active ()) {
+				processor->activate ();
+			}
+			pl.push_back (processor);
+		}
+}
+
+void
+ProcessorBox::_drop_plugin (Gtk::SelectionData const &data, Route::ProcessorList &pl)
+{
+		const void * d = data.get_data();
+		const Gtkmm2ext::DnDTreeView<ARDOUR::PluginInfoPtr>* tv = reinterpret_cast<const Gtkmm2ext::DnDTreeView<ARDOUR::PluginInfoPtr>*>(d);
+		PluginInfoList nfos;
+
+		TreeView* source;
+		tv->get_object_drag_data (nfos, &source);
+
+		for (list<PluginInfoPtr>::const_iterator i = nfos.begin(); i != nfos.end(); ++i) {
+			PluginPtr p = (*i)->load (*_session);
+			if (!p) {
+				continue;
+			}
+			boost::shared_ptr<Processor> processor (new PluginInsert (*_session, p));
+			if (Config->get_new_plugins_active ()) {
+				processor->activate ();
+			}
+			pl.push_back (processor);
+		}
+}
+
+void
+ProcessorBox::plugin_drop (Gtk::SelectionData const &data, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
+{
+	if (!_session) {
+		return;
+	}
+
+	boost::shared_ptr<Processor> p = find_drop_position (position);
+	Route::ProcessorList pl;
+
+	if (data.get_target() == "PluginInfoPtr") {
+		_drop_plugin (data, pl);
+	}
+	else if (data.get_target() == "PluginPresetPtr") {
+		_drop_plugin_preset (data, pl);
+	}
+	else {
+		return;
+	}
+
+	Route::ProcessorStreams err;
+	if (_route->add_processors (pl, p, &err)) {
+		string msg = _(
+				"Processor Drag/Drop failed. Probably because\n\
+the I/O configuration of the plugins could\n\
+not match the configuration of this track.");
+		MessageDialog am (msg);
+		am.run ();
+	}
+}
+
+void
+ProcessorBox::object_drop (DnDVBox<ProcessorEntry>* source, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context)
+{
+	boost::shared_ptr<Processor> p = find_drop_position (position);
 
 	list<ProcessorEntry*> children = source->selection ();
 	list<boost::shared_ptr<Processor> > procs;
@@ -1182,6 +1394,10 @@ ProcessorBox::build_possible_aux_menu ()
 		return 0;
 	}
 
+	if (_route->is_monitor ()) {
+		return 0;
+	}
+
 	using namespace Menu_Helpers;
 	Menu* menu = manage (new Menu);
 	MenuList& items = menu->items();
@@ -1227,6 +1443,9 @@ ProcessorBox::show_processor_menu (int arg)
 		}
 	}
 
+	ActionManager::get_action (X_("ProcessorMenu"), "newinsert")->set_sensitive (!_route->is_monitor ());
+	ActionManager::get_action (X_("ProcessorMenu"), "newsend")->set_sensitive (!_route->is_monitor ());
+
 	ProcessorEntry* single_selection = 0;
 	if (processor_display.selection().size() == 1) {
 		single_selection = processor_display.selection().front();
@@ -1253,7 +1472,7 @@ ProcessorBox::show_processor_menu (int arg)
 
 	Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
 	if (send_menu_item) {
-		if (single_selection) {
+		if (single_selection && !_route->is_monitor()) {
 			Menu* m = single_selection->build_send_options_menu ();
 			if (m && !m->items().empty()) {
 				send_menu_item->set_submenu (*m);
@@ -1530,10 +1749,13 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
 			weird_plugin_dialog (**p, err_streams);
 			return true;
 			// XXX SHAREDPTR delete plugin here .. do we even need to care?
-		} else {
-
-			if (Profile->get_sae()) {
-				processor->activate ();
+		} else if (plugins.size() == 1 && Config->get_open_gui_after_adding_plugin()) {
+			if (_session->engine().connected () && processor_can_be_edited (processor)) {
+				if ((*p)->has_editor ()) {
+					edit_processor (processor);
+				} else {
+					generic_edit_processor (processor);
+				}
 			}
 		}
 	}
@@ -1868,7 +2090,16 @@ ProcessorBox::add_processor_to_display (boost::weak_ptr<Processor> p)
 		e->show_all_controls ();
 	}
 
-	processor_display.add_child (e);
+	if (plugin_insert
+#ifdef MIXBUS
+			&& !plugin_insert->plugin(0)->is_channelstrip()
+#endif
+		 )
+	{
+		processor_display.add_child (e, drag_targets());
+	} else {
+		processor_display.add_child (e, drag_targets_noplugin());
+	}
 }
 
 void
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index 18ec38a..d904e13 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -119,6 +119,8 @@ public:
 	bool is_selectable() const {return _selectable;}
 	void set_selectable(bool s) { _selectable = s; }
 
+	bool drag_data_get (Glib::RefPtr<Gdk::DragContext> const, Gtk::SelectionData &);
+
 	enum Position {
 		PreFader,
 		Fader,
@@ -152,7 +154,7 @@ protected:
 private:
 	bool _selectable;
 	bool _unknown_processor;
-	void led_clicked();
+	void led_clicked(GdkEventButton *);
 	void processor_active_changed ();
 	void processor_property_changed (const PBD::PropertyChange&);
 	void processor_configuration_changed (const ARDOUR::ChanCount in, const ARDOUR::ChanCount out);
@@ -165,6 +167,7 @@ private:
 	PBD::ScopedConnection active_connection;
 	PBD::ScopedConnection name_connection;
 	PBD::ScopedConnection config_connection;
+	ARDOUR::PluginPresetPtr _plugin_preset_pointer;
 
 	class Control : public sigc::trackable {
 	public:
@@ -189,6 +192,7 @@ private:
 	private:
 		void slider_adjusted ();
 		void button_clicked ();
+		void button_clicked_event (GdkEventButton *);
 		void control_changed ();
 		std::string state_id () const;
 		void set_tooltip ();
@@ -290,6 +294,8 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
 	void select_all_inserts ();
 	void select_all_sends ();
 
+	void all_visible_processors_active(bool state);
+
 	void hide_things ();
 
 	bool edit_aux_send(boost::shared_ptr<ARDOUR::Processor>);
@@ -345,6 +351,12 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
 	Gtkmm2ext::DnDVBox<ProcessorEntry> processor_display;
 	Gtk::ScrolledWindow    processor_scroller;
 
+	boost::shared_ptr<ARDOUR::Processor> find_drop_position (ProcessorEntry* position);
+
+	void _drop_plugin_preset (Gtk::SelectionData const &, ARDOUR::Route::ProcessorList &);
+	void _drop_plugin (Gtk::SelectionData const &, ARDOUR::Route::ProcessorList &);
+
+	void plugin_drop (Gtk::SelectionData const &, ProcessorEntry* position, Glib::RefPtr<Gdk::DragContext> const & context);
 	void object_drop (Gtkmm2ext::DnDVBox<ProcessorEntry> *, ProcessorEntry *, Glib::RefPtr<Gdk::DragContext> const &);
 
 	Width _width;
@@ -381,7 +393,6 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
 	void processors_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*);
 	void compute_processor_sort_keys ();
 
-	void all_visible_processors_active(bool state);
 	void ab_plugins ();
 
 	typedef std::vector<boost::shared_ptr<ARDOUR::Processor> > ProcSelection;
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index c2671a6..fc904b2 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -37,11 +37,13 @@
 #include <gtkmm2ext/slider_controller.h>
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/paths_dialog.h>
+#include <gtkmm2ext/window_title.h>
 
 #include "pbd/fpu.h"
 #include "pbd/cpus.h"
 
 #include "ardour/audioengine.h"
+#include "ardour/profile.h"
 #include "ardour/dB.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/control_protocol_manager.h"
@@ -82,18 +84,18 @@ public:
 		Table* t = manage (new Table (4, 3));
 		t->set_spacings (4);
 
-		Label* l = manage (left_aligned_label (_("Use default Click:")));
-		t->attach (*l, 0, 1, 0, 1, FILL);
-		t->attach (_use_default_click_check_button, 1, 2, 0, 1, FILL);
-		_use_default_click_check_button.signal_toggled().connect (
-		    sigc::mem_fun (*this, &ClickOptions::use_default_click_toggled));
-
-		l = manage (left_aligned_label (_("Emphasis on first beat:")));
+		Label* l = manage (left_aligned_label (_("Emphasis on first beat:")));
 		t->attach (*l, 0, 1, 1, 2, FILL);
 		t->attach (_use_emphasis_on_click_check_button, 1, 2, 1, 2, FILL);
 		_use_emphasis_on_click_check_button.signal_toggled().connect (
 		    sigc::mem_fun (*this, &ClickOptions::use_emphasis_on_click_toggled));
 
+		l = manage (left_aligned_label (_("Use default Click:")));
+		t->attach (*l, 0, 1, 0, 1, FILL);
+		t->attach (_use_default_click_check_button, 1, 2, 0, 1, FILL);
+		_use_default_click_check_button.signal_toggled().connect (
+		    sigc::mem_fun (*this, &ClickOptions::use_default_click_toggled));
+
 		l = manage (left_aligned_label (_("Click audio file:")));
 		t->attach (*l, 0, 1, 2, 3, FILL);
 		t->attach (_click_path_entry, 1, 2, 2, 3, FILL);
@@ -330,14 +332,16 @@ static const struct {
 	   Option/Alt = Mod1
 	*/
 	{ "Key|Shift", GDK_SHIFT_MASK },
-	{ "Command", GDK_META_MASK },
+	{ "Command", GDK_MOD2_MASK },
 	{ "Control", GDK_CONTROL_MASK },
 	{ "Option", GDK_MOD1_MASK },
-	{ "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
-	{ "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
+	{ "Command-Shift", GDK_MOD2_MASK|GDK_SHIFT_MASK },
+	{ "Command-Option", GDK_MOD2_MASK|GDK_MOD1_MASK },
+	{ "Command-Option-Control", GDK_MOD2_MASK|GDK_MOD1_MASK|GDK_CONTROL_MASK },
+	{ "Option-Control", GDK_MOD1_MASK|GDK_CONTROL_MASK },
 	{ "Option-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
 	{ "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
-	{ "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
+	{ "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_MOD2_MASK },
 
 #else
 	{ "Key|Shift", GDK_SHIFT_MASK },
@@ -345,9 +349,10 @@ static const struct {
 	{ "Alt", GDK_MOD1_MASK },
 	{ "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
 	{ "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
-	{ "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
 	{ "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
 	{ "Alt-Windows", GDK_MOD1_MASK|GDK_MOD4_MASK },
+	{ "Alt-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
+	{ "Alt-Shift-Windows", GDK_MOD1_MASK|GDK_SHIFT_MASK|GDK_MOD4_MASK },
 	{ "Mod2", GDK_MOD2_MASK },
 	{ "Mod3", GDK_MOD3_MASK },
 	{ "Windows", GDK_MOD4_MASK },
@@ -368,6 +373,7 @@ public:
 		  _insert_note_button_adjustment (3, 1, 5),
 		  _insert_note_button_spin (_insert_note_button_adjustment)
 	{
+		const Glib::ustring restart_msg = _("\nChanges to this setting will only persist after your project has been saved.");
 		/* internationalize and prepare for use with combos */
 
 		vector<string> dumb;
@@ -377,7 +383,8 @@ public:
 
 		set_popdown_strings (_edit_modifier_combo, dumb);
 		_edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_edit_modifier_combo,
+						    (string_compose (_("<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"),  Keyboard::primary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
 				_edit_modifier_combo.set_active_text (S_(modifiers[x].name));
@@ -438,7 +445,8 @@ public:
 
 		set_popdown_strings (_delete_modifier_combo, dumb);
 		_delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_delete_modifier_combo,
+						    (string_compose (_("<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
 				_delete_modifier_combo.set_active_text (S_(modifiers[x].name));
@@ -467,7 +475,8 @@ public:
 
 		set_popdown_strings (_insert_note_modifier_combo, dumb);
 		_insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_insert_note_modifier_combo,
+						    (string_compose (_("<b>Recommended Setting: %1 + button 1 (left mouse button)</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
 				_insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
@@ -503,7 +512,14 @@ public:
 		/* copy modifier */
 		set_popdown_strings (_copy_modifier_combo, dumb);
 		_copy_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::copy_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_copy_modifier_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"),
+#ifdef GTKOSX
+								     Keyboard::secondary_modifier_name (),
+#else
+								     Keyboard::primary_modifier_name (),
+#endif
+								     restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) Keyboard::CopyModifier) {
 				_copy_modifier_combo.set_active_text (S_(modifiers[x].name));
@@ -523,7 +539,14 @@ public:
 		/* constraint modifier */
 		set_popdown_strings (_constraint_modifier_combo, dumb);
 		_constraint_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::constraint_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_constraint_modifier_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"),
+#ifdef GTKOSX
+								     Keyboard::primary_modifier_name (),
+#else
+								     Keyboard::secondary_modifier_name (),
+#endif
+								     restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) ArdourKeyboard::constraint_modifier ()) {
 				_constraint_modifier_combo.set_active_text (S_(modifiers[x].name));
@@ -549,7 +572,8 @@ public:
 		/* trim_contents */
 		set_popdown_strings (_trim_contents_combo, dumb);
 		_trim_contents_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_contents_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_trim_contents_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_contents_modifier ()) {
 				_trim_contents_combo.set_active_text (S_(modifiers[x].name));
@@ -569,7 +593,8 @@ public:
 		/* anchored trim */
 		set_popdown_strings (_trim_anchored_combo, dumb);
 		_trim_anchored_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_anchored_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_trim_anchored_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_anchored_modifier ()) {
 				_trim_anchored_combo.set_active_text (S_(modifiers[x].name));
@@ -612,7 +637,8 @@ public:
 		/* note resize relative */
 		set_popdown_strings (_note_size_relative_combo, dumb);
 		_note_size_relative_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::note_size_relative_modifier_chosen));
-
+		Gtkmm2ext::UI::instance()->set_tip (_note_size_relative_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) ArdourKeyboard::note_size_relative_modifier ()) {
 				_note_size_relative_combo.set_active_text (S_(modifiers[x].name));
@@ -639,7 +665,13 @@ public:
 		/* ignore snap */
 		set_popdown_strings (_snap_modifier_combo, dumb);
 		_snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
-
+#ifdef GTKOSX
+		Glib::ustring mod_str = string_compose (X_("%1-%2"), Keyboard::level4_modifier_name (), Keyboard::tertiary_modifier_name ());
+#else
+		Glib::ustring mod_str = Keyboard::secondary_modifier_name();
+#endif
+		Gtkmm2ext::UI::instance()->set_tip (_snap_modifier_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
 				_snap_modifier_combo.set_active_text (S_(modifiers[x].name));
@@ -659,7 +691,13 @@ public:
 		/* snap delta */
 		set_popdown_strings (_snap_delta_combo, dumb);
 		_snap_delta_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_delta_modifier_chosen));
-
+#ifdef GTKOSX
+		mod_str = Keyboard::level4_modifier_name ();
+#else
+		mod_str = string_compose (X_("%1-%2"), Keyboard::secondary_modifier_name (), Keyboard::level4_modifier_name ());
+#endif
+		Gtkmm2ext::UI::instance()->set_tip (_snap_delta_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) Keyboard::snap_delta_modifier ()) {
 				_snap_delta_combo.set_active_text (S_(modifiers[x].name));
@@ -686,6 +724,8 @@ public:
 		set_popdown_strings (_trim_overlap_combo, dumb);
 		_trim_overlap_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_overlap_modifier_chosen));
 
+		Gtkmm2ext::UI::instance()->set_tip (_trim_overlap_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_overlap_modifier ()) {
 				_trim_overlap_combo.set_active_text (S_(modifiers[x].name));
@@ -712,6 +752,9 @@ public:
 		set_popdown_strings (_fine_adjust_combo, dumb);
 		_fine_adjust_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::fine_adjust_modifier_chosen));
 
+		mod_str = string_compose (X_("%1-%2"), Keyboard::secondary_modifier_name (), Keyboard::tertiary_modifier_name ());
+		Gtkmm2ext::UI::instance()->set_tip (_fine_adjust_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) ArdourKeyboard::fine_adjust_modifier ()) {
 				_fine_adjust_combo.set_active_text (S_(modifiers[x].name));
@@ -732,6 +775,8 @@ public:
 		set_popdown_strings (_push_points_combo, dumb);
 		_push_points_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::push_points_modifier_chosen));
 
+		Gtkmm2ext::UI::instance()->set_tip (_push_points_combo,
+						    (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
 		for (int x = 0; modifiers[x].name; ++x) {
 			if (modifiers[x].modifier == (guint) ArdourKeyboard::push_points_modifier ()) {
 				_push_points_combo.set_active_text (S_(modifiers[x].name));
@@ -1008,7 +1053,7 @@ public:
 
 		_box->pack_start (*h, false, false);
 
-		set_note (_("Adjusting the scale require an application restart to re-layout."));
+		set_note (_("Adjusting the scale requires an application restart to re-layout."));
 
 		_dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
 	}
@@ -1038,6 +1083,68 @@ private:
 	HScale _dpi_slider;
 };
 
+class VstTimeOutSliderOption : public OptionEditorBox
+{
+public:
+	VstTimeOutSliderOption (RCConfiguration* c)
+		: _rc_config (c)
+		, _timeout_adjustment (0, 0, 3000, 50, 50)
+		, _timeout_slider (_timeout_adjustment)
+	{
+		_timeout_slider.set_digits (0);
+		_timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &VstTimeOutSliderOption::timeout_changed));
+
+		_timeout_slider.set_draw_value(false);
+		_timeout_slider.add_mark(   0,  Gtk::POS_TOP, _("\u221e")); // infinity
+		_timeout_slider.add_mark( 300,  Gtk::POS_TOP, _("30 sec"));
+		_timeout_slider.add_mark( 600,  Gtk::POS_TOP, _("1 min"));
+		_timeout_slider.add_mark(1200,  Gtk::POS_TOP, _("2 mins"));
+		_timeout_slider.add_mark(1800,  Gtk::POS_TOP, _("3 mins"));
+		_timeout_slider.add_mark(2400,  Gtk::POS_TOP, _("4 mins"));
+		_timeout_slider.add_mark(3000,  Gtk::POS_TOP, _("5 mins"));
+
+		Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
+			 _("Specify the default timeout for plugin instantiation. Plugins that require more time to load will be blacklisted. A value of 0 disables the timeout."));
+
+		Label* l = manage (left_aligned_label (_("Scan Time Out:")));
+		HBox* h = manage (new HBox);
+		h->set_spacing (4);
+		h->pack_start (*l, false, false);
+		h->pack_start (_timeout_slider, true, true);
+
+		_box->pack_start (*h, false, false);
+	}
+
+	void parameter_changed (string const & p)
+	{
+		if (p == "vst-scan-timeout") {
+			int const x = _rc_config->get_vst_scan_timeout();
+			_timeout_adjustment.set_value (x);
+		}
+	}
+
+	void set_state_from_config ()
+	{
+		parameter_changed ("vst-scan-timeout");
+	}
+
+private:
+
+	void timeout_changed ()
+	{
+		int x = floor(_timeout_adjustment.get_value());
+		_rc_config->set_vst_scan_timeout(x);
+	}
+
+	RCConfiguration* _rc_config;
+	Adjustment _timeout_adjustment;
+	HScale _timeout_slider;
+};
+
+
+
+
+
 class ClipLevelOptions : public OptionEditorBox
 {
 public:
@@ -1250,18 +1357,29 @@ public:
 
 		_box->pack_start (_view, false, false);
 
+		Gtk::HBox* edit_box = manage (new Gtk::HBox);
+		edit_box->set_spacing(3);
+		_box->pack_start (*edit_box, false, false);
+		edit_box->show ();
+		
 		Label* label = manage (new Label);
-		label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
-
-		_box->pack_start (*label, false, false);
+		label->set_text (_("Click to edit the settings for selected protocol ( it must be ENABLED first ):"));
+		edit_box->pack_start (*label, false, false);
 		label->show ();
 
+		edit_button = manage (new Button(_("Show Protocol Settings")));
+		edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
+		edit_box->pack_start (*edit_button, true, true);
+		edit_button->set_sensitive (false);
+		edit_button->show ();
+
 		ControlProtocolManager& m = ControlProtocolManager::instance ();
 		m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
 						boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
 
 		_store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
 		_view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
+		_view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
 	}
 
 	void parameter_changed (std::string const &)
@@ -1304,6 +1422,16 @@ private:
 		}
 	}
 
+	void selection_changed ()
+	{
+		//enable the Edit button when a row is selected for editing
+		TreeModel::Row row = *(_view.get_selection()->get_selected());
+		if (row && row[_model.enabled])
+			edit_button->set_sensitive (true);
+		else
+			edit_button->set_sensitive (false);
+	}
+	
 	void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
 	{
 		TreeModel::Row r = *i;
@@ -1338,12 +1466,8 @@ private:
 		}
 	}
 
-	void edit_clicked (GdkEventButton* ev)
+	void edit_btn_clicked ()
 	{
-		if (ev->type != GDK_2BUTTON_PRESS) {
-			return;
-		}
-
 		std::string name;
 		ControlProtocolInfo* cpi;
 		TreeModel::Row row;
@@ -1364,19 +1488,29 @@ private:
 			static_cast<ArdourWindow*>(box->get_parent())->present();
 			return;
 		}
-		string title = row[_model.name];
+		WindowTitle title (Glib::get_application_name());
+		title += row[_model.name];
+		title += _("Configuration");
 		/* once created, the window is managed by the surface itself (as ->get_parent())
 		 * Surface's tear_down_gui() is called on session close, when de-activating
 		 * or re-initializing a surface.
 		 * tear_down_gui() hides an deletes the Window if it exists.
 		 */
-		ArdourWindow* win = new ArdourWindow (_parent, title);
-		win->set_title ("Control Protocol Options");
+		ArdourWindow* win = new ArdourWindow (_parent, title.get_string());
 		win->add (*box);
 		box->show ();
 		win->present ();
 	}
 
+	void edit_clicked (GdkEventButton* ev)
+	{
+		if (ev->type != GDK_2BUTTON_PRESS) {
+			return;
+		}
+
+		edit_btn_clicked();
+	}
+
         class ControlSurfacesModelColumns : public TreeModelColumnRecord
 	{
 	public:
@@ -1401,6 +1535,7 @@ private:
         Gtk::Window& _parent;
         PBD::ScopedConnection protocol_status_connection;
         uint32_t _ignore_view_change;
+	Gtk::Button* edit_button;
 };
 
 class VideoTimelineOptions : public OptionEditorBox
@@ -1521,239 +1656,6 @@ private:
 	CheckButton _video_advanced_setup_button;
 };
 
-class PluginOptions : public OptionEditorBox
-{
-public:
-	PluginOptions (RCConfiguration* c)
-		: _rc_config (c)
-		, _display_plugin_scan_progress (_("Always Display Plugin Scan Progress"))
-		, _discover_vst_on_start (_("Scan for [new] VST Plugins on Application Start"))
-		, _discover_au_on_start (_("Scan for AudioUnit Plugins on Application Start"))
-		, _verbose_plugin_scan (_("Verbose Plugin Scan"))
-		, _timeout_adjustment (0, 0, 3000, 50, 50)
-		, _timeout_slider (_timeout_adjustment)
-	{
-		Label *l;
-		std::stringstream ss;
-		Table* t = manage (new Table (2, 6));
-		t->set_spacings (4);
-		Button* b;
-		int n = 0;
-
-		ss << "<b>" << _("General") << "</b>";
-		l = manage (left_aligned_label (ss.str()));
-		l->set_use_markup (true);
-		t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
-		t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
-
-		b = manage (new Button (_("Scan for Plugins")));
-		b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
-		t->attach (*b, 0, 2, n, n+1, FILL); ++n;
-
-		t->attach (_display_plugin_scan_progress, 0, 2, n, n+1); ++n;
-		_display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
-		Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
-					    _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
-
-#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
-		_timeout_slider.set_digits (0);
-		_timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PluginOptions::timeout_changed));
-
-		Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
-			 _("Specify the default timeout for plugin instantiation in 1/10 seconds. Plugins that require more time to load will be blacklisted. A value of 0 disables the timeout."));
-
-		l = manage (left_aligned_label (_("Scan Time Out [deciseconds]")));;
-		HBox* h = manage (new HBox);
-		h->set_spacing (4);
-		h->pack_start (*l, false, false);
-		h->pack_start (_timeout_slider, true, true);
-		t->attach (*h, 0, 2, n, n+1); ++n;
-
-		ss.str("");
-		ss << "<b>" << _("VST") << "</b>";
-		l = manage (left_aligned_label (ss.str()));
-		l->set_use_markup (true);
-		t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
-		t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
-
-		b = manage (new Button (_("Clear VST Cache")));
-		b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
-		t->attach (*b, 0, 1, n, n+1, FILL);
-
-		b = manage (new Button (_("Clear VST Blacklist")));
-		b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
-		t->attach (*b, 1, 2, n, n+1, FILL);
-		++n;
-
-		t->attach (_discover_vst_on_start, 0, 2, n, n+1); ++n;
-		_discover_vst_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_vst_on_start_toggled));
-		Gtkmm2ext::UI::instance()->set_tip (_discover_vst_on_start,
-					    _("<b>When enabled</b> new VST plugins are searched, tested and added to the cache index on application start. When disabled new plugins will only be available after triggering a 'Scan' manually"));
-
-#ifdef LXVST_SUPPORT
-		t->attach (*manage (right_aligned_label (_("Linux VST Path:"))), 0, 1, n, n+1);
-		b = manage (new Button (_("Edit")));
-		b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_path_clicked));
-		t->attach (*b, 1, 2, n, n+1, FILL); ++n;
-#endif
-
-#ifdef WINDOWS_VST_SUPPORT
-		t->attach (*manage (right_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
-		b = manage (new Button (_("Edit")));
-		b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
-		t->attach (*b, 1, 2, n, n+1, FILL); ++n;
-
-		// currently verbose logging is only implemented for Windows VST.
-		t->attach (_verbose_plugin_scan, 0, 2, n, n+1); ++n;
-		_verbose_plugin_scan.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::verbose_plugin_scan_toggled));
-		Gtkmm2ext::UI::instance()->set_tip (_verbose_plugin_scan,
-					    _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
-#endif
-#endif // any VST
-
-#ifdef AUDIOUNIT_SUPPORT
-		ss.str("");
-		ss << "<b>" << _("Audio Unit") << "</b>";
-		l = manage (left_aligned_label (ss.str()));
-		l->set_use_markup (true);
-		t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
-		t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
-
-		t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
-		_discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
-		Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
-					    _("<b>When enabled</b> Audio Unit Plugins are discovered on application start. When disabled AU plugins will only be available after triggering a 'Scan' manually. The first successful scan will enable AU auto-scan, Any crash during plugin discovery will disable it."));
-
-		++n;
-		b = manage (new Button (_("Clear AU Cache")));
-		b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_cache_clicked));
-		t->attach (*b, 0, 1, n, n+1, FILL);
-
-		b = manage (new Button (_("Clear AU Blacklist")));
-		b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_blacklist_clicked));
-		t->attach (*b, 1, 2, n, n+1, FILL);
-		++n;
-#endif
-
-		_box->pack_start (*t,true,true);
-	}
-
-	void parameter_changed (string const & p) {
-		if (p == "show-plugin-scan-window") {
-			bool const x = UIConfiguration::instance().get_show_plugin_scan_window();
-			_display_plugin_scan_progress.set_active (x);
-		}
-		else if (p == "discover-vst-on-start") {
-			bool const x = _rc_config->get_discover_vst_on_start();
-			_discover_vst_on_start.set_active (x);
-		}
-		else if (p == "vst-scan-timeout") {
-			int const x = _rc_config->get_vst_scan_timeout();
-			_timeout_adjustment.set_value (x);
-		}
-		else if (p == "discover-audio-units") {
-			bool const x = _rc_config->get_discover_audio_units();
-			_discover_au_on_start.set_active (x);
-		}
-		else if (p == "verbose-plugin-scan") {
-			bool const x = _rc_config->get_verbose_plugin_scan();
-			_verbose_plugin_scan.set_active (x);
-		}
-	}
-
-	void set_state_from_config () {
-		parameter_changed ("show-plugin-scan-window");
-		parameter_changed ("discover-vst-on-start");
-		parameter_changed ("vst-scan-timeout");
-		parameter_changed ("discover-audio-units");
-		parameter_changed ("verbose-plugin-scan");
-	}
-
-private:
-	RCConfiguration* _rc_config;
-	CheckButton _display_plugin_scan_progress;
-	CheckButton _discover_vst_on_start;
-	CheckButton _discover_au_on_start;
-	CheckButton _verbose_plugin_scan;
-	Adjustment _timeout_adjustment;
-	HScale _timeout_slider;
-
-	void display_plugin_scan_progress_toggled () {
-		bool const x = _display_plugin_scan_progress.get_active();
-		UIConfiguration::instance().set_show_plugin_scan_window(x);
-	}
-
-	void discover_vst_on_start_toggled () {
-		bool const x = _discover_vst_on_start.get_active();
-		_rc_config->set_discover_vst_on_start(x);
-	}
-
-	void discover_au_on_start_toggled () {
-		bool const x = _discover_au_on_start.get_active();
-		_rc_config->set_discover_audio_units(x);
-	}
-
-	void verbose_plugin_scan_toggled () {
-		bool const x = _verbose_plugin_scan.get_active();
-		_rc_config->set_verbose_plugin_scan(x);
-	}
-
-	void timeout_changed () {
-		int x = floor(_timeout_adjustment.get_value());
-		_rc_config->set_vst_scan_timeout(x);
-	}
-
-	void clear_vst_cache_clicked () {
-		PluginManager::instance().clear_vst_cache();
-	}
-
-	void clear_vst_blacklist_clicked () {
-		PluginManager::instance().clear_vst_blacklist();
-	}
-
-	void clear_au_cache_clicked () {
-		PluginManager::instance().clear_au_cache();
-	}
-
-	void clear_au_blacklist_clicked () {
-		PluginManager::instance().clear_au_blacklist();
-	}
-
-
-	void edit_vst_path_clicked () {
-		Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
-				_("Set Windows VST Search Path"),
-				_rc_config->get_plugin_path_vst(),
-				PluginManager::instance().get_default_windows_vst_path()
-			);
-		ResponseType r = (ResponseType) pd->run ();
-		pd->hide();
-		if (r == RESPONSE_ACCEPT) {
-			_rc_config->set_plugin_path_vst(pd->get_serialized_paths());
-		}
-		delete pd;
-	}
-
-	// todo consolidate with edit_vst_path_clicked..
-	void edit_lxvst_path_clicked () {
-		Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
-				_("Set Linux VST Search Path"),
-				_rc_config->get_plugin_path_lxvst(),
-				PluginManager::instance().get_default_lxvst_path()
-				);
-		ResponseType r = (ResponseType) pd->run ();
-		pd->hide();
-		if (r == RESPONSE_ACCEPT) {
-			_rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
-		}
-		delete pd;
-	}
-
-	void refresh_clicked () {
-		PluginManager::instance().refresh();
-	}
-};
-
 
 /** A class which allows control of visibility of some editor components usign
  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
@@ -1862,6 +1764,8 @@ RCOptionEditor::RCOptionEditor ()
 		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
 		     ));
 
+	add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
+
 	add_option (_("Misc"),
 	     new BoolOption (
 		     "periodic-safety-backups",
@@ -1870,8 +1774,6 @@ RCOptionEditor::RCOptionEditor ()
 		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
 		     ));
 
-	add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
-
 	add_option (_("Misc"),
 	     new BoolOption (
 		     "only-copy-imported-files",
@@ -2019,6 +1921,23 @@ RCOptionEditor::RCOptionEditor ()
 						   "that occurs when fast-forwarding or rewinding through some kinds of audio"));
 	add_option (_("Transport"), tsf);
 
+	ComboOption<float>* psc = new ComboOption<float> (
+		     "preroll-seconds",
+		     _("Preroll"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_preroll_seconds),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_preroll_seconds)
+		     );
+	Gtkmm2ext::UI::instance()->set_tip (psc->tip_widget(),
+					    (_("The amount of preroll (in seconds) to apply when <b>Play with Preroll</b> is initiated.\n\n"
+					       "If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead position when a region is selected or trimmed.")));
+	psc->add (0.0, _("0 (no pre-roll)"));
+	psc->add (0.1, _("0.1 second"));
+	psc->add (0.25, _("0.25 second"));
+	psc->add (0.5, _("0.5 second"));
+	psc->add (1.0, _("1.0 second"));
+	psc->add (2.0, _("2.0 seconds"));
+	add_option (_("Transport"), psc);
+	
 	add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
 
 	_sync_source = new ComboOption<SyncSource> (
@@ -2100,6 +2019,7 @@ RCOptionEditor::RCOptionEditor ()
 	_ltc_port->set_popdown_strings (physical_inputs);
 
 	populate_sync_options ();
+	AudioEngine::instance()->Running.connect (engine_started_connection, MISSING_INVALIDATOR, boost::bind (&RCOptionEditor::populate_sync_options, this), gui_context());
 
 	add_option (_("Transport"), _ltc_port);
 
@@ -2135,12 +2055,27 @@ RCOptionEditor::RCOptionEditor ()
 		 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
 
 	add_option (_("Transport"), _ltc_volume_slider);
-	parameter_changed ("send-ltc");
-
-	parameter_changed ("sync-source");
 
 	/* EDITOR */
 
+	add_option (_("Editor"),
+	     new BoolOption (
+		     "rubberbanding-snaps-to-grid",
+		     _("Make rubberband selection rectangle snap to the grid"),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
+		     ));
+
+	bo = new BoolOption (
+		     "name-new-markers",
+		     _("Name new markers"),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
+		);
+	add_option (_("Editor"), bo);
+	Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("If enabled, popup a dialog when a new marker is created to allow its name to be set as it is created."
+								"\n\nYou can always rename markers by right-clicking on them"));
+
 	add_option (S_("Editor"),
 	     new BoolOption (
 		     "draggable-playhead",
@@ -2151,14 +2086,6 @@ RCOptionEditor::RCOptionEditor ()
 
 	add_option (_("Editor"),
 	     new BoolOption (
-		     "automation-follows-regions",
-		     _("Move relevant automation when audio regions are moved"),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
-		     ));
-
-	add_option (_("Editor"),
-	     new BoolOption (
 		     "show-track-meters",
 		     _("Show meters on tracks in the editor"),
 		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
@@ -2173,30 +2100,76 @@ RCOptionEditor::RCOptionEditor ()
 		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
 		     ));
 
-	ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
-			"default-fade-shape",
-			_("Default fade shape"),
-			sigc::mem_fun (*_rc_config,
-				&RCConfiguration::get_default_fade_shape),
-			sigc::mem_fun (*_rc_config,
-				&RCConfiguration::set_default_fade_shape)
-			);
-
-	fadeshape->add (FadeLinear,
-			_("Linear (for highly correlated material)"));
-	fadeshape->add (FadeConstantPower, _("Constant power"));
-	fadeshape->add (FadeSymmetric, _("Symmetric"));
-	fadeshape->add (FadeSlow, _("Slow"));
-	fadeshape->add (FadeFast, _("Fast"));
+if (!Profile->get_mixbus()) {
+	add_option (_("Editor"),
+		    new BoolOption (
+			    "show-zoom-tools",
+			    _("Show zoom toolbar (if torn off)"),
+			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_zoom_tools),
+			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_zoom_tools)
+			    ));
+}  // !mixbus
 
-	add_option (_("Editor"), fadeshape);
+	add_option (_("Editor"),
+		    new BoolOption (
+			    "update-editor-during-summary-drag",
+			    _("Update editor window during drags of the summary"),
+			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
+			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
+			    ));
 
+	add_option (_("Editor"),
+	    new BoolOption (
+		    "autoscroll-editor",
+		    _("Auto-scroll editor window when dragging near its edges"),
+		    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
+		    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
+		    ));
 
-	bco = new BoolComboOption (
-		     "use-overlap-equivalency",
-		     _("Regions in active edit groups are edited together"),
-		     _("whenever they overlap in time"),
-		     _("only if they have identical length, position and origin"),
+	add_option (_("Editor"),
+	     new BoolComboOption (
+		     "show-region-gain-envelopes",
+		     _("Show gain envelopes in audio regions"),
+		     _("in all modes"),
+		     _("only in Draw and Internal Edit modes"),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
+		     ));
+
+	add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
+
+	add_option (_("Editor"),
+	     new BoolOption (
+		     "automation-follows-regions",
+		     _("Move relevant automation when audio regions are moved"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
+		     ));
+
+	ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
+			"default-fade-shape",
+			_("Default fade shape"),
+			sigc::mem_fun (*_rc_config,
+				&RCConfiguration::get_default_fade_shape),
+			sigc::mem_fun (*_rc_config,
+				&RCConfiguration::set_default_fade_shape)
+			);
+
+	fadeshape->add (FadeLinear,
+			_("Linear (for highly correlated material)"));
+	fadeshape->add (FadeConstantPower, _("Constant power"));
+	fadeshape->add (FadeSymmetric, _("Symmetric"));
+	fadeshape->add (FadeSlow, _("Slow"));
+	fadeshape->add (FadeFast, _("Fast"));
+
+	add_option (_("Editor"), fadeshape);
+
+
+	bco = new BoolComboOption (
+		     "use-overlap-equivalency",
+		     _("Regions in active edit groups are edited together"),
+		     _("whenever they overlap in time"),
+		     _("only if they have identical length, position and origin"),
 		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
 		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
 		     );
@@ -2214,14 +2187,27 @@ RCOptionEditor::RCOptionEditor ()
 	lm->add (Manual, _("manual layering"));
 	add_option (_("Editor"), lm);
 
-	add_option (_("Editor"),
-	     new BoolOption (
-		     "rubberbanding-snaps-to-grid",
-		     _("Make rubberband selection rectangle snap to the grid"),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
-		     ));
+	ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
+		    "region-selection-after-split",
+		    _("After splitting selected regions, select"),
+		    sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
+		    sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
 
+	// TODO: decide which of these modes are really useful
+	rsas->add(None, _("no regions"));
+	// rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
+	// rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
+	rsas->add(NewlyCreatedBoth, _("newly-created regions"));
+	// rsas->add(Existing, _("unmodified regions in the existing selection"));
+	// rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
+	// rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
+	rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
+
+	add_option (_("Editor"), rsas);
+	
+	add_option (_("Editor"), new OptionEditorHeading (_("Waveforms")));
+
+if (!Profile->get_mixbus()) {
 	add_option (_("Editor"),
 	     new BoolOption (
 		     "show-waveforms",
@@ -2229,15 +2215,14 @@ RCOptionEditor::RCOptionEditor ()
 		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
 		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
 		     ));
+}  // !mixbus
 
 	add_option (_("Editor"),
-	     new BoolComboOption (
-		     "show-region-gain-envelopes",
-		     _("Show gain envelopes in audio regions"),
-		     _("in all modes"),
-		     _("only in Draw and Internal Edit modes"),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
+	     new BoolOption (
+		     "show-waveforms-while-recording",
+		     _("Show waveforms for audio while it is being recorded"),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
 		     ));
 
 	ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
@@ -2266,67 +2251,6 @@ RCOptionEditor::RCOptionEditor ()
 
 	add_option (_("Editor"), new ClipLevelOptions ());
 
-	add_option (_("Editor"),
-	     new BoolOption (
-		     "show-waveforms-while-recording",
-		     _("Show waveforms for audio while it is being recorded"),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
-		     ));
-
-	add_option (_("Editor"),
-		    new BoolOption (
-			    "show-zoom-tools",
-			    _("Show zoom toolbar"),
-			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_zoom_tools),
-			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_zoom_tools)
-			    ));
-
-	add_option (_("Editor"),
-		    new BoolOption (
-			    "update-editor-during-summary-drag",
-			    _("Update editor window during drags of the summary"),
-			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
-			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
-			    ));
-
-	bo = new BoolOption (
-		     "name-new-markers",
-		     _("Name new markers"),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
-		);
-
-	add_option (_("Editor"), bo);
-	Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("If enabled, popup a dialog when a new marker is created to allow its name to be set as it is created."
-								"\n\nYou can always rename markers by right-clicking on them"));
-
-	add_option (_("Editor"),
-	    new BoolOption (
-		    "autoscroll-editor",
-		    _("Auto-scroll editor window when dragging near its edges"),
-		    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
-		    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
-		    ));
-
-	ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
-		    "region-selection-after-split",
-		    _("After splitting selected regions, select"),
-		    sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
-		    sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
-
-	// TODO: decide which of these modes are really useful
-	rsas->add(None, _("no regions"));
-	// rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
-	// rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
-	rsas->add(NewlyCreatedBoth, _("newly-created regions"));
-	// rsas->add(Existing, _("unmodified regions in the existing selection"));
-	// rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
-	// rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
-	rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
-
-	add_option (_("Editor"), rsas);
-
 
 	/* AUDIO */
 
@@ -2362,6 +2286,7 @@ RCOptionEditor::RCOptionEditor ()
 		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
 		     ));
 
+if (!Profile->get_mixbus()) {
 	add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
 
 	add_option (_("Audio"),
@@ -2396,6 +2321,7 @@ RCOptionEditor::RCOptionEditor ()
 	oac->add (ManualConnect, _("manually"));
 
 	add_option (_("Audio"), oac);
+}  // !mixbus
 
 	add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
 
@@ -2486,14 +2412,6 @@ RCOptionEditor::RCOptionEditor ()
 
 	add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
 
-	add_option (_("Solo / mute"),
-	     new FaderOption (
-		     "solo-mute-gain",
-		     _("Solo-in-place mute cut (dB)"),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
-		     ));
-
 	_solo_control_is_listen_control = new BoolOption (
 		"solo-control-is-listen-control",
 		_("Solo controls are Listen controls"),
@@ -2503,6 +2421,38 @@ RCOptionEditor::RCOptionEditor ()
 
 	add_option (_("Solo / mute"), _solo_control_is_listen_control);
 
+	add_option (_("Solo / mute"),
+	     new BoolOption (
+		     "exclusive-solo",
+		     _("Exclusive solo"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
+		     ));
+
+	add_option (_("Solo / mute"),
+	     new BoolOption (
+		     "show-solo-mutes",
+		     _("Show solo muting"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
+		     ));
+
+	add_option (_("Solo / mute"),
+	     new BoolOption (
+		     "solo-mute-override",
+		     _("Soloing overrides muting"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
+		     ));
+
+	add_option (_("Solo / mute"),
+	     new FaderOption (
+		     "solo-mute-gain",
+		     _("Solo-in-place mute cut (dB)"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
+		     ));
+
 	_listen_position = new ComboOption<ListenPosition> (
 		"listen-position",
 		_("Listen Position"),
@@ -2539,32 +2489,6 @@ RCOptionEditor::RCOptionEditor ()
 
 	add_option (_("Solo / mute"), pa);
 
-	parameter_changed ("use-monitor-bus");
-
-	add_option (_("Solo / mute"),
-	     new BoolOption (
-		     "exclusive-solo",
-		     _("Exclusive solo"),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
-		     ));
-
-	add_option (_("Solo / mute"),
-	     new BoolOption (
-		     "show-solo-mutes",
-		     _("Show solo muting"),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
-		     ));
-
-	add_option (_("Solo / mute"),
-	     new BoolOption (
-		     "solo-mute-override",
-		     _("Soloing overrides muting"),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
-		     ));
-
 	add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
 
 	add_option (_("Solo / mute"),
@@ -2609,6 +2533,8 @@ RCOptionEditor::RCOptionEditor ()
 		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
 		     ));
 
+	add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Preferences")));
+
 	add_option (_("MIDI"),
 		    new SpinOption<float> (
 			    "midi-readahead",
@@ -2620,6 +2546,49 @@ RCOptionEditor::RCOptionEditor ()
 			    ));
 
 	add_option (_("MIDI"),
+	     new SpinOption<int32_t> (
+		     "initial-program-change",
+		     _("Initial program change"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
+		     -1, 65536, 1, 10
+		     ));
+
+	add_option (_("MIDI"),
+		    new BoolOption (
+			    "display-first-midi-bank-as-zero",
+			    _("Display first MIDI bank/program as 0"),
+			    sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
+			    sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
+			    ));
+
+	add_option (_("MIDI"),
+	     new BoolOption (
+		     "never-display-periodic-midi",
+		     _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
+		     ));
+
+	add_option (_("MIDI"),
+	     new BoolOption (
+		     "sound-midi-notes",
+		     _("Sound MIDI notes as they are selected in the editor"),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
+		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
+		     ));
+
+	add_option (_("MIDI"),
+		    new BoolOption (
+			    "midi-feedback",
+			    _("Send MIDI control feedback"),
+			    sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
+			    sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
+			    ));
+
+	add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Clock")));
+
+	add_option (_("MIDI"),
 		    new BoolOption (
 			    "send-midi-clock",
 			    _("Send MIDI Clock"),
@@ -2627,6 +2596,8 @@ RCOptionEditor::RCOptionEditor ()
 			    sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
 			    ));
 
+	add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Time Code (MTC)")));
+
 	add_option (_("MIDI"),
 		    new BoolOption (
 			    "send-mtc",
@@ -2644,6 +2615,8 @@ RCOptionEditor::RCOptionEditor ()
 			    0, 20, 1, 5
 			    ));
 
+	add_option (_("MIDI"), new OptionEditorHeading (_("Midi Machine Control (MMC)")));
+
 	add_option (_("MIDI"),
 		    new BoolOption (
 			    "mmc-control",
@@ -2661,14 +2634,6 @@ RCOptionEditor::RCOptionEditor ()
 			    ));
 
 	add_option (_("MIDI"),
-		    new BoolOption (
-			    "midi-feedback",
-			    _("Send MIDI control feedback"),
-			    sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
-			    sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
-			    ));
-
-	add_option (_("MIDI"),
 	     new SpinOption<uint8_t> (
 		     "mmc-receive-device-id",
 		     _("Inbound MMC device ID"),
@@ -2686,39 +2651,6 @@ RCOptionEditor::RCOptionEditor ()
 		     0, 128, 1, 10
 		     ));
 
-	add_option (_("MIDI"),
-	     new SpinOption<int32_t> (
-		     "initial-program-change",
-		     _("Initial program change"),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
-		     -1, 65536, 1, 10
-		     ));
-
-	add_option (_("MIDI"),
-		    new BoolOption (
-			    "display-first-midi-bank-as-zero",
-			    _("Display first MIDI bank/program as 0"),
-			    sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
-			    sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
-			    ));
-
-	add_option (_("MIDI"),
-	     new BoolOption (
-		     "never-display-periodic-midi",
-		     _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
-		     ));
-
-	add_option (_("MIDI"),
-	     new BoolOption (
-		     "sound-midi-notes",
-		     _("Sound MIDI notes as they are selected"),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
-		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
-		     ));
-
 	add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
 
 	ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
@@ -2788,8 +2720,123 @@ RCOptionEditor::RCOptionEditor ()
 	add_option (_("Video"), new VideoTimelineOptions (_rc_config));
 
 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
-	/* Plugin options (currrently VST only) */
-	add_option (_("Plugins"), new PluginOptions (_rc_config));
+	add_option (_("Plugins"), new OptionEditorHeading (_("General")));
+
+	add_option (_("Plugins"),
+			new RcActionButton (_("Scan for Plugins"),
+				sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
+
+	bo = new BoolOption (
+			"show-plugin-scan-window",
+			_("Always Display Plugin Scan Progress"),
+			sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_plugin_scan_window),
+			sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_plugin_scan_window)
+			);
+	add_option (_("Plugins"), bo);
+	Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
+			_("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
+
+#endif
+
+#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
+	add_option (_("Plugins"), new OptionEditorHeading (_("VST")));
+
+	bo = new BoolOption (
+			"discover-vst-on-start",
+			_("Scan for [new] VST Plugins on Application Start"),
+			sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_vst_on_start),
+			sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_vst_on_start)
+			);
+	add_option (_("Plugins"), bo);
+	Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
+					    _("<b>When enabled</b> new VST plugins are searched, tested and added to the cache index on application start. When disabled new plugins will only be available after triggering a 'Scan' manually"));
+
+#ifdef WINDOWS_VST_SUPPORT
+	// currently verbose logging is only implemented for Windows VST.
+	bo = new BoolOption (
+			"verbose-plugin-scan",
+			_("Verbose Plugin Scan"),
+			sigc::mem_fun (*_rc_config, &RCConfiguration::get_verbose_plugin_scan),
+			sigc::mem_fun (*_rc_config, &RCConfiguration::set_verbose_plugin_scan)
+			);
+	add_option (_("Plugins"), bo);
+	Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
+					    _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
+#endif
+
+	add_option (_("Plugins"), new VstTimeOutSliderOption (_rc_config));
+
+	add_option (_("Plugins"),
+			new RcActionButton (_("Clear"),
+				sigc::mem_fun (*this, &RCOptionEditor::clear_vst_cache),
+				_("VST Cache:")));
+
+	add_option (_("Plugins"),
+			new RcActionButton (_("Clear"),
+				sigc::mem_fun (*this, &RCOptionEditor::clear_vst_blacklist),
+				_("VST Blacklist:")));
+#endif
+
+#ifdef LXVST_SUPPORT
+	add_option (_("Plugins"),
+			new RcActionButton (_("Edit"),
+				sigc::mem_fun (*this, &RCOptionEditor::edit_lxvst_path),
+			_("Linux VST Path:")));
+
+	add_option (_("Plugins"),
+			new RcConfigDisplay (
+				"plugin-path-lxvst",
+				_("Path:"),
+				sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_lxvst),
+				':'));
+#endif
+
+#ifdef WINDOWS_VST_SUPPORT
+	add_option (_("Plugins"),
+			new RcActionButton (_("Edit"),
+				sigc::mem_fun (*this, &RCOptionEditor::edit_vst_path),
+			_("Windows VST Path:")));
+	add_option (_("Plugins"),
+			new RcConfigDisplay (
+				"plugin-path-vst",
+				_("Path:"),
+				sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_vst),
+				';'));
+#endif
+
+#ifdef AUDIOUNIT_SUPPORT
+	add_option (_("Plugins"), new OptionEditorHeading (_("Audio Unit")));
+
+	bo = new BoolOption (
+			"discover-audio-units",
+			_("Scan for AudioUnit Plugins on Application Start"),
+			sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units),
+			sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units)
+			);
+	add_option (_("Plugins"), bo);
+	Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
+					    _("<b>When enabled</b> Audio Unit Plugins are discovered on application start. When disabled AU plugins will only be available after triggering a 'Scan' manually. The first successful scan will enable AU auto-scan, Any crash during plugin discovery will disable it."));
+
+	add_option (_("Plugins"),
+			new RcActionButton (_("Clear"),
+				sigc::mem_fun (*this, &RCOptionEditor::clear_au_cache),
+				_("AU Cache:")));
+
+	add_option (_("Plugins"),
+			new RcActionButton (_("Clear"),
+				sigc::mem_fun (*this, &RCOptionEditor::clear_au_blacklist),
+				_("AU Blacklist:")));
+#endif
+
+#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2)
+	add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI")));
+	add_option (_("Plugins"),
+	     new BoolOption (
+		     "open-gui-after-adding-plugin",
+		     _("Automatically open the plugin GUI when adding a new plugin"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_open_gui_after_adding_plugin),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_open_gui_after_adding_plugin)
+		     ));
 #endif
 
 	/* INTERFACE */
@@ -2845,20 +2892,20 @@ RCOptionEditor::RCOptionEditor ()
 		     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
 		     ));
 
-#ifndef GTKOSX
-	/* font scaling does nothing with GDK/Quartz */
-	add_option (S_("Preferences|GUI"), new FontScalingOptions ());
-#endif
-
 	add_option (S_("GUI"),
 		    new BoolOption (
 			    "super-rapid-clock-update",
-			    _("update transport clock display at FPS instead of every 100ms"),
+			    _("Update transport clock display at FPS instead of every 100ms"),
 			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
 			    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
 			    ));
 
 
+#ifndef GTKOSX
+	/* font scaling does nothing with GDK/Quartz */
+	add_option (S_("Preferences|GUI"), new FontScalingOptions ());
+#endif
+
 	/* Image cache size */
 
 	Gtk::Adjustment *ics = manage (new Gtk::Adjustment(0, 1, 1024, 10)); /* 1 MB to 1GB in steps of 10MB */
@@ -2874,6 +2921,7 @@ RCOptionEditor::RCOptionEditor ()
 		 _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
 	add_option (S_("Preferences|GUI"), sics);
 
+if (!ARDOUR::Profile->get_mixbus()) {
 	/* Lock GUI timeout */
 
 	Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
@@ -2888,6 +2936,7 @@ RCOptionEditor::RCOptionEditor ()
 		(slts->tip_widget(),
 		 _("Lock GUI after this many idle seconds (zero to never lock)"));
 	add_option (S_("Preferences|GUI"), slts);
+} // !mixbus
 
 	/* The names of these controls must be the same as those given in MixerStrip
 	   for the actual widgets being controlled.
@@ -3070,6 +3119,11 @@ RCOptionEditor::RCOptionEditor ()
 
 	ThemeManager* tm = manage (new ThemeManager);
 	add_page (_("Theme"), *tm);
+
+	//trigger some parameter-changed messages which affect widget-visibility or -sensitivity
+	parameter_changed ("send-ltc");
+	parameter_changed ("sync-source");
+	parameter_changed ("use-monitor-bus");
 }
 
 void
@@ -3114,6 +3168,56 @@ void RCOptionEditor::ltc_generator_volume_changed () {
 	_rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
 }
 
+void RCOptionEditor::plugin_scan_refresh () {
+	PluginManager::instance().refresh();
+}
+
+void RCOptionEditor::clear_vst_cache () {
+	PluginManager::instance().clear_vst_cache();
+}
+
+void RCOptionEditor::clear_vst_blacklist () {
+	PluginManager::instance().clear_vst_blacklist();
+}
+
+void RCOptionEditor::clear_au_cache () {
+	PluginManager::instance().clear_au_cache();
+}
+
+void RCOptionEditor::clear_au_blacklist () {
+	PluginManager::instance().clear_au_blacklist();
+}
+
+void RCOptionEditor::edit_lxvst_path () {
+	Glib::RefPtr<Gdk::Window> win = get_parent_window ();
+	Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
+			*this, _("Set Linux VST Search Path"),
+			_rc_config->get_plugin_path_lxvst(),
+			PluginManager::instance().get_default_lxvst_path()
+			);
+	ResponseType r = (ResponseType) pd->run ();
+	pd->hide();
+	if (r == RESPONSE_ACCEPT) {
+		_rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
+	}
+	delete pd;
+}
+
+void RCOptionEditor::edit_vst_path () {
+	Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
+			*this, _("Set Windows VST Search Path"),
+			_rc_config->get_plugin_path_vst(),
+			PluginManager::instance().get_default_windows_vst_path()
+			);
+	ResponseType r = (ResponseType) pd->run ();
+	pd->hide();
+	if (r == RESPONSE_ACCEPT) {
+		_rc_config->set_plugin_path_vst(pd->get_serialized_paths());
+	}
+	delete pd;
+}
+
+
 void
 RCOptionEditor::populate_sync_options ()
 {
@@ -3132,4 +3236,6 @@ RCOptionEditor::populate_sync_options ()
 			_rc_config->set_sync_source(sync_opts.front());
 		}
 	}
+
+	parameter_changed ("sync-source");
 }
diff --git a/gtk2_ardour/rc_option_editor.h b/gtk2_ardour/rc_option_editor.h
index 879a9c4..1b543e3 100644
--- a/gtk2_ardour/rc_option_editor.h
+++ b/gtk2_ardour/rc_option_editor.h
@@ -55,7 +55,17 @@ private:
 	Gtk::Adjustment* _ltc_volume_adjustment;
 	BoolOption* _ltc_send_continuously;
 
-        PBD::ScopedConnection parameter_change_connection;
+	PBD::ScopedConnection parameter_change_connection;
+	PBD::ScopedConnection engine_started_connection;
+
+	/* plugin actions */
+	void plugin_scan_refresh ();
+	void clear_vst_cache ();
+	void clear_vst_blacklist ();
+	void clear_au_cache ();
+	void clear_au_blacklist ();
+	void edit_lxvst_path ();
+	void edit_vst_path ();
 };
 
 #endif /* __gtk_ardour_rc_option_editor_h__ */
diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc
index 7a748c8..dc1c14e 100644
--- a/gtk2_ardour/region_gain_line.cc
+++ b/gtk2_ardour/region_gain_line.cc
@@ -81,6 +81,7 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
 		trackview.session()->add_command(new StatefulDiffCommand (rv.audio_region()));
 	}
 
+	trackview.editor ().get_selection ().clear_points ();
 	alist->erase (cp.model());
 
 	trackview.editor().session()->add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc
index 7ddca8b..3312fc3 100644
--- a/gtk2_ardour/region_view.cc
+++ b/gtk2_ardour/region_view.cc
@@ -84,7 +84,6 @@ RegionView::RegionView (ArdourCanvas::Container*          parent,
 	, wait_for_data(false)
 	, _silence_text (0)
 {
-	GhostRegion::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RegionView::remove_ghost, this, _1), gui_context());
 }
 
 RegionView::RegionView (const RegionView& other)
@@ -98,8 +97,6 @@ RegionView::RegionView (const RegionView& other)
 	current_visible_sync_position = other.current_visible_sync_position;
 	valid = false;
 	_pixel_width = other._pixel_width;
-
-	GhostRegion::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RegionView::remove_ghost, this, _1), gui_context());
 }
 
 RegionView::RegionView (const RegionView& other, boost::shared_ptr<Region> other_region)
@@ -117,8 +114,6 @@ RegionView::RegionView (const RegionView& other, boost::shared_ptr<Region> other
 	current_visible_sync_position = other.current_visible_sync_position;
 	valid = false;
 	_pixel_width = other._pixel_width;
-
-	GhostRegion::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RegionView::remove_ghost, this, _1), gui_context());
 }
 
 RegionView::RegionView (ArdourCanvas::Container*          parent,
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index 41d7905..33baf3a 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -738,12 +738,12 @@ RouteTimeAxisView::build_display_menu ()
                                         break;
                                 }
 
-                                alignment_items.push_back (RadioMenuElem (align_group, _("Align With Existing Material")));
+                                alignment_items.push_back (RadioMenuElem (align_group, _("Align with Existing Material")));
                                 i = dynamic_cast<RadioMenuItem*> (&alignment_items.back());
                                 i->set_active (existing != 0 && capture == 0 && automatic == 0);
                                 i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, UseExistingMaterial, true));
 
-                                alignment_items.push_back (RadioMenuElem (align_group, _("Align With Capture Time")));
+                                alignment_items.push_back (RadioMenuElem (align_group, _("Align with Capture Time")));
                                 i = dynamic_cast<RadioMenuItem*> (&alignment_items.back());
                                 i->set_active (existing == 0 && capture != 0 && automatic == 0);
                                 i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, UseCaptureTime, true));
@@ -864,8 +864,12 @@ RouteTimeAxisView::build_display_menu ()
 
 	items.push_back (SeparatorElem());
 	items.push_back (MenuElem (_("Hide"), sigc::bind (sigc::mem_fun(_editor, &PublicEditor::hide_track_in_display), this, true)));
-	items.push_front (SeparatorElem());
-	items.push_front (MenuElem (_("Remove"), sigc::mem_fun(_editor, &PublicEditor::remove_tracks)));
+	if (_route && !_route->is_master()) {
+		items.push_back (SeparatorElem());
+		items.push_back (MenuElem (_("Duplicate..."), boost::bind (&ARDOUR_UI::start_duplicate_routes, ARDOUR_UI::instance())));
+	}
+	items.push_back (SeparatorElem());
+	items.push_back (MenuElem (_("Remove"), sigc::mem_fun(_editor, &PublicEditor::remove_tracks)));
 }
 
 void
@@ -1701,7 +1705,7 @@ RouteTimeAxisView::build_playlist_menu ()
 	playlist_items.push_back (MenuElem (_("Clear Current"), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::clear_playlists), this)));
 	playlist_items.push_back (SeparatorElem());
 
-	playlist_items.push_back (MenuElem(_("Select From All..."), sigc::mem_fun(*this, &RouteTimeAxisView::show_playlist_selector)));
+	playlist_items.push_back (MenuElem(_("Select from All..."), sigc::mem_fun(*this, &RouteTimeAxisView::show_playlist_selector)));
 }
 
 void
@@ -2333,14 +2337,10 @@ RouteTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> p
 	}
 
 	if (x == processor_automation.end()) {
-
 		rai = new ProcessorAutomationInfo (processor);
 		processor_automation.push_back (rai);
-
 	} else {
-
 		rai = *x;
-
 	}
 
 	/* any older menu was deleted at the top of processors_changed()
@@ -2363,6 +2363,10 @@ RouteTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> p
 
 		string name = processor->describe_parameter (*i);
 
+		if (name == X_("hidden")) {
+			continue;
+		}
+
 		items.push_back (CheckMenuElem (name));
 		mitem = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
 
@@ -2389,6 +2393,10 @@ RouteTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> p
 		mitem->signal_toggled().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::processor_menu_item_toggled), rai, pan));
 	}
 
+	if (items.size() == 0) {
+		return;
+	}
+
 	/* add the menu for this processor, because the subplugin
 	   menu is always cleared at the top of processors_changed().
 	   this is the result of some poor design in gtkmm and/or
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index 79506f7..a3fa569 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -17,6 +17,8 @@
 
 */
 
+#include <boost/algorithm/string.hpp>
+
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/choice.h>
 #include <gtkmm2ext/doi.h>
@@ -71,6 +73,7 @@ using namespace std;
 uint32_t RouteUI::_max_invert_buttons = 3;
 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
+std::string RouteUI::program_port_prefix;
 
 RouteUI::RouteUI (ARDOUR::Session* sess)
 	: AxisView(sess)
@@ -84,6 +87,12 @@ RouteUI::RouteUI (ARDOUR::Session* sess)
 	, output_selector (0)
 	, _invert_menu(0)
 {
+	if (program_port_prefix.empty()) {
+		// compare to gtk2_ardour/port_group.cc
+		string lpn (PROGRAM_NAME);
+		boost::to_lower (lpn);
+		program_port_prefix = lpn + ":"; // e.g. "ardour:"
+	}
 	if (sess) init ();
 }
 
@@ -1730,6 +1739,12 @@ RouteUI::set_route_active (bool a, bool apply_to_selection)
 }
 
 void
+RouteUI::duplicate_selected_routes ()
+{
+	ARDOUR_UI::instance()->start_duplicate_routes();
+}
+
+void
 RouteUI::toggle_denormal_protection ()
 {
 	if (denormal_menu_item) {
@@ -1837,41 +1852,64 @@ RouteUI::adjust_latency ()
 	LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
 }
 
-void
-RouteUI::save_as_template ()
+bool
+RouteUI::process_save_template_prompter (ArdourPrompter& prompter, const std::string& dir)
 {
 	std::string path;
 	std::string safe_name;
-	string name;
+	std::string name;
 
-	path = ARDOUR::user_route_template_directory ();
+	prompter.get_result (name, true);
 
-	if (g_mkdir_with_parents (path.c_str(), 0755)) {
-		error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
-		return;
+	safe_name = legalize_for_path (name);
+	safe_name += template_suffix;
+
+	path = Glib::build_filename (dir, safe_name);
+
+	if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
+		bool overwrite = overwrite_file_dialog (prompter,
+		                                        _("Confirm Template Overwrite"),
+							_("A template already exists with that name. Do you want to overwrite it?"));
+
+		if (!overwrite) {
+			return false;
+		}
 	}
 
-	Prompter p (true); // modal
+	_route->save_as_template (path, name);
 
-	p.set_title (_("Save As Template"));
-	p.set_prompt (_("Template name:"));
-	p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
-	switch (p.run()) {
-	case RESPONSE_ACCEPT:
-		break;
-	default:
+	return true;
+}
+
+void
+RouteUI::save_as_template ()
+{
+	std::string dir;
+
+	dir = ARDOUR::user_route_template_directory ();
+
+	if (g_mkdir_with_parents (dir.c_str(), 0755)) {
+		error << string_compose (_("Cannot create route template directory %1"), dir) << endmsg;
 		return;
 	}
 
-	p.hide ();
-	p.get_result (name, true);
+	ArdourPrompter prompter (true); // modal
 
-	safe_name = legalize_for_path (name);
-	safe_name += template_suffix;
-
-	path = Glib::build_filename (path, safe_name);
+	prompter.set_title (_("Save As Template"));
+	prompter.set_prompt (_("Template name:"));
+	prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
 
-	_route->save_as_template (path, name);
+	bool finished = false;
+	while (!finished) {
+		switch (prompter.run()) {
+		case RESPONSE_ACCEPT:
+			finished = process_save_template_prompter (prompter, dir);
+			break;
+		default:
+			finished = true;
+			break;
+		}
+	}
 }
 
 void
diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h
index 7bc434f..ff4d453 100644
--- a/gtk2_ardour/route_ui.h
+++ b/gtk2_ardour/route_ui.h
@@ -194,6 +194,7 @@ class RouteUI : public virtual AxisView
 
 	virtual void route_active_changed () {}
 	void set_route_active (bool, bool);
+	void duplicate_selected_routes ();
 
         Gtk::Menu* record_menu;
         void build_record_menu ();
@@ -219,6 +220,7 @@ class RouteUI : public virtual AxisView
 	virtual void map_frozen ();
 
 	void adjust_latency ();
+	bool process_save_template_prompter (ArdourPrompter& prompter, const std::string& dir);
 	void save_as_template ();
 	void open_remote_control_id_dialog ();
 
@@ -268,6 +270,8 @@ class RouteUI : public virtual AxisView
 
 	virtual void bus_send_display_changed (boost::shared_ptr<ARDOUR::Route>);
 
+	static std::string program_port_prefix;
+
   private:
 	void check_rec_enable_sensitivity ();
 	void parameter_changed (std::string const &);
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 784f646..baf4246 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -26,8 +26,10 @@
 #include "ardour/playlist.h"
 #include "ardour/rc_configuration.h"
 
+#include "audio_region_view.h"
 #include "gui_thread.h"
 #include "midi_cut_buffer.h"
+#include "region_gain_line.h"
 #include "region_view.h"
 #include "selection.h"
 #include "selection_templates.h"
@@ -1113,7 +1115,7 @@ Selection::set (ControlPoint* cp)
 	clear_time ();  //enforce region/object exclusivity
 	clear_tracks();  //enforce object/track exclusivity
 
-	if (cp->get_selected()) {
+	if (cp->get_selected () && points.size () == 1) {
 		return;
 	}
 
@@ -1278,8 +1280,18 @@ Selection::get_state () const
 
 			snprintf(buf, sizeof(buf), "%d", (*i)->view_index());
 			r->add_property (X_("view-index"), string(buf));
+			continue;
+		}
 
+		AudioRegionGainLine* argl = dynamic_cast<AudioRegionGainLine*> (&(*i)->line());
+		if (argl) {
+			XMLNode* r = node->add_child (X_("ControlPoint"));
+			r->add_property (X_("type"), "region");
+			r->add_property (X_("region-id"), atoi (argl->region_view ().region ()->id ().to_s ().c_str()));
+			snprintf(buf, sizeof(buf), "%d", (*i)->view_index());
+			r->add_property (X_("view-index"), string(buf));
 		}
+
 	}
 
 	for (TimeSelection::const_iterator i = time.begin(); i != time.end(); ++i) {
@@ -1412,7 +1424,6 @@ Selection::set_state (XMLNode const & node, int)
 				XMLProperty* prop_parameter = (*i)->property (X_("parameter"));
 				XMLProperty* prop_view_index = (*i)->property (X_("view-index"));
 
-				assert (prop_type);
 				assert (prop_route_id);
 				assert (prop_alist_id);
 				assert (prop_parameter);
@@ -1440,6 +1451,35 @@ Selection::set_state (XMLNode const & node, int)
 				if (!cps.empty()) {
 					add (cps);
 				}
+			} else if (prop_type->value () == "region") {
+				XMLProperty* prop_region_id = (*i)->property (X_("region-id"));
+				XMLProperty* prop_view_index = (*i)->property (X_("view-index"));
+
+				if (!prop_region_id || !prop_view_index) {
+					continue;
+				}
+
+				PBD::ID region_id (prop_region_id->value ());
+				RegionSelection rs;
+				editor->get_regionviews_by_id (region_id, rs);
+
+				if (!rs.empty ()) {
+					vector <ControlPoint *> cps;
+					for (RegionSelection::iterator rsi = rs.begin(); rsi != rs.end(); ++rsi) {
+						AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*rsi);
+						if (arv) {
+							boost::shared_ptr<AudioRegionGainLine> gl = arv->get_gain_line ();
+							ControlPoint* cp = gl->nth(atol(prop_view_index->value().c_str()));
+							if (cp) {
+								cps.push_back (cp);
+								cp->show();
+							}
+						}
+					}
+					if (!cps.empty()) {
+						add (cps);
+					}
+				}
 			}
 
 		} else if  ((*i)->name() == X_("AudioRange")) {
diff --git a/gtk2_ardour/session_dialog.cc b/gtk2_ardour/session_dialog.cc
index 915a7ca..9ba479e 100644
--- a/gtk2_ardour/session_dialog.cc
+++ b/gtk2_ardour/session_dialog.cc
@@ -31,6 +31,7 @@
 
 #include <gtkmm/filechooser.h>
 
+#include "pbd/basename.h"
 #include "pbd/failed_constructor.h"
 #include "pbd/file_utils.h"
 #include "pbd/replace_all.h"
@@ -135,6 +136,8 @@ SessionDialog::SessionDialog (bool require_new, const std::string& session_name,
 
 			if (cnt > 4) {
 				recent_scroller.set_size_request (-1, 300);
+			} else {
+				recent_scroller.set_size_request (-1, 80);
 			}
 		} else {
 			recent_scroller.hide();
@@ -177,12 +180,16 @@ SessionDialog::SessionDialog ()
 
 	get_vbox()->pack_start (recent_scroller, true, true);
 	get_vbox()->show_all ();
+
 	recent_scroller.show();
 
 	int cnt = redisplay_recent_sessions ();
 	if (cnt > 4) {
 		recent_scroller.set_size_request (-1, 300);
+	} else {
+		recent_scroller.set_size_request (-1, 80);
 	}
+
 }
 
 
@@ -244,6 +251,10 @@ SessionDialog::session_name (bool& should_be_new)
 
 	if (iter) {
 		should_be_new = false;
+		string s = (*iter)[recent_session_columns.fullpath];
+		if (Glib::file_test (s, Glib::FILE_TEST_IS_REGULAR)) {
+			return PBD::basename_nosuffix (s);
+		}
 		return (*iter)[recent_session_columns.visible_name];
 	}
 
@@ -397,9 +408,7 @@ SessionDialog::setup_initial_choice_box ()
 	existing_session_chooser.add_filter (session_filter);
 	existing_session_chooser.set_filter (session_filter);
 
-#ifdef GTKOSX
-	existing_session_chooser.add_shortcut_folder ("/Volumes");
-#endif
+	Gtkmm2ext::add_volume_shortcuts (existing_session_chooser);
 
 	Label* browse_label = manage (new Label);
 	browse_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Other Sessions")));
@@ -407,6 +416,17 @@ SessionDialog::setup_initial_choice_box ()
 	centering_vbox->pack_start (*browse_label, false, false, 12);
 	centering_vbox->pack_start (existing_session_chooser, false, false);
 
+	/* --disable plugins UI */
+
+	_disable_plugins.set_label (_("Safe Mode: Disable all Plugins"));
+	_disable_plugins.set_flags (Gtk::CAN_FOCUS);
+	_disable_plugins.set_relief (Gtk::RELIEF_NORMAL);
+	_disable_plugins.set_mode (true);
+	_disable_plugins.set_active (ARDOUR::Session::get_disable_all_loaded_plugins());
+	_disable_plugins.set_border_width(0);
+	_disable_plugins.signal_clicked().connect (sigc::mem_fun (*this, &SessionDialog::disable_plugins_clicked));
+	centering_vbox->pack_start (_disable_plugins, false, false);
+
 	/* pack it all up */
 
 	centering_hbox->pack_start (*centering_vbox, true, true);
@@ -540,9 +560,7 @@ SessionDialog::setup_new_session_page ()
 	new_folder_chooser.show ();
 	new_folder_chooser.set_title (_("Select folder for session"));
 
-#ifdef __APPLE__
-	new_folder_chooser.add_shortcut_folder ("/Volumes");
-#endif
+	Gtkmm2ext::add_volume_shortcuts (new_folder_chooser);
 
 	vbox1->pack_start (*hbox2, false, false);
 
@@ -694,14 +712,27 @@ SessionDialog::redisplay_recent_sessions ()
 
 		float sr;
 		SampleFormat sf;
-		std::string state_file_basename = state_file_names.front();
+
+		std::string state_file_basename;
+
+		if (state_file_names.size() > 1) {
+			state_file_basename = Session::get_snapshot_from_instant (dirname);
+			std::string s = Glib::build_filename (dirname, state_file_basename + statefile_suffix);
+			if (!Glib::file_test (s, Glib::FILE_TEST_IS_REGULAR)) {
+				state_file_basename = "";
+			}
+		}
+
+		if (state_file_basename.empty()) {
+			state_file_basename = state_file_names.front();
+		}
 
 		std::string s = Glib::build_filename (dirname, state_file_basename + statefile_suffix);
 
 		GStatBuf gsb;
 		g_stat (s.c_str(), &gsb);
 
-		row[recent_session_columns.fullpath] = dirname; /* just the dir, but this works too */
+		row[recent_session_columns.fullpath] = s;
 		row[recent_session_columns.tip] = Gtkmm2ext::markup_escape_text (dirname);
 		row[recent_session_columns.time_modified] = gsb.st_mtime;
 
@@ -709,13 +740,13 @@ SessionDialog::redisplay_recent_sessions ()
 			row[recent_session_columns.sample_rate] = rate_as_string (sr);
 			switch (sf) {
 			case FormatFloat:
-				row[recent_session_columns.disk_format] = _("32 bit float");
+				row[recent_session_columns.disk_format] = _("32-bit float");
 				break;
 			case FormatInt24:
-				row[recent_session_columns.disk_format] = _("24 bit");
+				row[recent_session_columns.disk_format] = _("24-bit");
 				break;
 			case FormatInt16:
-				row[recent_session_columns.disk_format] = _("16 bit");
+				row[recent_session_columns.disk_format] = _("16-bit");
 				break;
 			}
 		} else {
@@ -756,13 +787,13 @@ SessionDialog::redisplay_recent_sessions ()
 					child_row[recent_session_columns.sample_rate] = rate_as_string (sr);
 					switch (sf) {
 					case FormatFloat:
-						child_row[recent_session_columns.disk_format] = _("32 bit float");
+						child_row[recent_session_columns.disk_format] = _("32-bit float");
 						break;
 					case FormatInt24:
-						child_row[recent_session_columns.disk_format] = _("24 bit");
+						child_row[recent_session_columns.disk_format] = _("24-bit");
 						break;
 					case FormatInt16:
-						child_row[recent_session_columns.disk_format] = _("16 bit");
+						child_row[recent_session_columns.disk_format] = _("16-bit");
 						break;
 					}
 				} else {
@@ -1133,6 +1164,12 @@ SessionDialog::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
 }
 
 void
+SessionDialog::disable_plugins_clicked ()
+{
+	ARDOUR::Session::set_disable_all_loaded_plugins (_disable_plugins.get_active());
+}
+
+void
 SessionDialog::existing_session_selected ()
 {
 	_existing_session_chooser_used = true;
diff --git a/gtk2_ardour/session_dialog.h b/gtk2_ardour/session_dialog.h
index 6953218..9143007 100644
--- a/gtk2_ardour/session_dialog.h
+++ b/gtk2_ardour/session_dialog.h
@@ -76,6 +76,11 @@ class SessionDialog : public ArdourDialog {
 	bool connect_outs_to_master() const;
 	bool connect_outs_to_physical() const;
 
+	void set_provided_session(const std::string& session_name, const std::string& session_path) {
+		_provided_session_name = session_name;
+		_provided_session_path = session_path;
+	}
+
   private:
 	bool new_only;
         std::string _provided_session_name;
@@ -231,6 +236,10 @@ class SessionDialog : public ArdourDialog {
 	void master_bus_button_clicked ();
 	void setup_more_options_box ();
 
+	/* --disable plugins UI */
+	Gtk::CheckButton _disable_plugins;
+	void disable_plugins_clicked ();
+
 	/* always there */
 
 	Glib::RefPtr<Pango::Layout> layout;
diff --git a/gtk2_ardour/session_import_dialog.cc b/gtk2_ardour/session_import_dialog.cc
index ed50b5d..5783c83 100644
--- a/gtk2_ardour/session_import_dialog.cc
+++ b/gtk2_ardour/session_import_dialog.cc
@@ -41,7 +41,7 @@ using namespace PBD;
 using namespace Gtk;
 
 SessionImportDialog::SessionImportDialog (ARDOUR::Session* target) :
-  ArdourDialog (_("Import From Session")),
+  ArdourDialog (_("Import from Session")),
   file_browse_button (_("Browse"))
 {
 	set_session (target);
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index c2bd388..4c96172 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -566,12 +566,12 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s, bool persi
 		chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
 		chooser.add_shortcut_folder_uri("file:///Library/Audio/Apple Loops");
 		chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
-		chooser.add_shortcut_folder_uri("file:///Volumes");
 	}
 	catch (Glib::Error & e) {
 		std::cerr << "sfdb.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
 	}
 #endif
+	Gtkmm2ext::add_volume_shortcuts (chooser);
 
 	//add the file chooser
 
@@ -1293,6 +1293,11 @@ SoundFileOmega::reset_options_noret ()
 bool
 SoundFileOmega::reset_options ()
 {
+	if (_import_active) {
+		_reset_post_import = true;
+		return true;
+	}
+
 	vector<string> paths = get_paths ();
 
 	if (paths.empty()) {
@@ -1664,6 +1669,8 @@ SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s,
 	, copy_files_btn ( _("Copy files to session"))
 	, selected_audio_track_cnt (selected_audio_tracks)
 	, selected_midi_track_cnt (selected_midi_tracks)
+	, _import_active (false)
+	, _reset_post_import (false)
 {
 	VBox* vbox;
 	HBox* hbox;
@@ -1977,10 +1984,19 @@ SoundFileOmega::do_something (int action)
 
 	SrcQuality quality = get_src_quality();
 
+	_import_active = true;
+
 	if (copy_files_btn.get_active()) {
 		PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
 	} else {
 		PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
 	}
+
+	_import_active = false;
+
+	if (_reset_post_import) {
+		_reset_post_import = false;
+		reset_options ();
+	}
 }
 
diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h
index 3c4f088..fcdce2a 100644
--- a/gtk2_ardour/sfdb_ui.h
+++ b/gtk2_ardour/sfdb_ui.h
@@ -321,6 +321,9 @@ class SoundFileOmega : public SoundFileBrowser
 	void where_combo_changed ();
 
 	void do_something (int action);
+
+	bool _import_active;
+	bool _reset_post_import;
 };
 
 #endif // __ardour_sfdb_ui_h__
diff --git a/gtk2_ardour/shuttle_control.cc b/gtk2_ardour/shuttle_control.cc
index 94c27c2..4616b76 100644
--- a/gtk2_ardour/shuttle_control.cc
+++ b/gtk2_ardour/shuttle_control.cc
@@ -678,7 +678,7 @@ ShuttleControl::ShuttleControllable::ShuttleControllable (ShuttleControl& s)
 }
 
 void
-ShuttleControl::ShuttleControllable::set_value (double val)
+ShuttleControl::ShuttleControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
 {
 	sc.set_shuttle_fract ((val - lower()) / (upper() - lower()), true);
 }
diff --git a/gtk2_ardour/shuttle_control.h b/gtk2_ardour/shuttle_control.h
index ed15a12..20fe460 100644
--- a/gtk2_ardour/shuttle_control.h
+++ b/gtk2_ardour/shuttle_control.h
@@ -46,7 +46,7 @@ class ShuttleControl : public CairoWidget, public ARDOUR::SessionHandlePtr
 
 	struct ShuttleControllable : public PBD::Controllable {
 		ShuttleControllable (ShuttleControl&);
-		void set_value (double);
+		void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
 		double get_value (void) const;
 
                 double lower() const { return -1.0; }
diff --git a/gtk2_ardour/stereo_panner.cc b/gtk2_ardour/stereo_panner.cc
index 91c8b02..304300f 100644
--- a/gtk2_ardour/stereo_panner.cc
+++ b/gtk2_ardour/stereo_panner.cc
@@ -52,6 +52,8 @@ using namespace Gtk;
 using namespace Gtkmm2ext;
 using namespace ARDOUR_UI_UTILS;
 
+using PBD::Controllable;
+
 StereoPanner::ColorScheme StereoPanner::colors[3];
 bool StereoPanner::have_colors = false;
 
@@ -355,21 +357,21 @@ StereoPanner::on_button_press_event (GdkEventButton* ev)
 				/* left side dbl click */
 				if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) {
 					/* 2ndary-double click on left, collapse to hard left */
-					width_control->set_value (0);
-					position_control->set_value (0);
+					width_control->set_value (0, Controllable::NoGroup);
+					position_control->set_value (0, Controllable::NoGroup);
 				} else {
-					position_control->set_value (min_pos);
+					position_control->set_value (min_pos, Controllable::NoGroup);
 				}
 			} else if (ev->x > 2*width/3) {
 				if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) {
 					/* 2ndary-double click on right, collapse to hard right */
-					width_control->set_value (0);
-					position_control->set_value (1.0);
+					width_control->set_value (0, Controllable::NoGroup);
+					position_control->set_value (1.0, Controllable::NoGroup);
 				} else {
-					position_control->set_value (max_pos);
+					position_control->set_value (max_pos, Controllable::NoGroup);
 				}
 			} else {
-				position_control->set_value (0.5);
+				position_control->set_value (0.5, Controllable::NoGroup);
 			}
 
 		} else {
@@ -381,13 +383,13 @@ StereoPanner::on_button_press_event (GdkEventButton* ev)
 
 			if (ev->x <= width/3) {
 				/* left side dbl click */
-				width_control->set_value (max_width); // reset width to 100%
+				width_control->set_value (max_width, Controllable::NoGroup); // reset width to 100%
 			} else if (ev->x > 2*width/3) {
 				/* right side dbl click */
-				width_control->set_value (-max_width); // reset width to inverted 100%
+				width_control->set_value (-max_width, Controllable::NoGroup); // reset width to inverted 100%
 			} else {
 				/* center dbl click */
-				width_control->set_value (0); // collapse width to 0%
+				width_control->set_value (0, Controllable::NoGroup); // collapse width to 0%
 			}
 		}
 
@@ -500,19 +502,19 @@ StereoPanner::on_scroll_event (GdkEventScroll* ev)
 	switch (ev->direction) {
 	case GDK_SCROLL_LEFT:
 		wv += step;
-		width_control->set_value (wv);
+		width_control->set_value (wv, Controllable::NoGroup);
 		break;
 	case GDK_SCROLL_UP:
 		pv -= step;
-		position_control->set_value (pv);
+		position_control->set_value (pv, Controllable::NoGroup);
 		break;
 	case GDK_SCROLL_RIGHT:
 		wv -= step;
-		width_control->set_value (wv);
+		width_control->set_value (wv, Controllable::NoGroup);
 		break;
 	case GDK_SCROLL_DOWN:
 		pv += step;
-		position_control->set_value (pv);
+		position_control->set_value (pv, Controllable::NoGroup);
 		break;
 	}
 
@@ -551,9 +553,9 @@ StereoPanner::on_motion_notify_event (GdkEventMotion* ev)
 			double pv = position_control->get_value();
 
 			if (dragging_left) {
-				position_control->set_value (pv - delta);
+				position_control->set_value (pv - delta, Controllable::NoGroup);
 			} else {
-				position_control->set_value (pv + delta);
+				position_control->set_value (pv + delta, Controllable::NoGroup);
 			}
 
 			if (delta > 0.0) {
@@ -563,9 +565,9 @@ StereoPanner::on_motion_notify_event (GdkEventMotion* ev)
 				   other side remains in place when we set
 				   the position as well.
 				*/
-				width_control->set_value (current_width + (delta * 2.0));
+				width_control->set_value (current_width + (delta * 2.0), Controllable::NoGroup);
 			} else {
-				width_control->set_value (current_width + delta);
+				width_control->set_value (current_width + delta, Controllable::NoGroup);
 			}
 
 			_panner->thaw ();
@@ -579,7 +581,7 @@ StereoPanner::on_motion_notify_event (GdkEventMotion* ev)
 			if (!detented && fabs (current_width) < 0.02) {
 				detented = true;
 				/* snap to zero */
-				width_control->set_value (0);
+				width_control->set_value (0, Controllable::NoGroup);
 			}
 
 			if (detented) {
@@ -589,21 +591,21 @@ StereoPanner::on_motion_notify_event (GdkEventMotion* ev)
 				/* have we pulled far enough to escape ? */
 
 				if (fabs (accumulated_delta) >= 0.025) {
-					width_control->set_value (current_width + accumulated_delta);
+					width_control->set_value (current_width + accumulated_delta, Controllable::NoGroup);
 					detented = false;
 					accumulated_delta = false;
 				}
 
 			} else {
 				/* width needs to change by 2 * delta because both L & R move */
-				width_control->set_value (current_width + (delta * 2.0));
+				width_control->set_value (current_width + (delta * 2.0), Controllable::NoGroup);
 			}
 		}
 
 	} else if (dragging_position) {
 
 		double pv = position_control->get_value(); // 0..1.0 ; 0 = left
-		position_control->set_value (pv + delta);
+		position_control->set_value (pv + delta, Controllable::NoGroup);
 	}
 
 	last_drag_x = ev->x;
@@ -635,30 +637,30 @@ StereoPanner::on_key_press_event (GdkEventKey* ev)
 	switch (ev->keyval) {
 	case GDK_Up:
 		if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
-			width_control->set_value (1.0);
+			width_control->set_value (1.0, Controllable::NoGroup);
 		} else {
-			width_control->set_value (wv + step);
+			width_control->set_value (wv + step, Controllable::NoGroup);
 		}
 		break;
 	case GDK_Down:
 		if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
-			width_control->set_value (-1.0);
+			width_control->set_value (-1.0, Controllable::NoGroup);
 		} else {
-			width_control->set_value (wv - step);
+			width_control->set_value (wv - step, Controllable::NoGroup);
 		}
 		break;
 
 	case GDK_Left:
 		pv -= step;
-		position_control->set_value (pv);
+		position_control->set_value (pv, Controllable::NoGroup);
 		break;
 	case GDK_Right:
 		pv += step;
-		position_control->set_value (pv);
+		position_control->set_value (pv, Controllable::NoGroup);
 		break;
 	case GDK_0:
 	case GDK_KP_0:
-		width_control->set_value (0.0);
+		width_control->set_value (0.0, Controllable::NoGroup);
 		break;
 
 	default:
diff --git a/gtk2_ardour/stereo_panner_editor.cc b/gtk2_ardour/stereo_panner_editor.cc
index e7a4a45..477a665 100644
--- a/gtk2_ardour/stereo_panner_editor.cc
+++ b/gtk2_ardour/stereo_panner_editor.cc
@@ -31,6 +31,8 @@ using namespace std;
 using namespace Gtk;
 using namespace Gtkmm2ext;
 
+using PBD::Controllable;
+
 StereoPannerEditor::StereoPannerEditor (StereoPanner* p)
 	: PannerEditor (_("Stereo Panner"))
 	, _panner (p)
@@ -103,7 +105,7 @@ StereoPannerEditor::position_changed ()
 
 	_ignore_changes = true;
 	double const v = _position.get_value() / 100;
-	_panner->get_position_controllable()->set_value (v);
+	_panner->get_position_controllable()->set_value (v, Controllable::NoGroup);
 	set_width_range ();
 	_ignore_changes = false;
 }
@@ -117,7 +119,7 @@ StereoPannerEditor::width_changed ()
 
 	_ignore_changes = true;
 	double const v = _width.get_value() / 100;
-	_panner->get_width_controllable()->set_value (v);
+	_panner->get_width_controllable()->set_value (v, Controllable::NoGroup);
 	set_position_range ();
 	_ignore_changes = false;
 }
diff --git a/gtk2_ardour/strip_silence_dialog.cc b/gtk2_ardour/strip_silence_dialog.cc
index d802244..cd41950 100644
--- a/gtk2_ardour/strip_silence_dialog.cc
+++ b/gtk2_ardour/strip_silence_dialog.cc
@@ -46,6 +46,8 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list<RegionView*> const & v)
 	, _minimum_length (new AudioClock (X_("silence duration"), true, "", true, false, true, false))
 	, _fade_length (new AudioClock (X_("silence duration"), true, "", true, false, true, false))
 	, _destroying (false)
+	, analysis_progress_cur (0)
+	, analysis_progress_max (0)
 {
 	set_session (s);
 
@@ -106,6 +108,11 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list<RegionView*> const & v)
 	update_silence_rects ();
 	update_threshold_line ();
 
+	_progress_bar.set_text (_("Analyzing"));
+	update_progress_gui (0);
+	apply_button->set_sensitive (false);
+	progress_idle_connection = Glib::signal_idle().connect (sigc::mem_fun (*this, &StripSilenceDialog::idle_update_progress));
+
 	/* Create a thread which runs while the dialogue is open to compute the silence regions */
 	Completed.connect (_completed_connection, invalidator(*this), boost::bind (&StripSilenceDialog::update, this), gui_context ());
 	_thread_should_finish = false;
@@ -116,10 +123,11 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list<RegionView*> const & v)
 StripSilenceDialog::~StripSilenceDialog ()
 {
 	_destroying = true;
+	progress_idle_connection.disconnect();
 
 	/* Terminate our thread */
-	_lock.lock ();
 	_interthread_info.cancel = true;
+	_lock.lock ();
 	_thread_should_finish = true;
 	_lock.unlock ();
 
@@ -130,6 +138,21 @@ StripSilenceDialog::~StripSilenceDialog ()
 	delete _fade_length;
 }
 
+bool
+StripSilenceDialog::idle_update_progress()
+{
+	if (analysis_progress_max > 0) {
+		// AudioRegion::find_silence() has
+		// itt.progress = (end - pos) / length
+		// not sure if that's intentional, but let's use (1. - val)
+		float rp = std::min(1.f, std::max (0.f, (1.f - _interthread_info.progress)));
+		float p = analysis_progress_cur / (float) analysis_progress_max
+		        + rp / (float) analysis_progress_max;
+		update_progress_gui (p);
+	}
+	return !_destroying;
+}
+
 void
 StripSilenceDialog::silences (AudioIntervalMap& m)
 {
@@ -145,6 +168,12 @@ StripSilenceDialog::drop_rects ()
 	// called by parent when starting to progess (dialog::run returned),
 	// but before the dialog is destoyed.
 
+	_interthread_info.cancel = true;
+
+	/* Block until the thread is idle */
+	_lock.lock ();
+	_lock.unlock ();
+
 	for (list<ViewInterval>::iterator v = views.begin(); v != views.end(); ++v) {
 		v->view->drop_silent_frames ();
 	}
@@ -180,6 +209,9 @@ StripSilenceDialog::update ()
 {
 	update_threshold_line ();
 	update_silence_rects ();
+	_progress_bar.set_text ("");
+	update_progress_gui (0);
+	apply_button->set_sensitive(true);
 }
 
 void
@@ -205,12 +237,17 @@ StripSilenceDialog::_detection_thread_work (void* arg)
 void *
 StripSilenceDialog::detection_thread_work ()
 {
-	ARDOUR_UI::instance()->register_thread ("gui", pthread_self(), "silence", 32);
+	/* Do not register with all UIs, but do register with the GUI,
+	   because we will need to queue some GUI (only) requests
+	*/
+	ARDOUR_UI::instance()->register_thread (pthread_self(), "silence", 32);
 
 	/* Hold this lock when we are doing work */
 	_lock.lock ();
 
 	while (1) {
+		analysis_progress_cur = 0;
+		analysis_progress_max = views.size();
 		for (list<ViewInterval>::iterator i = views.begin(); i != views.end(); ++i) {
 			boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> ((*i).view->region());
 
@@ -221,8 +258,13 @@ StripSilenceDialog::detection_thread_work ()
 			if (_interthread_info.cancel) {
 				break;
 			}
+			++analysis_progress_cur;
+			_interthread_info.progress = 1.0;
+			ARDOUR::GUIIdle ();
 		}
 
+		analysis_progress_max = 0;
+
 		if (!_interthread_info.cancel) {
 			Completed (); /* EMIT SIGNAL */
 		}
@@ -253,6 +295,10 @@ StripSilenceDialog::restart_thread ()
 		return;
 	}
 
+	_progress_bar.set_text (_("Analyzing"));
+	update_progress_gui (0);
+	apply_button->set_sensitive (false);
+
 	/* Cancel any current run */
 	_interthread_info.cancel = true;
 
diff --git a/gtk2_ardour/strip_silence_dialog.h b/gtk2_ardour/strip_silence_dialog.h
index 44f5409..7445b72 100644
--- a/gtk2_ardour/strip_silence_dialog.h
+++ b/gtk2_ardour/strip_silence_dialog.h
@@ -89,4 +89,9 @@ private:
 	PBD::Signal0<void> Completed; ///< emitted when a silence detection has completed
 	PBD::ScopedConnection _completed_connection;
 	ARDOUR::InterThreadInfo _interthread_info;
+
+	sigc::connection progress_idle_connection;
+	bool idle_update_progress(); ///< GUI-thread progress updates of background silence computation
+	int analysis_progress_cur;
+	int analysis_progress_max;
 };
diff --git a/gtk2_ardour/theme_manager.cc b/gtk2_ardour/theme_manager.cc
index 8374c5d..e1daeab 100644
--- a/gtk2_ardour/theme_manager.cc
+++ b/gtk2_ardour/theme_manager.cc
@@ -35,6 +35,7 @@
 #include "pbd/compose.h"
 
 #include "ardour/filesystem_paths.h"
+#include "ardour/profile.h"
 
 #include "canvas/container.h"
 #include "canvas/rectangle.h"
@@ -70,6 +71,7 @@ ThemeManager::ThemeManager()
 	, timeline_item_gradient_depth_label (_("Timeline item gradient depth"))
 	, all_dialogs (_("All floating windows are dialogs"))
 	, transients_follow_front (_("Transient windows follow front window."))
+	, floating_monitor_section (_("Float detached monitor-section window"))
 	, icon_set_label (_("Icon Set"))
 	, palette_viewport (*palette_scroller.get_hadjustment(), *palette_scroller.get_vadjustment())
 	, palette_group (0)
@@ -91,7 +93,6 @@ ThemeManager::ThemeManager()
 	alias_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
 	alias_display.get_column (1)->set_expand (false);
 	alias_display.set_reorderable (false);
-	alias_display.get_selection()->set_mode (SELECTION_NONE);
 	alias_display.set_headers_visible (true);
 
 	alias_display.signal_button_press_event().connect (sigc::mem_fun (*this, &ThemeManager::alias_button_press_event), false);
@@ -115,6 +116,9 @@ ThemeManager::ThemeManager()
 	pack_start (all_dialogs, PACK_SHRINK);
 	pack_start (transients_follow_front, PACK_SHRINK);
 #endif
+	if (!Profile->get_mixbus()) {
+		pack_start (floating_monitor_section, PACK_SHRINK);
+	}
 	pack_start (flat_buttons, PACK_SHRINK);
 	pack_start (blink_rec_button, PACK_SHRINK);
 	pack_start (region_color_button, PACK_SHRINK);
@@ -184,6 +188,7 @@ ThemeManager::ThemeManager()
 	timeline_item_gradient_depth.signal_value_changed().connect (sigc::mem_fun (*this, &ThemeManager::on_timeline_item_gradient_depth_change));
 	all_dialogs.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_all_dialogs_toggled));
 	transients_follow_front.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_transients_follow_front_toggled));
+	floating_monitor_section.signal_toggled().connect (sigc::mem_fun (*this, &ThemeManager::on_floating_monitor_section_toggled));
 	icon_set_dropdown.signal_changed().connect (sigc::mem_fun (*this, &ThemeManager::on_icon_set_changed));
 
 	Gtkmm2ext::UI::instance()->set_tip (all_dialogs,
@@ -193,6 +198,9 @@ ThemeManager::ThemeManager()
 	Gtkmm2ext::UI::instance()->set_tip (transients_follow_front,
 					    string_compose (_("Make transient windows follow the front window when toggling between the editor and mixer.\n"
 							      "This requires a restart of %1 to take effect"), PROGRAM_NAME));
+	Gtkmm2ext::UI::instance()->set_tip (floating_monitor_section,
+					    string_compose (_("When detaching the monitoring section, mark it as \"Utility\" window to stay in front.\n"
+							      "This requires a restart of %1 to take effect"), PROGRAM_NAME));
 
 	set_size_request (-1, 400);
 	/* no need to call setup_palette() here, it will be done when its size is allocated */
@@ -307,6 +315,12 @@ ThemeManager::on_transients_follow_front_toggled ()
 }
 
 void
+ThemeManager::on_floating_monitor_section_toggled ()
+{
+	UIConfiguration::instance().set_floating_monitor_section (floating_monitor_section.get_active());
+}
+
+void
 ThemeManager::on_waveform_gradient_depth_change ()
 {
 	double v = waveform_gradient_depth.get_value();
@@ -369,6 +383,7 @@ ThemeManager::set_ui_to_state()
 	 */
 	all_dialogs.set_active (UIConfiguration::instance().get_all_floating_windows_are_dialogs());
 	transients_follow_front.set_active (UIConfiguration::instance().get_transients_follow_front());
+	floating_monitor_section.set_active (UIConfiguration::instance().get_floating_monitor_section());
 	flat_buttons.set_active (UIConfiguration::instance().get_flat_buttons());
 	blink_rec_button.set_active (UIConfiguration::instance().get_blink_rec_arm());
 	region_color_button.set_active (UIConfiguration::instance().get_color_regions_using_track_color());
diff --git a/gtk2_ardour/theme_manager.h b/gtk2_ardour/theme_manager.h
index 6ed5820..36e85e5 100644
--- a/gtk2_ardour/theme_manager.h
+++ b/gtk2_ardour/theme_manager.h
@@ -60,6 +60,7 @@ class ThemeManager : public Gtk::VBox
         void on_timeline_item_gradient_depth_change ();
 	void on_all_dialogs_toggled ();
 	void on_transients_follow_front_toggled ();
+	void on_floating_monitor_section_toggled ();
 	void on_icon_set_changed ();
 
   private:
@@ -92,6 +93,7 @@ class ThemeManager : public Gtk::VBox
         Gtk::Label timeline_item_gradient_depth_label;
 	Gtk::CheckButton all_dialogs;
 	Gtk::CheckButton transients_follow_front;
+	Gtk::CheckButton floating_monitor_section;
 	Gtk::CheckButton gradient_waveforms;
 	Gtk::Label icon_set_label;
 	Gtk::ComboBoxText icon_set_dropdown;
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 436e161..4ad476b 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -221,8 +221,6 @@ TimeAxisView::TimeAxisView (ARDOUR::Session* sess, PublicEditor& ed, TimeAxisVie
 	top_hbox.pack_start (scroomer_placeholder, false, false); // OR pack_end to move after meters ?
 
 	UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &TimeAxisView::color_handler));
-
-	GhostRegion::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&TimeAxisView::erase_ghost, this, _1), gui_context());
 }
 
 TimeAxisView::~TimeAxisView()
diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc
index 5a85005..008dfab 100644
--- a/gtk2_ardour/time_axis_view_item.cc
+++ b/gtk2_ardour/time_axis_view_item.cc
@@ -171,14 +171,12 @@ TimeAxisViewItem::init (ArdourCanvas::Item* parent, double fpp, uint32_t base_co
 	position_locked = false;
 	max_item_duration = ARDOUR::max_framepos;
 	min_item_duration = 0;
-	show_vestigial = true;
 	visibility = vis;
 	_sensitive = true;
 	name_text_width = 0;
 	last_item_width = 0;
 	wide_enough_for_name = wide;
 	high_enough_for_name = high;
-	vestigial_frame = 0;
 
 	if (duration == 0) {
 		warning << "Time Axis Item Duration == 0" << endl;
@@ -191,6 +189,7 @@ TimeAxisViewItem::init (ArdourCanvas::Item* parent, double fpp, uint32_t base_co
 									 trackview.current_height()));
 
 		frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::LEFT|ArdourCanvas::Rectangle::RIGHT));
+		frame->show ();
 
 		CANVAS_DEBUG_NAME (frame, string_compose ("frame for %1", get_item_name()));
 
@@ -571,11 +570,6 @@ TimeAxisViewItem::set_height (double height)
 		}
 	}
 
-	if (vestigial_frame) {
-		vestigial_frame->set_y0 (0.0);
-		vestigial_frame->set_y1 (height);
-	}
-
 	set_colors ();
 }
 
@@ -823,21 +817,9 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 
 	if (pixel_width < 2.0) {
 
-		if (show_vestigial) {
-
-			if (!vestigial_frame) {
-				vestigial_frame = new ArdourCanvas::Rectangle (group, ArdourCanvas::Rect (0.0, 0.0, 2.0, trackview.current_height()));
-				CANVAS_DEBUG_NAME (vestigial_frame, string_compose ("vestigial frame for %1", get_item_name()));
-				vestigial_frame->set_outline_color (UIConfiguration::instance().color ("vestigial frame"));
-				vestigial_frame->set_fill_color (UIConfiguration::instance().color ("vestigial frame"));
-				vestigial_frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::LEFT|ArdourCanvas::Rectangle::RIGHT));
-			}
-
-			vestigial_frame->show();
-		}
-
 		if (frame) {
-			frame->hide();
+			frame->set_outline (false);
+			frame->set_x1 (std::max(1.0, pixel_width));
 		}
 
 		if (frame_handle_start) {
@@ -846,12 +828,8 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 		}
 
 	} else {
-		if (vestigial_frame) {
-			vestigial_frame->hide();
-		}
-
 		if (frame) {
-			frame->show();
+			frame->set_outline (true);
 			/* Note: x0 is always zero - the position is defined by
 			 * the position of the group, not the frame.
 			 */
diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h
index af08d9d..63cc564 100644
--- a/gtk2_ardour/time_axis_view_item.h
+++ b/gtk2_ardour/time_axis_view_item.h
@@ -210,9 +210,6 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
 	/** true if the name should respond to events */
 	bool name_connected;
 
-	/** true if a small vestigial rect should be shown when the item gets very narrow */
-	bool show_vestigial;
-
 	uint32_t fill_color;
 
 	uint32_t last_item_width;
@@ -221,7 +218,6 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
 	bool high_enough_for_name;
 
 	ArdourCanvas::Container*      group;
-	ArdourCanvas::Rectangle* vestigial_frame;
 	ArdourCanvas::Rectangle* frame;
 	ArdourCanvas::Rectangle* selection_frame;
 	ArdourCanvas::Text*      name_text;
diff --git a/gtk2_ardour/timers.cc b/gtk2_ardour/timers.cc
index 13f2cfd..3469d39 100644
--- a/gtk2_ardour/timers.cc
+++ b/gtk2_ardour/timers.cc
@@ -87,6 +87,7 @@ public:
 		, rapid(100)
 		, super_rapid(40)
 		, fps(40)
+		, _suspend_counter(0)
 	{
 #ifndef NDEBUG
 		second.connect (sigc::mem_fun (*this, &UITimers::on_second_timer));
@@ -99,6 +100,8 @@ public:
 	StandardTimer   super_rapid;
 	StandardTimer   fps;
 
+	gint            _suspend_counter;
+
 #ifndef NDEBUG
 	std::vector<uint64_t> rapid_eps_count;
 	std::vector<uint64_t> super_rapid_eps_count;
@@ -207,4 +210,22 @@ fps_connect(const sigc::slot<void>& slot)
 	return get_timers().fps.connect (slot);
 }
 
+TimerSuspender::TimerSuspender ()
+{
+	if (g_atomic_int_add(&get_timers()._suspend_counter, 1) == 0) {
+		get_timers().rapid.suspend();
+		get_timers().super_rapid.suspend();
+		get_timers().fps.suspend();
+	}
+}
+
+TimerSuspender::~TimerSuspender ()
+{
+	if (g_atomic_int_dec_and_test (&get_timers()._suspend_counter)) {
+		get_timers().rapid.resume();
+		get_timers().super_rapid.resume();
+		get_timers().fps.resume();
+	}
+}
+
 } // namespace Timers
diff --git a/gtk2_ardour/timers.h b/gtk2_ardour/timers.h
index 8854571..28e88e4 100644
--- a/gtk2_ardour/timers.h
+++ b/gtk2_ardour/timers.h
@@ -37,6 +37,12 @@ void set_fps_interval(unsigned int interval);
 
 sigc::connection fps_connect(const sigc::slot<void>& slot);
 
+class TimerSuspender {
+	public:
+		TimerSuspender ();
+		~TimerSuspender ();
+};
+
 };
 
 #endif // TIMERS_H
diff --git a/gtk2_ardour/transcode_ffmpeg.cc b/gtk2_ardour/transcode_ffmpeg.cc
index efe4e44..2883f87 100644
--- a/gtk2_ardour/transcode_ffmpeg.cc
+++ b/gtk2_ardour/transcode_ffmpeg.cc
@@ -53,9 +53,9 @@ TranscodeFfmpeg::TranscodeFfmpeg (std::string f)
 	if (!ArdourVideoToolPaths::transcoder_exe(ffmpeg_exe, ffprobe_exe)) {
 		warning << string_compose(
 				_(
-					"No ffprobe or ffmpeg executables could be found on this system.\n"
-					"Video import and export is not possible until you install those tools.\n"
+					"ffmpeg installation was not found on this system.\n"
 					"%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
+					"Video import and export is not possible until you install tools.\n"
 					"\n"
 					"The tools are included with the %1 releases from ardour.org "
 					"and also available with the video-server at http://x42.github.com/harvid/\n"
@@ -96,7 +96,7 @@ TranscodeFfmpeg::probe ()
 	argp[6] = 0;
 	ffcmd = new ARDOUR::SystemExec(ffprobe_exe, argp);
 	ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffprobeparse, this, _1 ,_2));
-	ffcmd->Terminated.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffexit, this));
+	ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
 	if (ffcmd->start(1)) {
 		ffexit();
 		return false;
@@ -110,6 +110,7 @@ TranscodeFfmpeg::probe ()
 	int timeout = 300; // 1.5 sec
 	while (ffcmd && --timeout > 0) {
 		Glib::usleep(5000);
+		ARDOUR::GUIIdle();
 	}
 	if (timeout == 0 || ffoutput.empty()) {
 		return false;
@@ -137,9 +138,20 @@ TranscodeFfmpeg::probe ()
 		} \
 	}
 
+	std::string duration_from_format;
+
 	for (std::vector<std::vector<std::string> >::iterator i = lines.begin(); i != lines.end(); ++i) {
 		if (i->at(0) == X_("format")) {
 			/* format,filename,#streams,format-name,format-long-name,start-time,duration,size,bitrate */
+			for (std::vector<std::string>::iterator kv = i->begin(); kv != i->end(); ++kv) {
+				const size_t kvsep = kv->find('=');
+				if(kvsep == std::string::npos) continue;
+				std::string key = kv->substr(0, kvsep);
+				std::string value = kv->substr(kvsep + 1);
+				if (key == X_("duration")) {
+					duration_from_format = value;
+				}
+			}
 		} else
 		if (i->at(0) == X_("stream")) {
 			if (i->at(5) == X_("codec_type=video") && m_width == 0) {
@@ -171,7 +183,7 @@ TranscodeFfmpeg::probe ()
 						PARSE_FRACTIONAL_FPS(m_fps)
 					} else if (key == X_("time_base")) {
 						PARSE_FRACTIONAL_FPS(timebase)
-					} else if (key == X_("timecode") && m_duration == 0) {
+					} else if (key == X_("timecode") && m_duration == 0 && m_fps > 0) {
 						int h,m,s; char f[32];
 						if (sscanf(i->at(16).c_str(), "%d:%d:%d:%32s",&h,&m,&s,f) == 4) {
 							m_duration = (ARDOUR::framecnt_t) floor(m_fps * (
@@ -238,6 +250,11 @@ TranscodeFfmpeg::probe ()
 	}
 	/* end parse */
 
+	if (m_duration == 0 && !duration_from_format.empty() && m_fps > 0) {
+		warning << "using video-duration from format (container)." << endmsg;
+		m_duration = atof(duration_from_format) * m_fps;
+	}
+
 #if 0 /* DEBUG */
 	printf("FPS: %f\n", m_fps);
 	printf("Duration: %lu frames\n",(unsigned long)m_duration);
@@ -399,7 +416,7 @@ TranscodeFfmpeg::encode (std::string outfile, std::string inf_a, std::string inf
 
 	ffcmd = new ARDOUR::SystemExec(ffmpeg_exe, argp);
 	ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_v, this, _1 ,_2));
-	ffcmd->Terminated.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffexit, this));
+	ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
 	if (ffcmd->start(2)) {
 		ffexit();
 		return false;
@@ -447,7 +464,7 @@ TranscodeFfmpeg::extract_audio (std::string outfile, ARDOUR::framecnt_t /*sample
 
 	ffcmd = new ARDOUR::SystemExec(ffmpeg_exe, argp);
 	ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_a, this, _1 ,_2));
-	ffcmd->Terminated.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffexit, this));
+	ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
 	if (ffcmd->start(2)) {
 		ffexit();
 		return false;
@@ -478,7 +495,7 @@ TranscodeFfmpeg::transcode (std::string outfile, const int outw, const int outh,
 	if (bitrate < 10)  bitrate = 10;
 	if (bitrate > 1000) bitrate = 1000;
 
-	argp=(char**) calloc(15,sizeof(char*));
+	argp=(char**) calloc(16,sizeof(char*));
 	argp[0] = strdup(ffmpeg_exe.c_str());
 	argp[1] = strdup("-i");
 	argp[2] = strdup(infile.c_str());
@@ -488,17 +505,18 @@ TranscodeFfmpeg::transcode (std::string outfile, const int outw, const int outh,
 	argp[6] = (char*) calloc(10,sizeof(char)); snprintf(argp[6], 10, "%ix%i", width, height);
 	argp[7] = strdup("-y");
 	argp[8] = strdup("-vcodec");
-	argp[9] = strdup("mpeg4");
+	argp[9] = strdup("mjpeg");
 	argp[10] = strdup("-an");
-	argp[11] = strdup("-keyint_min");
-	argp[12] = strdup("10");
-	argp[13] = strdup(outfile.c_str());
-	argp[14] = (char *)0;
+	argp[11] = strdup("-intra");
+	argp[12] = strdup("-g");
+	argp[13] = strdup("1");
+	argp[14] = strdup(outfile.c_str());
+	argp[15] = (char *)0;
 	/* Note: these are free()d in ~SystemExec */
 #if 1 /* DEBUG */
 	if (debug_enable) { /* tentative debug mode */
 	printf("TRANSCODE VIDEO:\n");
-	for (int i=0; i< 14; ++i) {
+	for (int i=0; i< 15; ++i) {
 	  printf("%s ", argp[i]);
 	}
 	printf("\n");
@@ -506,7 +524,7 @@ TranscodeFfmpeg::transcode (std::string outfile, const int outw, const int outh,
 #endif
 	ffcmd = new ARDOUR::SystemExec(ffmpeg_exe, argp);
 	ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_v, this, _1 ,_2));
-	ffcmd->Terminated.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffexit, this));
+	ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
 	if (ffcmd->start(2)) {
 		ffexit();
 		return false;
diff --git a/gtk2_ardour/transcode_video_dialog.cc b/gtk2_ardour/transcode_video_dialog.cc
index ad4b46d..146ca0c 100644
--- a/gtk2_ardour/transcode_video_dialog.cc
+++ b/gtk2_ardour/transcode_video_dialog.cc
@@ -95,7 +95,6 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
 	path_hbox->pack_start (path_label, false, false, 3);
 	path_hbox->pack_start (path_entry, true, true, 3);
 	path_hbox->pack_start (browse_button, false, false, 3);
-	browse_button.set_name ("PaddedButton");
 
 	path_entry.set_width_chars(38);
 	height_spinner.set_sensitive(false);
@@ -111,7 +110,7 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
 
 	bool ffok = false;
 	if (!transcoder->ffexec_ok()) {
-		l = manage (new Label (_("No ffprobe or ffmpeg executables could be found on this system. Video Import is not possible until you install those tools. See the Log window for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
+		l = manage (new Label (_("ffmpeg installation was not found. Video Import is not possible. See the Log window for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
 		l->set_line_wrap();
 		options_box->pack_start (*l, false, true, 4);
 		aspect_checkbox.set_sensitive(false);
@@ -181,10 +180,8 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
 	l->set_use_markup ();
 	options_box->pack_start (*l, false, true, 4);
 
-	video_combo.set_name ("PaddedButton");
-
 	if (ffok) {
-		video_combo.append_text(_("Reference From Current Location (Previously Transcoded Files Only)"));
+		video_combo.append_text(_("Reference from Current Location (Previously Transcoded Files Only)"));
 		video_combo.append_text(_("Import/Transcode Video to Session"));
 		video_combo.set_active(1);
 		if (as.size() > 0) {
@@ -226,7 +223,6 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
 
 	l = manage (new Label (_("Scale Video: Width = "), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
 	t->attach (*l, 0, 1, 0, 1);
-	scale_combo.set_name ("PaddedButton");
 	t->attach (scale_combo, 1, 2, 0, 1);
 	t->attach (aspect_checkbox, 2, 3, 0, 1);
 	t->attach (height_spinner, 3, 4, 0, 1);
@@ -253,7 +249,6 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
 
 	l = manage (new Label (_("Extract Audio:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
 	t->attach (*l, 0, 1, 2, 3);
-	audio_combo.set_name ("PaddedButton");
 	t->attach (audio_combo, 1, 4, 2, 3);
 	t->attach (ltc_detect, 1, 4, 3, 4);
 	if (as.size() == 0) {
@@ -404,7 +399,7 @@ TranscodeVideoDialog::launch_transcode ()
 		return;
 	}
 	std::string outfn = path_entry.get_text();
-	if (!confirm_video_outfn(outfn, video_get_docroot(Config))) return;
+	if (!confirm_video_outfn(*this, outfn, video_get_docroot(Config))) return;
 	progress_label.set_text (_("Transcoding Video.."));
 	dialog_progress_mode();
 #if 1 /* tentative debug mode */
diff --git a/gtk2_ardour/ui_config_vars.h b/gtk2_ardour/ui_config_vars.h
index 3a46b53..2cf2855 100644
--- a/gtk2_ardour/ui_config_vars.h
+++ b/gtk2_ardour/ui_config_vars.h
@@ -25,6 +25,7 @@ UI_CONFIG_VARIABLE (bool, blink_rec_arm, "blink-rec-arm", false)
 UI_CONFIG_VARIABLE (float, waveform_gradient_depth, "waveform-gradient-depth", 0)
 UI_CONFIG_VARIABLE (float, timeline_item_gradient_depth, "timeline-item-gradient-depth", 0.5)
 UI_CONFIG_VARIABLE (bool, all_floating_windows_are_dialogs, "all-floating-windows-are-dialogs", false)
+UI_CONFIG_VARIABLE (bool, floating_monitor_section, "floating-monitor-section", false)
 UI_CONFIG_VARIABLE (bool, transients_follow_front, "transients-follow-front", false)
 UI_CONFIG_VARIABLE (bool, color_regions_using_track_color, "color-regions-using-track-color", false)
 UI_CONFIG_VARIABLE (bool, show_waveform_clipping, "show-waveform-clipping", true)
diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc
index a047708..60498b9 100644
--- a/gtk2_ardour/utils.cc
+++ b/gtk2_ardour/utils.cc
@@ -53,6 +53,7 @@
 #include "rgb_macros.h"
 #include "gui_thread.h"
 #include "ui_config.h"
+#include "ardour_dialog.h"
 
 using namespace std;
 using namespace Gtk;
@@ -926,3 +927,23 @@ ARDOUR_UI_UTILS::windows_overlap (Gtk::Window *a, Gtk::Window *b)
 	}
 	return false;
 }
+
+bool
+ARDOUR_UI_UTILS::overwrite_file_dialog (Gtk::Window& parent, string title, string text)
+{
+	ArdourDialog dialog (parent, title, true);
+	Label label (text);
+
+	dialog.get_vbox()->pack_start (label, true, true);
+	dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+	dialog.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
+	dialog.show_all ();
+
+	switch (dialog.run()) {
+	case RESPONSE_ACCEPT:
+		return true;
+	case RESPONSE_CANCEL:
+	default:
+		return false;
+	}
+}
diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h
index a7f1e16..c6df938 100644
--- a/gtk2_ardour/utils.h
+++ b/gtk2_ardour/utils.h
@@ -92,5 +92,7 @@ std::string rate_as_string (float r);
 
 bool windows_overlap (Gtk::Window *a, Gtk::Window *b);
 
+bool overwrite_file_dialog (Gtk::Window& parent, std::string title, std::string text);
+
 } // namespace
 #endif /* __ardour_gtk_utils_h__ */
diff --git a/gtk2_ardour/utils_videotl.cc b/gtk2_ardour/utils_videotl.cc
index 51cbe1a..b62ac94 100644
--- a/gtk2_ardour/utils_videotl.cc
+++ b/gtk2_ardour/utils_videotl.cc
@@ -28,6 +28,7 @@
 #include "ardour/session_directory.h"
 #include "video_image_frame.h"
 #include "utils_videotl.h"
+#include "utils.h"
 
 #ifdef WAF_BUILD
 #include "gtk2ardour-version.h"
@@ -45,7 +46,7 @@ using namespace ARDOUR;
 using namespace VideoUtils;
 
 bool
-VideoUtils::confirm_video_outfn (std::string outfn, std::string docroot)
+VideoUtils::confirm_video_outfn (Gtk::Window& parent, std::string outfn, std::string docroot)
 {
 	/* replace docroot's '/' to G_DIR_SEPARATOR for the comparison */
 	size_t look_here = 0;
@@ -67,13 +68,13 @@ VideoUtils::confirm_video_outfn (std::string outfn, std::string docroot)
 	}
 
 	if (Glib::file_test(outfn, Glib::FILE_TEST_EXISTS)) {
-		ArdourDialog confirm (_("Confirm Overwrite"), true);
-		Label m (_("A file with the same name already exists.  Do you want to overwrite it?"));
-		confirm.get_vbox()->pack_start (m, true, true);
-		confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
-		confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
-		confirm.show_all ();
-		if (confirm.run() == RESPONSE_CANCEL) { return false; }
+		bool overwrite = ARDOUR_UI_UTILS::overwrite_file_dialog (parent,
+		                                                         _("Confirm Overwrite"),
+		                                                         _("A file with the same name already exists. Do you want to overwrite it?"));
+
+		if (!overwrite) {
+			return false;
+		}
 	}
 
 	std::string dir = Glib::path_get_dirname (outfn);
diff --git a/gtk2_ardour/utils_videotl.h b/gtk2_ardour/utils_videotl.h
index 7f6f605..a7d0908 100644
--- a/gtk2_ardour/utils_videotl.h
+++ b/gtk2_ardour/utils_videotl.h
@@ -34,7 +34,7 @@
 
 namespace VideoUtils {
 
-bool confirm_video_outfn (std::string, std::string docroot="");
+bool confirm_video_outfn (Gtk::Window& parent, std::string, std::string docroot="");
 std::string video_dest_dir (const std::string, const std::string);
 std::string video_dest_file (const std::string, const std::string);
 std::string strip_file_extension (const std::string infile);
diff --git a/gtk2_ardour/video_server_dialog.cc b/gtk2_ardour/video_server_dialog.cc
index 227671a..2bd814b 100644
--- a/gtk2_ardour/video_server_dialog.cc
+++ b/gtk2_ardour/video_server_dialog.cc
@@ -74,13 +74,10 @@ VideoServerDialog::VideoServerDialog (Session* s)
 	HBox* docroot_hbox = manage (new HBox);
 
 	path_entry.set_width_chars(38);
-	path_browse_button.set_name ("PaddedButton");
 	path_entry.set_text("/usr/bin/harvid");
 	docroot_entry.set_width_chars(38);
 	docroot_entry.set_text(Config->get_video_server_docroot());
-	docroot_browse_button.set_name ("PaddedButton");
 
-	listenaddr_combo.set_name ("PaddedButton");
 #ifndef __APPLE__
 	/* Note: on OSX icsd is not able to bind to IPv4 localhost */
 	listenaddr_combo.append_text("127.0.0.1");
diff --git a/gtk2_ardour/video_timeline.cc b/gtk2_ardour/video_timeline.cc
index 12236ee..a1dd4bc 100644
--- a/gtk2_ardour/video_timeline.cc
+++ b/gtk2_ardour/video_timeline.cc
@@ -761,13 +761,14 @@ VideoTimeLine::find_xjadeo () {
 			{
 				if (v_major >= 1) v_ok = true;
 				else if (v_major == 0 && v_minor >= 8) v_ok = true;
+				else if (v_major == 0 && v_minor >= 7 && v_micro >= 7) v_ok = true;
 			}
 		}
 		if (!v_ok) {
 			_xjadeo_bin = X_("");
 			warning << _(
 					"Video-monitor 'xjadeo' is too old. "
-					"Please install xjadeo version 0.8.0 or later. http://xjadeo.sf.net/"
+					"Please install xjadeo version 0.7.7 or later. http://xjadeo.sf.net/"
 					) << endmsg;
 		}
 	}
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index 7b138f7..80ab941 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -9,6 +9,8 @@ import re
 import time
 from waflib.Task import Task
 from waflib.Tools import winres
+import subprocess
+import glob
 
 # Mandatory variables
 top = '.'
@@ -56,6 +58,7 @@ gtk2_ardour_sources = [
         'cursor_context.cc',
         'curvetest.cc',
         'debug.cc',
+        'duplicate_routes_dialog.cc',
         'edit_note_dialog.cc',
         'editing.cc',
         'editor.cc',
@@ -260,6 +263,11 @@ gtk2_ardour_sources = [
 ]
 
 def enoify (major, minor):
+    # Code names based on
+    # https://en.wikipedia.org/wiki/Brian_Eno_discography
+    #
+    # sort Studio albums + Collaborative albums + Compilation albums by Month/Year.
+    # (no Singles, no EPs, no Video Albums, no Production)
     if major == 3:
         return "\\n\\\"E-No\\\""
     elif major == 4:
@@ -277,6 +285,10 @@ def enoify (major, minor):
             return "\\n\\\"Another Green World\\\""
         elif minor == 6:
             return "\\n\\\"Evening Star\\\""
+        elif minor == 7:
+            return "\\n\\\"Cluster and Eno\\\""
+        elif minor == 8:
+            return "\\n\\\"Before and After Science\\\""
     return "\\\"\\\""
 
 def options(opt):
@@ -291,6 +303,8 @@ def configure(conf):
 
     autowaf.check_pkg(conf, 'fftw3f', uselib_store='FFTW3F',
                       mandatory=True)
+    autowaf.check_pkg(conf, 'fftw3f', uselib_store='FFTW35F',
+                      atleast_version='3.3.5', mandatory=False)
     autowaf.check_pkg(conf, 'flac', uselib_store='FLAC',
                       atleast_version='1.2.1')
     autowaf.check_pkg(conf, 'gthread-2.0', uselib_store='GTHREAD',
@@ -335,7 +349,7 @@ def _doPyp(infileName, deps = False):
     inLines = fd.readlines()
     if fd != sys.stdin:
         fd.close()
-        
+
 
     for line in inLines:
         bits = re_spaces.split(line)
@@ -417,10 +431,12 @@ def build(bld):
 
         # now the shared library containing the GTK GUI for ardour
         obj = bld (features = 'cxx c cxxshlib')
-        obj.source    = gtk2_ardour_sources
+        # operate on copy to avoid adding sources twice
+        obj.source    = list(gtk2_ardour_sources)
         obj.includes  = [ '../libs/fst', '.' ]
         obj.name      = 'libgtk2_ardour'
         obj.target    = 'gtk2_ardour'
+        obj.cflags  = [ '-fPIC' ]
 
     else:
         # just the normal executable version of the GTK GUI
@@ -428,7 +444,8 @@ def build(bld):
             obj = bld (features = 'cxx c cxxprogram winres')
         else:
             obj = bld (features = 'cxx c cxxprogram')
-        obj.source    = gtk2_ardour_sources
+        # operate on copy to avoid adding sources twice
+        obj.source    = list(gtk2_ardour_sources)
         obj.target = 'ardour-' + str (bld.env['VERSION'])
         obj.includes = ['.']
         obj.ldflags = ['-no-undefined']
@@ -457,6 +474,7 @@ def build(bld):
         'LOCALEDIR="' + os.path.normpath(bld.env['LOCALEDIR']) + '"',
         ]
     obj.install_path = bld.env['DLLDIR']
+    obj.linkflags    = ''
     obj.uselib       = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD GTK OGG CURL DL'
     obj.uselib       += ' GTKMM CANVAS FFTW3F'
     obj.uselib       += ' AUDIOUNITS OSX GTKOSX LO '
@@ -477,21 +495,24 @@ def build(bld):
     obj.use += 'libptformat'
 
     if bld.env['build_target'] == 'mingw':
-        obj.linkflags = ['-mwindows']
+        obj.linkflags += ' -mwindows'
 
     if bld.is_defined('HAVE_SUIL'):
         obj.source += [ 'lv2_plugin_ui.cc' ]
         obj.use += [ 'SUIL' ]
 
+    if bld.is_defined('HAVE_FFTW35F') and bld.env['build_target'] != 'mingw':
+        bld.env['LIB_FFTW3F'] += ['fftw3f_threads']
+
     if bld.is_defined('NEED_INTL'):
-        obj.linkflags = ' -lintl'
+        obj.linkflags += ' -lintl'
 
     if bld.is_defined('WINDOWS_VST_SUPPORT'):
         obj.source += [ 'windows_vst_plugin_ui.cc' ]
         obj.defines += [ 'WINDOWS_VST_SUPPORT' ]
         if bld.env['build_target'] != 'mingw':
             obj.use += [ 'X11' ]
-        
+
     if bld.is_defined('LXVST_SUPPORT'):
         obj.source += [ 'linux_vst_gui_support.cc', 'lxvst_plugin_ui.cc' ]
         obj.defines += [ 'LXVST_SUPPORT' ]
@@ -499,7 +520,7 @@ def build(bld):
 
     if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT'):
         obj.source += [ 'vst_plugin_ui.cc' ]
-        
+
     if bld.is_defined('PHONE_HOME'):
         obj.defines += [ 'PHONE_HOME' ]
 
@@ -570,9 +591,9 @@ def build(bld):
                 'HUGER' : '36',
                 'MASSIVE' : '60',
         }
-        
+
         # There is no acceptable monospace font available on older versions of OS X
-        # and no API on those versions to load TTF files that will work with 
+        # and no API on those versions to load TTF files that will work with
         # GTK/fontconfig/pango.
         #
         # In addition, the ArdourMono font gets clipped for some reason on OS X
@@ -612,9 +633,9 @@ def build(bld):
             else:
                 key = "_".join (['FONT',sizename])
                 fontstyle = " ".join ([basefont,points])
-                
+
             font_subst_dict[key] = fontstyle
-            
+
     # @FONT_SIZE_XXXX@
     for sizename,points in iter(font_sizes.items()):
             key = "_".join (['FONT_SIZE',sizename])
@@ -642,7 +663,7 @@ def build(bld):
     # Menus
     menus_argv = []
     if bld.is_defined('GTKOSX'):
-        menus_argv = [ '-E', '-P', '-DGTKOSX' ]
+        menus_argv = [ '-E', '-P', '-DGTKOSX', '-' ]
     else:
         menus_argv = [ '-E', '-P' ]
 
@@ -662,6 +683,36 @@ def build(bld):
         obj.stdout = program + '.menus'
         bld.install_files (bld.env['CONFDIR'], program + '.menus')
 
+    # Freedesktop
+    freedesktop_subst_dict = {
+                    'ARDOUR_EXEC' : str (bld.env['lwrcase_dirname']),
+                    'ARDOUR_ICON' : str (bld.env['lwrcase_dirname']),
+                    'VERSION': str (bld.env['VERSION']),
+    }
+
+    if bld.env['FREEDESKTOP']:
+        obj              = bld(features = 'subst')
+        obj.source       = 'ardour.desktop.in'
+        obj.target       = str (bld.env['lwrcase_dirname']) + '.desktop'
+        obj.chmod        = Utils.O644
+        obj.dict         = freedesktop_subst_dict
+        set_subst_dict(obj, freedesktop_subst_dict)
+
+        obj              = bld(features = 'subst')
+        obj.source       = 'ardour-mime-info.xml'
+        obj.target       = 'ardour.xml'
+        obj.chmod        = Utils.O644
+
+        # build appdata with translations
+        appdata_i18n_mo(bld)
+        appdata_i18n_xmlin(bld)
+        obj              = bld(features = 'subst')
+        obj.source       = 'ardour.appdata.xml.in'
+        obj.target       = str (bld.env['lwrcase_dirname']) + '.appdata.xml'
+        obj.chmod        = Utils.O644
+        obj.dict         = freedesktop_subst_dict
+        set_subst_dict(obj, freedesktop_subst_dict)
+
     # Keybindings
 
     # 'SAE-de-keypad', 'SAE-de-nokeypad', 'SAE-us-keypad',
@@ -669,7 +720,7 @@ def build(bld):
 
     #
     # explicitly state the use of perl here so that it works on windows too
-    # 
+    #
     a_rule = 'perl ../tools/fmt-bindings --platform="%s" --winkey="%s" --accelmap <${SRC} >${TGT}' % (sys.platform, bld.env['WINDOWS_KEY'] )
     for b in [ 'mnemonic-us' ] :
         obj = bld(
@@ -717,18 +768,60 @@ def i18n(bld):
         I18N_PACKAGE = 'gtk2_ardour' + bld.env['MAJOR']
         autowaf.build_i18n(bld, top, 'gtk2_ardour', I18N_PACKAGE, gtk2_ardour_sources,
                            'Paul Davis')
-        
+        appdata_i18n_pot(bld)
+        appdata_i18n_po(bld)
+
 def i18n_pot(bld):
         I18N_PACKAGE = 'gtk2_ardour' + bld.env['MAJOR']
         autowaf.build_i18n_pot(bld, top, 'gtk2_ardour', I18N_PACKAGE, gtk2_ardour_sources,
                                'Paul Davis')
+        appdata_i18n_pot(bld)
 
 def i18n_po(bld):
         I18N_PACKAGE = 'gtk2_ardour' + bld.env['MAJOR']
         autowaf.build_i18n_po(bld, top, 'gtk2_ardour', I18N_PACKAGE, gtk2_ardour_sources,
                               'Paul Davis')
-        
+        appdata_i18n_po(bld)
+
 def i18n_mo(bld):
         I18N_PACKAGE = 'gtk2_ardour' + bld.env['MAJOR']
         autowaf.build_i18n_mo(bld, top, 'gtk2_ardour', I18N_PACKAGE, gtk2_ardour_sources,
                               'Paul Davis')
+
+def appdata_i18n_pot(bld):
+    potfile = os.path.join(bld.top_dir, 'gtk2_ardour', 'appdata',
+            'ardour.appdata.pot')
+    if bld.cmd == 'build':
+        Logs.info('Generating pot file from Ardour appdata')
+        itsfile = os.path.join(bld.top_dir, 'tools', 'as-metainfo.its')
+        adsource = os.path.join(bld.top_dir, 'gtk2_ardour',
+                'ardour.appdata.xml.in.in')
+        Logs.info('Updating ' + potfile)
+        subprocess.call(('itstool', '-i', itsfile, '-o', potfile, adsource))
+    elif bld.cmd == 'clean' and os.path.exists(potfile):
+        Logs.info('Removing Ardour appdata pot file')
+        os.remove(potfile)
+
+def appdata_i18n_po(bld):
+    autowaf.build_i18n_po(bld, bld.top_dir, os.path.join(
+        'gtk2_ardour', 'appdata'), 'ardour.appdata', 'dummy', 'dummy')
+
+def appdata_i18n_mo(bld):
+    autowaf.build_i18n_mo(bld, bld.top_dir, os.path.join(
+        'gtk2_ardour', 'appdata'), 'ardour.appdata', 'dummy', 'dummy')
+
+def appdata_i18n_xmlin(bld):
+    adxmlinfile = os.path.join(bld.top_dir, 'gtk2_ardour',
+            'ardour.appdata.xml.in')
+    if bld.cmd == 'build':
+        itsfile = os.path.join(bld.top_dir, 'tools', 'as-metainfo.its')
+        adxmlininfile = os.path.join(bld.top_dir, 'gtk2_ardour',
+                'ardour.appdata.xml.in.in')
+        mo_glob = os.path.join(bld.top_dir, 'gtk2_ardour', 'appdata', 'po', '*.mo')
+        mo_files = glob.glob(mo_glob)
+        Logs.info('Generating ' + adxmlinfile)
+        subprocess.call(['itstool', '-i', itsfile, '-o', adxmlinfile,
+            '-j', adxmlininfile] + mo_files)
+    elif bld.cmd == 'clean' and os.path.exists(adxmlinfile):
+        Logs.info('Removing ' + adxmlinfile)
+        os.remove(adxmlinfile)
diff --git a/headless/wscript b/headless/wscript
index 85e2787..31a111b 100644
--- a/headless/wscript
+++ b/headless/wscript
@@ -32,7 +32,7 @@ def build(bld):
     VERSION = "%s.%s" % (bld.env['MAJOR'], bld.env['MINOR'])
     if bld.is_defined('WINDOWS_VST_SUPPORT') and bld.env['build_target'] != 'mingw':
         return
-    
+
     # just the normal executable version of the GTK GUI
     obj = bld (features = 'cxx c cxxprogram')
     # this program does not do the whole hidden symbols thing
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp
new file mode 100644
index 0000000..f1ffdf7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp
@@ -0,0 +1,580 @@
+/*
+     File: ACBaseCodec.cpp
+ Abstract: ACBaseCodec.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+#include <algorithm>
+#include "ACBaseCodec.h"
+
+#include "CABundleLocker.h"
+
+#if TARGET_OS_WIN32
+	#include "CAWin32StringResources.h"
+#endif
+
+//=============================================================================
+//	ACBaseCodec
+//=============================================================================
+
+ACBaseCodec::ACBaseCodec( AudioComponentInstance inInstance )
+:
+	ACCodec(inInstance),
+	mIsInitialized(false),
+	mInputFormatList(),
+	mInputFormat(),
+	mOutputFormatList(),
+	mOutputFormat()
+{
+	mCodecSubType = 0;
+	if (inInstance) GetSubType();
+}
+
+ACBaseCodec::~ACBaseCodec()
+{
+}
+
+void	ACBaseCodec::GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable)
+{
+	switch(inPropertyID)
+	{
+#if BUILD_ADEC_LIB
+		case kAudioCodecPropertyNameCFString:
+		case kAudioCodecPropertyFormatCFString:
+		case kAudioCodecPropertyManufacturerCFString:
+			outPropertyDataSize = 0;
+			outWritable = false;
+			break;
+#else
+		case kAudioCodecPropertyNameCFString:
+			outPropertyDataSize = SizeOf32(CFStringRef);
+			outWritable = false;
+			break;
+			
+		case kAudioCodecPropertyManufacturerCFString:
+			outPropertyDataSize = SizeOf32(CFStringRef);
+			outWritable = false;
+			break;
+			
+		case kAudioCodecPropertyFormatCFString:
+			outPropertyDataSize = SizeOf32(CFStringRef);
+			outWritable = false;
+			break;			
+#endif
+		case kAudioCodecPropertyRequiresPacketDescription:
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+			
+		case kAudioCodecPropertyMinimumNumberInputPackets :
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+			
+		case kAudioCodecPropertyMinimumNumberOutputPackets :
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+
+		case kAudioCodecPropertyCurrentInputFormat:
+			outPropertyDataSize = SizeOf32(AudioStreamBasicDescription);
+			outWritable = true;
+			break;
+			
+		case kAudioCodecPropertySupportedInputFormats:
+		case kAudioCodecPropertyInputFormatsForOutputFormat:
+			outPropertyDataSize = GetNumberSupportedInputFormats() * SizeOf32(AudioStreamBasicDescription);
+			outWritable = false;
+			break;
+			
+		case kAudioCodecPropertyCurrentOutputFormat:
+			outPropertyDataSize = SizeOf32(AudioStreamBasicDescription);
+			outWritable = true;
+			break;
+			
+		case kAudioCodecPropertySupportedOutputFormats:
+		case kAudioCodecPropertyOutputFormatsForInputFormat:
+			outPropertyDataSize = GetNumberSupportedOutputFormats() * SizeOf32(AudioStreamBasicDescription);
+			outWritable = false;
+			break;
+			
+		case kAudioCodecPropertyMagicCookie:
+			outPropertyDataSize = GetMagicCookieByteSize();
+			outWritable = true;
+			break;
+			
+		case kAudioCodecPropertyInputBufferSize:
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+			
+		case kAudioCodecPropertyUsedInputBufferSize:
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+		
+		case kAudioCodecPropertyIsInitialized:
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+
+		case kAudioCodecPropertyAvailableNumberChannels:
+			outPropertyDataSize = SizeOf32(UInt32) * 2; // Mono, stereo
+			outWritable = false;
+			break;
+			
+ 		case kAudioCodecPropertyPrimeMethod:
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+
+ 		case kAudioCodecPropertyPrimeInfo:
+			outPropertyDataSize = SizeOf32(AudioCodecPrimeInfo);
+			outWritable = false;
+			break;
+
+ 		case kAudioCodecPropertyDoesSampleRateConversion:
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = false;
+			break;
+
+		default:
+			CODEC_THROW(kAudioCodecUnknownPropertyError);
+			break;
+			
+	};
+}
+
+void	ACBaseCodec::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData)
+{
+	UInt32 thePacketsToGet;
+	
+	switch(inPropertyID)
+	{
+#if !BUILD_ADEC_LIB
+		case kAudioCodecPropertyNameCFString:
+		{
+			if (ioPropertyDataSize != SizeOf32(CFStringRef)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+			
+			CABundleLocker lock;
+			CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("unknown codec"), CFSTR("CodecNames"), GetCodecBundle(), CFSTR(""));
+			*(CFStringRef*)outPropertyData = name;
+			break; 
+		}
+		
+		case kAudioCodecPropertyManufacturerCFString:
+		{
+			if (ioPropertyDataSize != SizeOf32(CFStringRef)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+			
+			CABundleLocker lock;
+			CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("Apple, Inc."), CFSTR("CodecNames"), GetCodecBundle(), CFSTR(""));
+			*(CFStringRef*)outPropertyData = name;
+			break; 
+		}
+#else
+			// If called on the device these should return nothing but 0
+		case kAudioCodecPropertyNameCFString:
+		case kAudioCodecPropertyFormatCFString:
+		case kAudioCodecPropertyManufacturerCFString:
+			ioPropertyDataSize = 0;
+			outPropertyData = 0;
+			break;
+#endif
+        case kAudioCodecPropertyRequiresPacketDescription:
+  			if(ioPropertyDataSize == SizeOf32(UInt32))
+			{
+                *reinterpret_cast<UInt32*>(outPropertyData) = 0; 
+            }
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+            break;
+			
+		case kAudioCodecPropertyMinimumNumberInputPackets :
+			if(ioPropertyDataSize != SizeOf32(UInt32)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+			*(UInt32*)outPropertyData = 1;
+			break;
+			
+		case kAudioCodecPropertyMinimumNumberOutputPackets :
+			if(ioPropertyDataSize != SizeOf32(UInt32)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+			*(UInt32*)outPropertyData = 1;
+			break;
+			
+		case kAudioCodecPropertyCurrentInputFormat:
+			if(ioPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+			{
+				GetCurrentInputFormat(*reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData));
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+		case kAudioCodecPropertySupportedInputFormats:
+		case kAudioCodecPropertyInputFormatsForOutputFormat:
+			thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription);
+			GetSupportedInputFormats(reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData), thePacketsToGet);
+			ioPropertyDataSize = thePacketsToGet * SizeOf32(AudioStreamBasicDescription);
+			break;
+			
+		case kAudioCodecPropertyCurrentOutputFormat:
+			if(ioPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+			{
+				GetCurrentOutputFormat(*reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData));
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+		case kAudioCodecPropertySupportedOutputFormats:
+		case kAudioCodecPropertyOutputFormatsForInputFormat:
+			thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription);
+			GetSupportedOutputFormats(reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData), thePacketsToGet);
+			ioPropertyDataSize = thePacketsToGet * SizeOf32(AudioStreamBasicDescription);
+			break;
+			
+		case kAudioCodecPropertyMagicCookie:
+			if(ioPropertyDataSize >= GetMagicCookieByteSize())
+			{
+				GetMagicCookie(outPropertyData, ioPropertyDataSize);
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+		case kAudioCodecPropertyInputBufferSize:
+			if(ioPropertyDataSize == SizeOf32(UInt32))
+			{
+				*reinterpret_cast<UInt32*>(outPropertyData) = GetInputBufferByteSize();
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+		case kAudioCodecPropertyUsedInputBufferSize:
+			if(ioPropertyDataSize == SizeOf32(UInt32))
+			{
+				*reinterpret_cast<UInt32*>(outPropertyData) = GetUsedInputBufferByteSize();
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+		case kAudioCodecPropertyIsInitialized:
+			if(ioPropertyDataSize == SizeOf32(UInt32))
+			{
+				*reinterpret_cast<UInt32*>(outPropertyData) = IsInitialized() ? 1 : 0;
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+        case kAudioCodecPropertyAvailableNumberChannels:
+  			if(ioPropertyDataSize == SizeOf32(UInt32) * 2)
+			{
+				(reinterpret_cast<UInt32*>(outPropertyData))[0] = 1;
+				(reinterpret_cast<UInt32*>(outPropertyData))[1] = 2;
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+
+        case kAudioCodecPropertyPrimeMethod:
+  			if(ioPropertyDataSize == SizeOf32(UInt32))
+			{
+				*reinterpret_cast<UInt32*>(outPropertyData) = (UInt32)kAudioCodecPrimeMethod_None;
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+
+		case kAudioCodecPropertyPrimeInfo:
+  			if(ioPropertyDataSize == SizeOf32(AudioCodecPrimeInfo) )
+			{
+				(reinterpret_cast<AudioCodecPrimeInfo*>(outPropertyData))->leadingFrames = 0;
+				(reinterpret_cast<AudioCodecPrimeInfo*>(outPropertyData))->trailingFrames = 0;
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+
+        case kAudioCodecPropertyDoesSampleRateConversion:
+  			if(ioPropertyDataSize == SizeOf32(UInt32))
+			{
+				*reinterpret_cast<UInt32*>(outPropertyData) = 0;
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+
+		default:
+			CODEC_THROW(kAudioCodecUnknownPropertyError);
+			break;
+			
+	};
+}
+
+void	ACBaseCodec::SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData)
+{
+	// No property can be set when the codec is initialized
+	if(mIsInitialized)
+	{
+		CODEC_THROW(kAudioCodecIllegalOperationError);
+	}
+	
+	switch(inPropertyID)
+	{
+		case kAudioCodecPropertyCurrentInputFormat:
+			if(inPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+			{
+				SetCurrentInputFormat(*reinterpret_cast<const AudioStreamBasicDescription*>(inPropertyData));
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+		case kAudioCodecPropertyCurrentOutputFormat:
+			if(inPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+			{
+				SetCurrentOutputFormat(*reinterpret_cast<const AudioStreamBasicDescription*>(inPropertyData));
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+			
+		case kAudioCodecPropertyMagicCookie:
+			SetMagicCookie(inPropertyData, inPropertyDataSize);
+			break;
+			
+		case kAudioCodecPropertyMinimumNumberOutputPackets :
+		case kAudioCodecPropertyMinimumNumberInputPackets :
+		case kAudioCodecPropertyInputBufferSize:
+		case kAudioCodecPropertyNameCFString:
+		case kAudioCodecPropertyManufacturerCFString:
+		case kAudioCodecPropertyFormatCFString:
+		case kAudioCodecPropertySupportedInputFormats:
+		case kAudioCodecPropertySupportedOutputFormats:
+		case kAudioCodecPropertyUsedInputBufferSize:
+		case kAudioCodecPropertyIsInitialized:
+		case kAudioCodecPropertyAvailableNumberChannels:
+		case kAudioCodecPropertyPrimeMethod:
+		case kAudioCodecPropertyPrimeInfo:
+		case kAudioCodecPropertyOutputFormatsForInputFormat:
+		case kAudioCodecPropertyInputFormatsForOutputFormat:
+		case kAudioCodecPropertyDoesSampleRateConversion:
+		case kAudioCodecPropertyRequiresPacketDescription:
+			CODEC_THROW(kAudioCodecIllegalOperationError);
+			break;
+			
+		default:
+			CODEC_THROW(kAudioCodecUnknownPropertyError);
+			break;
+	};
+}
+
+void	ACBaseCodec::Initialize(const AudioStreamBasicDescription* /* inInputFormat */, const AudioStreamBasicDescription* /* inOutputFormat */, const void* /* inMagicCookie */, UInt32 /* inMagicCookieByteSize */)
+{
+	mIsInitialized = true;
+}
+
+void	ACBaseCodec::Uninitialize()
+{
+	mIsInitialized = false;
+}
+
+void	ACBaseCodec::Reset()
+{
+}
+
+UInt32	ACBaseCodec::GetNumberSupportedInputFormats() const
+{
+	return (UInt32)mInputFormatList.size();
+}
+
+void	ACBaseCodec::GetSupportedInputFormats(AudioStreamBasicDescription* outInputFormats, UInt32& ioNumberInputFormats) const
+{
+	UInt32 theNumberFormats = (UInt32)mInputFormatList.size();
+	ioNumberInputFormats = (theNumberFormats < ioNumberInputFormats) ? theNumberFormats : ioNumberInputFormats;
+	
+	FormatList::const_iterator theIterator = mInputFormatList.begin();
+	theNumberFormats = ioNumberInputFormats;
+	while((theNumberFormats > 0) && (theIterator != mInputFormatList.end()))
+	{
+		*outInputFormats = *theIterator;
+		
+		++outInputFormats;
+		--theNumberFormats;
+		std::advance(theIterator, 1);
+	}
+}
+
+void	ACBaseCodec::GetCurrentInputFormat(AudioStreamBasicDescription& outInputFormat)
+{
+	outInputFormat = mInputFormat;
+}
+
+void	ACBaseCodec::SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat)
+{
+	if(!mIsInitialized)
+	{
+		mInputFormat = inInputFormat;
+	}
+	else
+	{
+		CODEC_THROW(kAudioCodecStateError);
+	}
+}
+
+UInt32	ACBaseCodec::GetNumberSupportedOutputFormats() const
+{
+	return (UInt32)mOutputFormatList.size();
+}
+
+void	ACBaseCodec::GetSupportedOutputFormats(AudioStreamBasicDescription* outOutputFormats, UInt32& ioNumberOutputFormats) const
+{
+	UInt32 theNumberFormats = (UInt32)mOutputFormatList.size();
+	ioNumberOutputFormats = (theNumberFormats < ioNumberOutputFormats) ? theNumberFormats : ioNumberOutputFormats;
+	
+	FormatList::const_iterator theIterator = mOutputFormatList.begin();
+	theNumberFormats = ioNumberOutputFormats;
+	while((theNumberFormats > 0) && (theIterator != mOutputFormatList.end()))
+	{
+		*outOutputFormats = *theIterator;
+		
+		++outOutputFormats;
+		--theNumberFormats;
+		std::advance(theIterator, 1);
+	}
+}
+
+void	ACBaseCodec::GetCurrentOutputFormat(AudioStreamBasicDescription& outOutputFormat)
+{
+	outOutputFormat = mOutputFormat;
+}
+
+void	ACBaseCodec::SetCurrentOutputFormat(const AudioStreamBasicDescription& inOutputFormat)
+{
+	if(!mIsInitialized)
+	{
+		mOutputFormat = inOutputFormat;
+	}
+	else
+	{
+		CODEC_THROW(kAudioCodecStateError);
+	}
+}
+
+UInt32	ACBaseCodec::GetMagicCookieByteSize() const
+{
+	return 0;
+}
+
+void	ACBaseCodec::GetMagicCookie(void* /* outMagicCookieData */, UInt32& ioMagicCookieDataByteSize) const
+{
+	ioMagicCookieDataByteSize = 0;
+}
+
+void	ACBaseCodec::SetMagicCookie(const void* /* outMagicCookieData */, UInt32 /* inMagicCookieDataByteSize */)
+{
+	if(mIsInitialized)
+	{
+		CODEC_THROW(kAudioCodecStateError);
+	}
+}
+
+void	ACBaseCodec::AddInputFormat(const AudioStreamBasicDescription& inInputFormat)
+{
+	FormatList::iterator theIterator = std::find(mInputFormatList.begin(), mInputFormatList.end(), inInputFormat);
+	if(theIterator == mInputFormatList.end())
+	{
+		theIterator = std::lower_bound(mInputFormatList.begin(), mInputFormatList.end(), inInputFormat);
+		mInputFormatList.insert(theIterator, inInputFormat);
+	}
+}
+
+void	ACBaseCodec::AddOutputFormat(const AudioStreamBasicDescription& inOutputFormat)
+{
+	FormatList::iterator theIterator = std::find(mOutputFormatList.begin(), mOutputFormatList.end(), inOutputFormat);
+	if(theIterator == mOutputFormatList.end())
+	{
+		theIterator = std::lower_bound(mOutputFormatList.begin(), mOutputFormatList.end(), inOutputFormat);
+		mOutputFormatList.insert(theIterator, inOutputFormat);
+	}
+}
+
+OSType ACBaseCodec::GetSubType()
+{
+	if (!mCodecSubType)
+	{
+		AudioComponentDescription desc = GetComponentDescription();
+		mCodecSubType = desc.componentSubType;
+	}
+	return mCodecSubType;
+}
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h
new file mode 100644
index 0000000..6689d91
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h
@@ -0,0 +1,147 @@
+/*
+     File: ACBaseCodec.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__ACBaseCodec_h__)
+#define __ACBaseCodec_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "ACCodec.h"
+#include "CAStreamBasicDescription.h"
+#include <vector>
+#include "GetCodecBundle.h"
+
+//=============================================================================
+//	ACBaseCodec
+//
+//	An abstract subclass of ACCodec that implements all the nuts and bolts
+//	of the ACCodec interface, except for buffer handling. This class does
+//	the proper dispatching of property requests and manages the list of
+//	input and output formats.
+//=============================================================================
+
+class ACBaseCodec
+:
+	public ACCodec
+{
+
+//	Construction/Destruction
+public:
+									ACBaseCodec( AudioComponentInstance inInstance );
+	virtual							~ACBaseCodec();
+
+//	Property Management
+public:
+	virtual void					GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable);
+	virtual void					GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData);
+	virtual void					SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData);
+
+//	Data Handling
+public:
+	bool							IsInitialized() const { return mIsInitialized; }
+	virtual void					Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize);
+	virtual void					Uninitialize();
+	virtual void					Reset();
+	virtual UInt32					GetInputBufferByteSize() const = 0;
+	virtual UInt32					GetUsedInputBufferByteSize() const = 0;
+
+protected:
+	virtual void					ReallocateInputBuffer(UInt32 inInputBufferByteSize) = 0;
+	
+	bool							mIsInitialized;
+
+//	Format Management
+public:
+	UInt32							GetNumberSupportedInputFormats() const;
+	void							GetSupportedInputFormats(AudioStreamBasicDescription* outInputFormats, UInt32& ioNumberInputFormats) const;
+
+	void							GetCurrentInputFormat(AudioStreamBasicDescription& outInputFormat);
+	virtual void					SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat);
+	
+	UInt32							GetNumberSupportedOutputFormats() const;
+	void							GetSupportedOutputFormats(AudioStreamBasicDescription* outOutputFormats, UInt32& ioNumberOutputFormats) const;
+	
+	void							GetCurrentOutputFormat(AudioStreamBasicDescription& outOutputFormat);
+	virtual void					SetCurrentOutputFormat(const AudioStreamBasicDescription& inOutputFormat);
+	
+	virtual UInt32					GetMagicCookieByteSize() const;
+	virtual void					GetMagicCookie(void* outMagicCookieData, UInt32& ioMagicCookieDataByteSize) const;
+	virtual void					SetMagicCookie(const void* outMagicCookieData, UInt32 inMagicCookieDataByteSize);
+
+	virtual bool					ImplementsFeature(UInt32 /* feature */) const { return false; }
+	virtual void					AppendInputBufferList(const AudioBufferList * /* ioBufferList */, UInt32& /* ioNumberPackets */, const AudioStreamPacketDescription * /* inPacketDescription */, UInt32 * /* outBytesConsumed */) { CODEC_THROW(-4); /*unimpErr*/ }
+	virtual UInt32					ProduceOutputBufferList(AudioBufferList * /* ioBufferList */, UInt32& /* ioNumberPackets */,  AudioStreamPacketDescription * /* outPacketDescription */) { CODEC_THROW(-4); /*unimpErr*/ }
+protected:
+	void							AddInputFormat(const AudioStreamBasicDescription& inInputFormat);
+	void							AddOutputFormat(const AudioStreamBasicDescription& inOutputFormat);
+	
+	OSType							GetSubType();
+	
+	typedef std::vector<CAStreamBasicDescription>	FormatList;
+	
+	FormatList						mInputFormatList;
+#if TARGET_OS_WIN32
+	// VC 2005 screws up if this is not aligned to 8-byte boundaries
+	__declspec(align(8)) CAStreamBasicDescription		mInputFormat;
+#else
+	CAStreamBasicDescription		mInputFormat;
+#endif
+	
+	FormatList						mOutputFormatList;
+#if TARGET_OS_WIN32
+	// VC 2005 screws up if this is not aligned to 8-byte boundaries
+	__declspec(align(8)) CAStreamBasicDescription		mOutputFormat;
+#else
+	CAStreamBasicDescription		mOutputFormat;
+#endif
+	OSType							mCodecSubType;
+	UInt32							mPadding[3]; // Align this with 16-byte boundaries
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp
new file mode 100644
index 0000000..512f938
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp
@@ -0,0 +1,329 @@
+/*
+     File: ACCodec.cpp
+ Abstract: ACCodec.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "ACCodec.h"
+
+//=============================================================================
+//	ACCodec
+//=============================================================================
+
+ACCodec::ACCodec(AudioComponentInstance inInstance) : ComponentBase(inInstance)
+{
+}
+
+ACCodec::~ACCodec()
+{
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_IPHONE
+
+#if TARGET_OS_MAC
+	#if __LP64__
+		// comp instance, parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+		_typ _name = *(_typ *)((void*)&inParameters->params[_index + 1]);
+	#else
+		// parameters in reverse order, then comp instance
+		#define PARAM(_typ, _name, _index, _nparams) \
+		_typ _name = *(_typ *)((void*)&inParameters->params[_nparams - 1 - _index]);
+	#endif
+#elif TARGET_OS_WIN32
+	// (no comp instance), parameters in forward order
+	#define PARAM(_typ, _name, _index, _nparams) \
+	_typ _name = *(_typ *)&inParameters->params[_index];
+#endif
+
+OSStatus	ACCodec::ComponentEntryDispatch(ComponentParameters *inParameters, ACCodec *inThis)
+{
+	OSStatus		theError = kAudioCodecNoError;
+	
+	try
+	{
+		switch (inParameters->what)
+		{
+				//	these selectors don't use the object pointer
+				
+			case kComponentOpenSelect:
+			case kComponentCloseSelect:
+				theError = ComponentBase::ComponentEntryDispatch(inParameters, inThis);
+				break;
+				
+			case kComponentCanDoSelect:
+			{
+				switch (GetSelectorForCanDo(inParameters))
+				{
+					case kAudioCodecGetPropertyInfoSelect:
+					case kAudioCodecGetPropertySelect:
+					case kAudioCodecSetPropertySelect:
+					case kAudioCodecInitializeSelect:
+					case kAudioCodecUninitializeSelect: // was missing -- why?
+					case kAudioCodecAppendInputDataSelect:
+					case kAudioCodecProduceOutputDataSelect:
+					case kAudioCodecResetSelect:
+						theError = 1;
+						break;
+					default:
+						theError = ComponentBase::ComponentEntryDispatch(inParameters, inThis);
+						break;
+				}
+			}
+			break;
+				
+			default:
+				//	these selectors use the object pointer
+				if(inThis != NULL)
+				{
+					switch (inParameters->what)
+					{
+						case kComponentVersionSelect:
+							theError = inThis->Version();
+							break;
+							
+						case kAudioCodecGetPropertyInfoSelect:
+						{
+							PARAM(AudioCodecPropertyID, inPropertyID, 0, 3);
+							PARAM(UInt32 *, outSize, 1, 3);
+							PARAM(Boolean *, outWritable, 2, 3);
+							
+							UInt32 theSize = 0;
+							Boolean isWritable = false;
+							
+							inThis->GetPropertyInfo(inPropertyID, theSize, isWritable);
+							if(outSize != NULL)
+							{
+								*outSize = theSize;
+							}
+							if(outWritable != NULL)
+							{
+								*outWritable = isWritable ? 1 : 0;
+							}
+						}
+							break;
+							
+						case kAudioCodecGetPropertySelect:
+						{
+							PARAM(AudioCodecPropertyID, inPropertyID, 0, 3);
+							PARAM(UInt32 *, ioPropertyDataSize, 1, 3);
+							PARAM(void *, outPropertyData, 2, 3);
+							
+							if((ioPropertyDataSize != NULL) && (outPropertyData != NULL))
+							{
+								inThis->GetProperty(inPropertyID, *ioPropertyDataSize, outPropertyData);
+							}
+							else
+							{
+								theError = kAudio_ParamError;
+							}
+						}
+							break;
+							
+						case kAudioCodecSetPropertySelect:
+						{
+							PARAM(AudioCodecPropertyID, inPropertyID, 0, 3);
+							PARAM(UInt32, inPropertyDataSize, 1, 3);
+							PARAM(const void *, inPropertyData, 2, 3);
+							
+							if(inPropertyData != NULL)
+							{
+								inThis->SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+							}
+							else
+							{
+								theError = kAudio_ParamError;
+							}
+						}
+							break;
+							
+						case kAudioCodecInitializeSelect:
+						{
+							PARAM(const AudioStreamBasicDescription *, inInputFormat, 0, 4);
+							PARAM(const AudioStreamBasicDescription *, inOutputFormat, 1, 4);
+							PARAM(const void *, inMagicCookie, 2, 4);
+							PARAM(UInt32, inMagicCookieByteSize, 3, 4);
+							
+							inThis->Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
+						}
+							break;
+							
+						case kAudioCodecUninitializeSelect:
+						{
+							inThis->Uninitialize();
+						}
+							break;
+							
+						case kAudioCodecAppendInputDataSelect:
+						{
+							PARAM(const void *, inInputData, 0, 4);
+							PARAM(UInt32 *, ioInputDataByteSize, 1, 4);
+							PARAM(UInt32 *, ioNumberPackets, 2, 4);
+							PARAM(const AudioStreamPacketDescription *, inPacketDescription, 3, 4);
+							
+							if((inInputData != NULL) && (ioInputDataByteSize != NULL))
+							{
+								if(ioNumberPackets != NULL)
+								{
+									inThis->AppendInputData(inInputData, *ioInputDataByteSize, *ioNumberPackets, inPacketDescription);
+								}
+								else
+								{
+									UInt32 theNumberPackets = 0;
+									inThis->AppendInputData(inInputData, *ioInputDataByteSize, theNumberPackets, inPacketDescription);
+								}
+							}
+							else
+							{
+								theError = kAudio_ParamError;
+							}
+						}
+							break;
+							
+						case kAudioCodecProduceOutputDataSelect:
+						{
+							PARAM(void *, outOutputData, 0, 5);
+							PARAM(UInt32 *, ioOutputDataByteSize, 1, 5);
+							PARAM(UInt32 *, ioNumberPackets, 2, 5);
+							PARAM(AudioStreamPacketDescription *, outPacketDescription, 3, 5);
+							PARAM(UInt32 *, outStatus, 4, 5);
+							
+							if((outOutputData != NULL) && (ioOutputDataByteSize != NULL) && (ioNumberPackets != NULL) && (outStatus != NULL))
+							{
+								*outStatus = inThis->ProduceOutputPackets(outOutputData, *ioOutputDataByteSize, *ioNumberPackets, outPacketDescription);
+								if(kAudioCodecProduceOutputPacketFailure == *outStatus)
+								{
+									theError = kAudio_ParamError;
+								}
+							}
+							else
+							{
+								theError = kAudio_ParamError;
+							}
+						}
+							break;
+							
+#if AC_NON_INTERLEAVED_SUPPORT
+						case kAudioCodecAppendInputBufferListSelect:
+						{
+							PARAM(const AudioBufferList *, inBufferList, 0, 4);
+							PARAM(UInt32 *, ioNumberPackets, 1, 4);
+							PARAM(const AudioStreamPacketDescription *, inPacketDescription, 2, 4);
+							PARAM(UInt32 *, outBytesConsumed, 3, 4);
+							
+							if((inBufferList != NULL) && (outBytesConsumed != NULL))
+							{
+								if(ioNumberPackets != NULL)
+								{
+									inThis->AppendInputBufferList(inBufferList, *ioNumberPackets, inPacketDescription, outBytesConsumed);
+								}
+								else
+								{
+									UInt32 theNumberPackets = 0;
+									inThis->AppendInputBufferList(inBufferList, theNumberPackets, inPacketDescription, outBytesConsumed);
+								}
+							}
+							else
+							{
+								theError = kAudio_ParamError;
+							}
+						}
+							break;
+							
+						case kAudioCodecProduceOutputBufferListSelect:
+						{
+							PARAM(AudioBufferList *, ioBufferList, 0, 4);
+							PARAM(UInt32 *, ioNumberPackets, 1, 4);
+							PARAM(AudioStreamPacketDescription *, outPacketDescription, 2, 4);
+							PARAM(UInt32 *, outStatus, 3, 4);
+							
+							if((ioBufferList != NULL) && (ioNumberPackets != NULL) && (outStatus != NULL))
+							{
+								*outStatus = inThis->ProduceOutputBufferList(ioBufferList, *ioNumberPackets, outPacketDescription);
+								if(kAudioCodecProduceOutputPacketFailure == *outStatus)
+								{
+									theError = kAudio_ParamError;
+								}
+							}
+							else
+							{
+								theError = kAudio_ParamError;
+							}
+						}
+							break;
+#endif	// AC_NON_INTERLEAVED_SUPPORT
+							
+						case kAudioCodecResetSelect:
+						{
+							inThis->Reset();
+						}
+							break;
+							
+						default:
+							theError = badComponentSelector;
+							break;
+					};
+				}
+				else
+				{
+					theError = kAudio_ParamError;
+				}
+				break;
+		};
+	}
+	catch(OSStatus inErrorCode)
+	{
+		theError = inErrorCode;
+	}
+	catch(...)
+	{
+		theError = kAudioCodecUnspecifiedError;
+	}
+	
+	return theError;
+}
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_IPHONE
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h
new file mode 100644
index 0000000..b0d9316
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h
@@ -0,0 +1,115 @@
+/*
+     File: ACCodec.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__ACCodec_h__)
+#define __ACCodec_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioCodec.h>
+#else
+	#include "AudioCodec.h"
+#endif
+
+#include "ComponentBase.h"
+
+//=============================================================================
+//	ACCodec
+//
+//	A totally abstract base class for implementing components that conform to
+//	the AudioCodec API.
+//=============================================================================
+
+class ACCodec : public ComponentBase
+{
+
+//	Construction/Destruction
+public:
+					ACCodec(AudioComponentInstance inInstance);
+	virtual			~ACCodec();
+	
+#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_IPHONE
+	static		OSStatus ComponentEntryDispatch(ComponentParameters *p, ACCodec *This);
+#endif
+
+//	Property Management
+public:
+	virtual void	GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outSize, Boolean& outWritable) = 0;
+	virtual void	GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData) = 0;
+	virtual void	SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData) = 0;
+
+//	Data Handling
+public:
+	virtual void	Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize) = 0;
+	virtual void	Uninitialize() = 0;
+	virtual void	Reset() = 0;
+	
+	virtual void	AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription) = 0;
+	virtual void	AppendInputBufferList(const AudioBufferList *ioBufferList, UInt32& ioNumberPackets, const AudioStreamPacketDescription *inPacketDescription, UInt32 *outBytesConsumed) = 0;
+	
+	virtual UInt32	ProduceOutputPackets(void* outOutputData, UInt32& ioOutputDataByteSize, UInt32& ioNumberPackets, AudioStreamPacketDescription* outPacketDescription) = 0;
+	virtual UInt32	ProduceOutputBufferList(AudioBufferList *ioBufferList, UInt32& ioNumberPackets,  AudioStreamPacketDescription *outPacketDescription) = 0;
+
+//	Component Support
+public:
+// used internally
+	virtual bool	ImplementsFeature(UInt32 feature) const = 0;
+};
+
+// when throwing static_cast to OSStatus so the catch will grab the error code correctly
+#define CODEC_THROW(err) \
+	throw static_cast<OSStatus>(err)
+
+#define CODEC_THROW_IF(cond, err) \
+	if(bool(cond)) CODEC_THROW(err);
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h
new file mode 100644
index 0000000..42c2bc5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h
@@ -0,0 +1,259 @@
+/*
+     File: ACCodecDispatchTypes.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__ACCodecDispatchTypes_h__)
+#define __ACCodecDispatchTypes_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	note that AudioCodec.h needs to be included prior to including this file
+#if !defined(__AudioCodec_h__)
+	#error	AudioCodec.h needs to be included prior to including this file
+#endif
+
+//=============================================================================
+//	Parameter Blocks for AudioCodec Component Routines
+//
+//	Note that the arguments for all the AudioCodec component routines are
+//	4 bytes in size (assuming pointers are 4 bytes). This means that even on
+//	Windows (where all arguments are forced into SInt32s), we can get away with
+//	mass casting the argument list through the appropriate paramblock structure.
+//	This gets around the fact that the component glue passes the arguments in
+//	a different order depending on the platform and therefore makes writing the
+//	 calling glue and the dispatcher much simpler.
+//=============================================================================
+
+#if PRAGMA_STRUCT_ALIGN
+	#pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+	#pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+	#pragma pack(2)
+#endif
+
+#define	AudioCodecStandardGluePBFields	UInt8 componentFlags; UInt8 componentParamSize; SInt16 componentWhat
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecOpenGluePB {
+	AudioCodecStandardGluePBFields;
+	AudioCodec						inCodec;
+	void*							unused;
+};
+#else
+struct AudioCodecOpenGluePB {
+	AudioCodecStandardGluePBFields;
+	AudioCodec						inCodec;
+};
+#endif
+typedef struct AudioCodecOpenGluePB	AudioCodecOpenGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecGetPropertyInfoGluePB
+{
+	AudioCodecStandardGluePBFields;
+	Boolean*						outWritable;
+	UInt32*							outSize;
+	AudioCodecPropertyID			inPropertyID;
+	AudioCodec						inCodec;
+};
+#else
+struct AudioCodecGetPropertyInfoGluePB
+{
+	AudioCodecStandardGluePBFields;
+	AudioCodecPropertyID			inPropertyID;
+	UInt32*							outSize;
+	Boolean*						outWritable;
+};
+#endif
+typedef struct AudioCodecGetPropertyInfoGluePB	AudioCodecGetPropertyInfoGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecGetPropertyGluePB
+{
+	AudioCodecStandardGluePBFields;
+	void*							outPropertyData;
+	UInt32*							ioPropertyDataSize;
+	AudioCodecPropertyID			inPropertyID;
+	AudioCodec						inCodec;
+};
+#else
+struct AudioCodecGetPropertyGluePB
+{
+	AudioCodecStandardGluePBFields;
+	AudioCodecPropertyID			inPropertyID;
+	UInt32*							ioPropertyDataSize;
+	void*							outPropertyData;
+};
+#endif
+typedef struct AudioCodecGetPropertyGluePB	AudioCodecGetPropertyGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecSetPropertyGluePB
+{
+	AudioCodecStandardGluePBFields;
+	const void*						inPropertyData;
+	UInt32							inPropertyDataSize;
+	AudioCodecPropertyID			inPropertyID;
+	AudioCodec						inCodec;
+};
+#else
+struct AudioCodecSetPropertyGluePB
+{
+	AudioCodecStandardGluePBFields;
+	AudioCodecPropertyID			inPropertyID;
+	UInt32							inPropertyDataSize;
+	const void*						inPropertyData;
+};
+#endif
+typedef struct AudioCodecSetPropertyGluePB	AudioCodecSetPropertyGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecInitializeGluePB
+{
+	AudioCodecStandardGluePBFields;
+	UInt32								inMagicCookieByteSize;
+	const void*							inMagicCookie;
+	const AudioStreamBasicDescription*	inOutputFormat;
+	const AudioStreamBasicDescription*	inInputFormat;
+	AudioCodec							inCodec;
+};
+#else
+struct AudioCodecInitializeGluePB
+{
+	AudioCodecStandardGluePBFields;
+	const AudioStreamBasicDescription*	inInputFormat;
+	const AudioStreamBasicDescription*	inOutputFormat;
+	const void*							inMagicCookie;
+	UInt32								inMagicCookieByteSize;
+};
+#endif
+typedef struct AudioCodecInitializeGluePB	AudioCodecInitializeGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecUninitializeGluePB
+{
+	AudioCodecStandardGluePBFields;
+	AudioCodec						inCodec;
+};
+#else
+struct AudioCodecUninitializeGluePB
+{
+	AudioCodecStandardGluePBFields;
+};
+#endif
+typedef struct AudioCodecUninitializeGluePB	AudioCodecUninitializeGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecAppendInputDataGluePB
+{
+	AudioCodecStandardGluePBFields;
+	const AudioStreamPacketDescription*	inPacketDescription;
+	UInt32*								ioNumberPackets;
+	UInt32*								ioInputDataByteSize;
+	const void*							inInputData;
+	AudioCodec							inCodec;
+};
+#else
+struct AudioCodecAppendInputDataGluePB
+{
+	AudioCodecStandardGluePBFields;
+	const void*							inInputData;
+	UInt32*								ioInputDataByteSize;
+	UInt32*								ioNumberPackets;
+	const AudioStreamPacketDescription*	inPacketDescription;
+};
+#endif
+typedef struct AudioCodecAppendInputDataGluePB	AudioCodecAppendInputDataGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecProduceOutputPacketsGluePB
+{
+	AudioCodecStandardGluePBFields;
+	UInt32*							outStatus;
+	AudioStreamPacketDescription*	outPacketDescription;
+	UInt32*							ioNumberPackets;
+	UInt32*							ioOutputDataByteSize;
+	void*							outOutputData;
+	AudioCodec						inCodec;
+};
+#else
+struct AudioCodecProduceOutputPacketsGluePB
+{
+	AudioCodecStandardGluePBFields;
+	void*							outOutputData;
+	UInt32*							ioOutputDataByteSize;
+	UInt32*							ioNumberPackets;
+	AudioStreamPacketDescription*	outPacketDescription;
+	UInt32*							outStatus;
+};
+#endif
+typedef struct AudioCodecProduceOutputPacketsGluePB	AudioCodecProduceOutputPacketsGluePB;
+
+#if	!TARGET_OS_WIN32
+struct AudioCodecResetGluePB
+{
+	AudioCodecStandardGluePBFields;
+	AudioCodec						inCodec;
+};
+#else
+struct AudioCodecResetGluePB
+{
+	AudioCodecStandardGluePBFields;
+};
+#endif
+typedef struct AudioCodecResetGluePB	AudioCodecResetGluePB;
+
+#if PRAGMA_STRUCT_ALIGN
+	#pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+	#pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+	#pragma pack()
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r
new file mode 100644
index 0000000..a84fd11
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r
@@ -0,0 +1,196 @@
+/*
+     File: ACComponentResources.r
+ Abstract: ACComponentResources.r
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef GEN_MISSING
+	#define GEN_MISSING 0
+#endif
+
+#ifndef thng_RezTemplateVersion
+	#define thng_RezTemplateVersion	2
+#endif
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "ConditionalMacros.r"
+#include "MacTypes.r"
+#include "Components.r"
+
+//=============================================================================
+//	Platform constants for the thng resources
+//=============================================================================
+
+#if	TARGET_OS_MAC && TARGET_API_MAC_OSX
+	#define Target_PlatformType		1000
+	#define Target_CodeResType		'dlle'
+	#define kUseDLLEResource		1
+#elif TARGET_OS_WIN32
+	#define Target_PlatformType      platformWin32
+	#define Target_CodeResType		'dlle'
+	#define kUseDLLEResource		1
+#else
+	#define Target_PlatformType		platformPowerPC
+	#define Target_CodeResType		'tppc'
+	#define kUseDLLEResource		0
+#endif
+
+#if kComponentIsThreadSafe
+	#ifndef cmpThreadSafeOnMac	// so we don't need Panther headers to build
+		#define cmpThreadSafeOnMac	0x10000000
+	#endif
+	#define COMPONENT_FLAGS		cmpThreadSafeOnMac
+#else
+	#define COMPONENT_FLAGS		0
+#endif
+
+//=============================================================================
+//	The thng and related resources
+//
+//	The definitions below use the following macros, all of which must be
+//	defined. Note that kPrimaryResourceID is used to define two 'STR '
+//	resources with consecutive IDs so be sure to space them at least two'
+//	apart. Here's a sample of how to do the defines:
+//	
+//	#define kPrimaryResourceID				128
+//	#define kComponentType					'aenc'
+//	#define kComponentSubtype				'ima4'
+//	#define kComponentManufacturer			'appl'
+//	#define	kComponentFlags					0
+//	#define kComponentVersion				0x00010000
+//	#define kComponentName					"Apple IMA4 Encoder"
+//	#define kComponentInfo					"An AudioCodec that encodes linear PCM data into IMA4"
+//	#define kComponentEntryPoint			"ACAppleIMA4EncoderEntry"
+//	#define	kComponentPublicResourceMapType	0
+//	#define kComponentIsThreadSafe			1
+//=============================================================================
+
+#ifndef AC_LOCALIZED
+resource 'strn' (kPrimaryResourceID, purgeable)
+{
+	kComponentName
+};
+
+resource 'stri' (kPrimaryResourceID, purgeable)
+{
+	kComponentInfo
+};
+#endif
+
+#if !GEN_MISSING
+
+#if kUseDLLEResource
+
+	resource 'dlle' (kPrimaryResourceID)
+	{
+		kComponentEntryPoint
+	};
+
+#endif
+
+#define kComponentRegistrationFlags	componentHasMultiplePlatforms | componentDoAutoVersion | componentLoadResident
+resource 'thng' (kPrimaryResourceID, kComponentName)
+{
+	kComponentType,											//	Component type
+	kComponentSubtype,										//	Component subtype
+	kComponentManufacturer,									//	Component manufacturer
+	kComponentFlags,										//	Component flags
+	0,														//	Component flags mask
+	0, 0,													//	Code type, Code ID
+	'strn',	kPrimaryResourceID,								//	Name resource type, resource ID
+	'stri',	kPrimaryResourceID,								//	Info resource type, resource ID
+	0, 0,													//	Icon resource type, resource ID
+	kComponentVersion,										//	Component version
+	kComponentRegistrationFlags,							//	Registration flags
+	0,														//	Icon family resource ID
+	{														//	Beginning of platform info
+		COMPONENT_FLAGS,									//	Component flags
+		Target_CodeResType, kPrimaryResourceID,				//	Code resource type, resource ID
+		Target_PlatformType,								//	Platform type
+	},
+#if thng_RezTemplateVersion >= 2
+	kComponentPublicResourceMapType, kPrimaryResourceID		//	Resource map type, resource map ID
+#endif	
+};
+
+#else	//	GEN_MISSING
+
+resource 'thga' (kPrimaryResourceID) {
+	kComponentType,											//	Component type
+	kComponentSubtype,										//	Component subtype
+	kComponentManufacturer,									//	Component manufacturer
+	kComponentFlags,										//	Component flags
+	0,														//	Component flags mask
+	0, 0,													//	Code type, Code ID
+	'strn',	kPrimaryResourceID,								//	Name resource type, resource ID
+	'stri',	kPrimaryResourceID,								//	Info resource type, resource ID
+	0, 0,													//	Icon resource type, resource ID
+	'miss',													//	Alias component type
+	'base',													//	Alias component subtype
+	0,														//	Alias component manufacturer
+	0,														//	Alias component flags
+	0,														//	Alias component flags mask
+#if thng_RezTemplateVersion >= 2
+	kComponentPublicResourceMapType, kPrimaryResourceID,	//	Resource map type, resource map ID
+	cmpAliasNoFlags											//	Alias flags	
+#endif
+};
+
+#endif	//	GEN_MISSING
+
+#undef kPrimaryResourceID
+#undef kComponentType
+#undef kComponentSubtype
+#undef kComponentManufacturer
+#undef kComponentVersion
+#undef kComponentRegistrationFlags
+#undef kComponentName
+#undef kComponentInfo
+#undef kComponentEntryPoint
+#undef kComponentPublicResourceMapType
+#undef Target_PlatformType
+#undef Target_CodeResType
+#undef kUseDLLEResource
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h
new file mode 100644
index 0000000..2cff483
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h
@@ -0,0 +1,73 @@
+/*
+     File: ACConditionalMacros.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__ACConditionalMacros_h__)
+#define __ACConditionalMacros_h__
+
+//=============================================================================
+//	This file exists to make figuring out how to include system headers
+//	easier. We throw in an include of the standard ConditionalMacros too.
+//=============================================================================
+
+//	TargetConditionals.h defines the bare minimum we need
+#include "TargetConditionals.h"
+
+//	Determine whether or not to use framework style includes for system headers
+#if !defined(AC_Use_Framework_Includes)
+	#if	TARGET_OS_MAC && TARGET_RT_MAC_MACHO
+		#define	AC_Use_Framework_Includes	1
+	#else
+		#define	AC_Use_Framework_Includes	0
+	#endif
+#endif
+
+#if	AC_Use_Framework_Includes
+	#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/ConditionalMacros.h>
+#else
+	#include "ConditionalMacros.h"
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp
new file mode 100644
index 0000000..de9599b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp
@@ -0,0 +1,283 @@
+/*
+     File: ACPlugInDispatch.cpp
+ Abstract: ACPlugInDispatch.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if AUDIOCODECS_SUPPORT_PLUGINS
+#include "ACPlugInDispatch.h"
+#include "CAXException.h"
+#include "ACCodec.h"
+#include <new>
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define ACC	((ACCodec *)&ACPI->mInstanceStorage)
+
+static OSStatus	GetPropertyInfo(void *self, AudioCodecPropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable)
+{
+	OSStatus result = noErr;
+	try {
+		UInt32 size;
+		Boolean writable;
+		ACC->GetPropertyInfo(inPropertyID, size, writable);
+		if (outSize) *outSize = size;
+		if (outWritable) *outWritable = writable;
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus	GetProperty(void *self, AudioCodecPropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData)
+{
+	OSStatus result = noErr;
+	try {
+		ACC->GetProperty(inPropertyID, *ioPropertyDataSize, outPropertyData);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus	SetProperty(void *self, AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData)
+{
+	OSStatus result = noErr;
+	try {
+		ACC->SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+
+static OSStatus Initialize(void *self, const AudioStreamBasicDescription *inInputFormat, const AudioStreamBasicDescription *inOutputFormat, const void *inMagicCookie, UInt32 inMagicCookieByteSize)
+{
+	OSStatus result = noErr;
+	try {
+		ACC->Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus Uninitialize(void *self)
+{
+	OSStatus result = noErr;
+	try {
+		ACC->Uninitialize();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus	AppendInputData(void *self, const void *inInputData, UInt32 *ioInputDataByteSize, UInt32 *ioNumberPackets, const AudioStreamPacketDescription *inPacketDescription)
+{
+	OSStatus result = noErr;
+	try {
+		UInt32 npackets = (ioNumberPackets != NULL) ? *ioNumberPackets : 0;
+		ACC->AppendInputData(inInputData, *ioInputDataByteSize, npackets, inPacketDescription);
+        if(ioNumberPackets != NULL)
+            *ioNumberPackets = npackets;
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus	ProduceOutputPackets(void *self, void *outOutputData, UInt32 *ioOutputDataByteSize, UInt32 *ioNumberPackets, AudioStreamPacketDescription *outPacketDescription, UInt32 *outStatus)
+{
+	OSStatus result = noErr;
+	try {
+		*outStatus = ACC->ProduceOutputPackets(outOutputData, *ioOutputDataByteSize, *ioNumberPackets, outPacketDescription);
+		if (*outStatus == kAudioCodecProduceOutputPacketFailure)
+			result = kAudio_ParamError;
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus	Reset(void *self)
+{
+	OSStatus result = noErr;
+	try {
+		ACC->Reset();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+#if AC_NON_INTERLEAVED_SUPPORT
+static OSStatus AppendInputBufferList(void *self, const AudioBufferList *ioBufferList, UInt32 *inNumberPackets, const AudioStreamPacketDescription *inPacketDescription, UInt32 *outBytesConsumed)
+{
+	OSStatus result = noErr;
+	try {
+		if((ioBufferList != NULL) && (outBytesConsumed != NULL))
+		{
+			if(inNumberPackets != NULL)
+			{
+				ACC->AppendInputBufferList(ioBufferList, *inNumberPackets, inPacketDescription, outBytesConsumed);
+			}
+			else
+			{
+				UInt32 theNumberPackets = 0;
+				ACC->AppendInputBufferList(ioBufferList, theNumberPackets, inPacketDescription, outBytesConsumed);
+			}
+		}
+		else
+		{
+			result = kAudio_ParamError;
+		}
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus ProduceOutputBufferList(void *self, AudioBufferList *ioBufferList, UInt32 *ioNumberPackets, AudioStreamPacketDescription *outPacketDescription, UInt32 *outStatus)
+{
+	OSStatus result = noErr;
+	try {
+		if((ioBufferList != NULL) && (ioNumberPackets != NULL) && (outStatus != NULL))
+		{
+			*outStatus = ACC->ProduceOutputBufferList(ioBufferList, *ioNumberPackets, outPacketDescription);
+			if(kAudioCodecProduceOutputPacketFailure == *outStatus)
+			{
+				result = kAudio_ParamError;
+			}
+		}
+		else
+		{
+			result = kAudio_ParamError;
+		}
+	}
+	COMPONENT_CATCH
+	return result;
+}
+#endif
+
+#if TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+// The ACTransformerCodecBase class is the base for ALL hardware codecs.
+// No need to check for ImplementFeature...
+#include "ACTransformerManager.h"
+#define ACTM	((ACTransformerCodecBase*)&ACPI->mInstanceStorage)
+
+static OSStatus	AcquireHardware(void *self)
+{
+	OSStatus result = noErr;
+	try {
+        ACTM->AcquireHardware();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus	ReleaseHardware(void *self)
+{
+	OSStatus result = noErr;
+	try {
+        ACTM->ReleaseHardware();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+#endif // TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+
+
+AudioComponentMethod AudioCodecLookup::Lookup (SInt16 selector)
+{
+	switch (selector) {
+		case kAudioCodecGetPropertyInfoSelect:			return (AudioComponentMethod)GetPropertyInfo;
+		case kAudioCodecGetPropertySelect:				return (AudioComponentMethod)GetProperty;
+		case kAudioCodecSetPropertySelect:				return (AudioComponentMethod)SetProperty;
+		case kAudioCodecInitializeSelect:				return (AudioComponentMethod)Initialize;
+		case kAudioCodecUninitializeSelect:				return (AudioComponentMethod)Uninitialize;
+		case kAudioCodecAppendInputDataSelect:			return (AudioComponentMethod)AppendInputData;
+		case kAudioCodecProduceOutputDataSelect:		return (AudioComponentMethod)ProduceOutputPackets;
+		case kAudioCodecResetSelect:					return (AudioComponentMethod)Reset;
+		default:
+			break;
+	}
+	return NULL;
+}
+
+#if AC_NON_INTERLEAVED_SUPPORT
+AudioComponentMethod AudioCodecNonInterleavedEncoderLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AudioCodecLookup::Lookup(selector);
+	if (method)
+		return method;
+	
+	if (selector == kAudioCodecAppendInputBufferListSelect)
+		return (AudioComponentMethod)AppendInputBufferList;
+	
+	return NULL;
+}
+
+AudioComponentMethod AudioCodecNonInterleavedDecoderLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AudioCodecLookup::Lookup(selector);
+	if (method)
+		return method;
+	
+	if (selector == kAudioCodecProduceOutputBufferListSelect)
+		return (AudioComponentMethod)ProduceOutputBufferList;
+	
+	return NULL;
+}
+#endif
+
+#if TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+#include "AudioCodecPriv.h"
+
+AudioComponentMethod AudioCodecHWCodecLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AudioCodecLookup::Lookup(selector);
+	if (method) return method;
+	
+	switch (selector) {
+		case kAudioCodecAcquireHardwareSelect:			return (AudioComponentMethod)AcquireHardware;
+		case kAudioCodecReleaseHardwareSelect:			return (AudioComponentMethod)ReleaseHardware;
+		default:
+			break;
+	}
+	return NULL;	
+}
+#endif // TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+
+#endif // AUDIOCODECS_SUPPORT_PLUGINS
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h
new file mode 100644
index 0000000..252a4af
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h
@@ -0,0 +1,88 @@
+/*
+     File: ACPlugInDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __ACPlugInDispatch_h__
+#define __ACPlugInDispatch_h__
+
+#include "ComponentBase.h"
+
+struct AudioCodecLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecFactory : public APFactory<AudioCodecLookup, Implementor>
+{
+};
+
+#if AC_NON_INTERLEAVED_SUPPORT
+struct AudioCodecNonInterleavedEncoderLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecNonInterleavedEncoderFactory : public APFactory<AudioCodecNonInterleavedEncoderLookup, Implementor>
+{
+};
+
+struct AudioCodecNonInterleavedDecoderLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecNonInterleavedDecoderFactory : public APFactory<AudioCodecNonInterleavedDecoderLookup, Implementor>
+{
+};
+#endif
+
+#if TARGET_OS_IPHONE
+struct AudioCodecHWCodecLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecHWCodecFactory : public APFactory<AudioCodecHWCodecLookup, Implementor>
+{
+};
+#endif // TARGET_OS_IPHONE
+
+#endif // __ACPlugInDispatch_h__
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp
new file mode 100644
index 0000000..b10add9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp
@@ -0,0 +1,364 @@
+/*
+     File: ACSimpleCodec.cpp
+ Abstract: ACSimpleCodec.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "ACSimpleCodec.h"
+#include <string.h>
+
+//=============================================================================
+//	ACSimpleCodec
+//=============================================================================
+
+static const UInt32 kBufferPad = 64; // this is used to prevent end from passing start.
+
+ACSimpleCodec::ACSimpleCodec(UInt32 inInputBufferByteSize, AudioComponentInstance inInstance)
+:
+	ACBaseCodec(inInstance),
+	mInputBuffer(NULL),
+	mInputBufferByteSize(inInputBufferByteSize+kBufferPad),
+	mInputBufferStart(0),
+	mInputBufferEnd(0)
+{
+}
+
+ACSimpleCodec::~ACSimpleCodec()
+{
+	delete[] mInputBuffer;
+}
+
+void	ACSimpleCodec::Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize)
+{
+	ReallocateInputBuffer(mInputBufferByteSize - kBufferPad);
+
+	// By definition CBR has this greater than 0. We must avoid a div by 0 error in AppendInputData()
+	// Note this will cause us to fail initialization which is intended
+	if (mInputFormat.mBytesPerPacket == 0)
+	{
+		CODEC_THROW(kAudioCodecUnsupportedFormatError);
+	}	
+	
+	ACBaseCodec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
+}
+
+void	ACSimpleCodec::Uninitialize()
+{
+	//	get rid of the buffer
+	delete[] mInputBuffer;
+	mInputBuffer = NULL;
+	
+	//	reset the ring buffer state
+	mInputBufferStart = 0;
+	mInputBufferEnd = 0;
+	
+	ACBaseCodec::Uninitialize();
+}
+
+void	ACSimpleCodec::Reset()
+{
+	//	clear the entire input buffer
+	if (mInputBuffer) { // could be called before allocated.
+		memset(mInputBuffer, 0, mInputBufferByteSize);
+	}
+	
+	//	reset the ring buffer state
+	mInputBufferStart = 0;
+	mInputBufferEnd = 0;
+	
+	ACBaseCodec::Reset();
+}
+
+UInt32	ACSimpleCodec::GetInputBufferByteSize() const
+{
+	return mInputBufferByteSize - kBufferPad; // minus kBufferPad to prevent end moving past start
+}
+
+UInt32	ACSimpleCodec::GetUsedInputBufferByteSize() const
+{
+	UInt32 theAnswer = 0;
+	
+	//	this object uses a ring buffer
+	if(mInputBufferStart <= mInputBufferEnd)
+	{
+		//	the active region is contiguous
+		theAnswer = mInputBufferEnd - mInputBufferStart;
+	}
+	else
+	{
+		//	the active region wraps around 
+		theAnswer = (mInputBufferByteSize - mInputBufferStart) + mInputBufferEnd;
+	}
+	
+	return theAnswer;
+}
+
+
+void	ACSimpleCodec::AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription)
+{
+	//	this buffer handling code doesn't care about such things as the packet descriptions
+	if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
+	
+	//	this is a ring buffer we're dealing with, so we need to set up a few things
+	UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
+	UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
+
+	UInt32 theMaxAvailableInputBytes = ioInputDataByteSize; // we can't consume more than we get
+
+	const Byte* theInputData = static_cast<const Byte*>(inInputData);
+	
+	// >>jamesmcc: added this because ioNumberPackets was not being updated if less was taken than given.
+	// THIS ASSUMES CBR!
+	UInt32 bytesPerPacketOfInput = mInputFormat.mBytesPerPacket;
+	UInt32 theAvailablePacketSize = theAvailableByteSize / bytesPerPacketOfInput;
+	
+	UInt32 minPacketSize = ioNumberPackets < theAvailablePacketSize ? ioNumberPackets : theAvailablePacketSize;
+	UInt32 minByteSize = minPacketSize * bytesPerPacketOfInput;
+	
+	//	we can copy only as much data as there is or up to how much space is availiable
+	ioNumberPackets = minPacketSize;
+	ioInputDataByteSize = minByteSize;
+	
+	// ioInputDataByteSize had better be <= to theMaxAvailableInputBytes or we're screwed
+	if (ioInputDataByteSize > theMaxAvailableInputBytes)
+	{
+		CODEC_THROW(kAudioCodecStateError);
+	}
+	// <<jamesmcc 
+	
+	//	now we have to copy the data taking into account the wrap around and where the start is
+	if(mInputBufferEnd + ioInputDataByteSize < mInputBufferByteSize)
+	{
+		//	no wrap around here
+		memcpy(mInputBuffer + mInputBufferEnd, theInputData, ioInputDataByteSize);
+		
+		//	adjust the end point
+		mInputBufferEnd += ioInputDataByteSize;
+	}
+	else
+	{
+		//	the copy will wrap
+		
+		//	copy the first part
+		UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd;
+		memcpy(mInputBuffer + mInputBufferEnd, theInputData, theBeforeWrapByteSize);
+		
+		//	and the rest
+		UInt32 theAfterWrapByteSize = ioInputDataByteSize - theBeforeWrapByteSize;
+		memcpy(mInputBuffer, theInputData + theBeforeWrapByteSize, theAfterWrapByteSize);
+		
+		//	adjust the end point
+		mInputBufferEnd = theAfterWrapByteSize;
+	}
+	
+}
+
+
+void	ACSimpleCodec::ZeroPadInputData(UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription)
+{
+	//	this buffer handling code doesn't care about such things as the packet descriptions
+	if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
+	
+	
+	//	this is a ring buffer we're dealing with, so we need to set up a few things
+	UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
+	UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
+	
+	// >>jamesmcc: added this because ioNumberPackets was not being updated if less was taken than given.
+	// THIS ASSUMES CBR!
+	UInt32 bytesPerPacketOfInput = mInputFormat.mBytesPerPacket;
+	UInt32 theAvailablePacketSize = theAvailableByteSize / bytesPerPacketOfInput;
+	
+	UInt32 minPacketSize = ioNumberPackets < theAvailablePacketSize ? ioNumberPackets : theAvailablePacketSize;
+	UInt32 minByteSize = minPacketSize * bytesPerPacketOfInput;
+	
+	//	we can copy only as much data as there is or up to how much space is availiable
+	ioNumberPackets = minPacketSize;
+	
+	// <<jamesmcc 
+	
+	//	now we have to copy the data taking into account the wrap around and where the start is
+	if(mInputBufferEnd + minByteSize < mInputBufferByteSize)
+	{
+		//	no wrap around here
+		memset(mInputBuffer + mInputBufferEnd, 0, minByteSize);
+		
+		//	adjust the end point
+		mInputBufferEnd += minByteSize;
+	}
+	else
+	{
+		//	the copy will wrap
+		
+		//	copy the first part
+		UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd;
+		memset(mInputBuffer + mInputBufferEnd, 0, theBeforeWrapByteSize);
+		
+		//	and the rest
+		UInt32 theAfterWrapByteSize = minByteSize - theBeforeWrapByteSize;
+		memset(mInputBuffer, 0, theAfterWrapByteSize);
+		
+		//	adjust the end point
+		mInputBufferEnd = theAfterWrapByteSize;
+	}
+}
+
+
+void	ACSimpleCodec::ConsumeInputData(UInt32 inConsumedByteSize)
+{
+	//	this is a convenience routine to make maintaining the ring buffer state easy
+	UInt32 theContiguousRange = GetInputBufferContiguousByteSize();
+	
+	if(inConsumedByteSize > GetUsedInputBufferByteSize()) CODEC_THROW(kAudioCodecUnspecifiedError);
+	
+	if(inConsumedByteSize <= theContiguousRange)
+	{
+		//	the region to consume doesn't wrap
+		
+		//	figure out how much to consume
+		inConsumedByteSize = (theContiguousRange < inConsumedByteSize) ? theContiguousRange : inConsumedByteSize;
+		
+		//	clear the consumed bits
+		memset(mInputBuffer + mInputBufferStart, 0, inConsumedByteSize);
+		
+		//	adjust the start
+		mInputBufferStart += inConsumedByteSize;
+	}
+	else
+	{
+		//	the region to consume will wrap
+		
+		//	clear the bits to the end of the buffer
+		memset(mInputBuffer + mInputBufferStart, 0, theContiguousRange);
+		
+		//	now clear the bits left from the start
+		memset(mInputBuffer, 0, inConsumedByteSize - theContiguousRange);
+		
+		//	adjust the start
+		mInputBufferStart = inConsumedByteSize - theContiguousRange;
+	}
+}
+
+
+Byte* ACSimpleCodec::GetBytes(UInt32& ioNumberBytes) const
+{
+	// if a client's algorithm has to have contiguous data and mInputBuffer wraps, then someone has to make a copy.
+	// I can do it more efficiently than the client. 
+	
+	if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
+
+	UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
+	//UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
+	
+	if (ioNumberBytes > theUsedByteSize) ioNumberBytes = theUsedByteSize;
+		
+	SInt32 leftOver = mInputBufferStart + ioNumberBytes - mInputBufferByteSize;
+	
+	if(leftOver > 0)
+	{
+		// need to copy beginning of buffer to the end. 
+		// We cleverly over allocated our buffer space to make this possible.
+		memmove(mInputBuffer + mInputBufferByteSize, mInputBuffer, leftOver);
+	}
+	
+	return GetInputBufferStart();
+}
+
+
+void	ACSimpleCodec::ReallocateInputBuffer(UInt32 inInputBufferByteSize)
+{
+	mInputBufferByteSize = inInputBufferByteSize + kBufferPad;
+	
+	//	toss the old buffer
+	delete[] mInputBuffer;
+	mInputBuffer = NULL;
+	
+	//	allocate the new one
+	// allocate extra in order to allow making contiguous data.
+	UInt32 allocSize = 2*inInputBufferByteSize + kBufferPad;
+	mInputBuffer = new Byte[allocSize];
+	memset(mInputBuffer, 0, allocSize);
+	
+	//	reset the ring buffer state
+	mInputBufferStart = 0;
+	mInputBufferEnd = 0;
+}
+
+void	ACSimpleCodec::GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable)
+{
+	switch(inPropertyID)
+	{
+		case kAudioCodecPropertyInputBufferSize:
+			outPropertyDataSize = SizeOf32(UInt32);
+			outWritable = true;
+			break;
+		default:
+			ACBaseCodec::GetPropertyInfo(inPropertyID, outPropertyDataSize, outWritable);
+			break;
+	}
+
+}
+
+void	ACSimpleCodec::SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData)
+{
+	switch(inPropertyID)
+	{
+		case kAudioCodecPropertyInputBufferSize:
+			if(inPropertyDataSize == sizeof(UInt32))
+			{
+				ReallocateInputBuffer(*reinterpret_cast<const UInt32*>(inPropertyData));
+			}
+			else
+			{
+				CODEC_THROW(kAudioCodecBadPropertySizeError);
+			}
+			break;
+		default:
+            ACBaseCodec::SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+            break;            
+    }
+}
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h
new file mode 100644
index 0000000..f41fe54
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h
@@ -0,0 +1,105 @@
+/*
+     File: ACSimpleCodec.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__ACSimpleCodec_h__)
+#define __ACSimpleCodec_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "ACBaseCodec.h"
+
+//=============================================================================
+//	ACSimpleCodec
+//
+//	This extension of ACBaseCodec provides for a simple ring buffer to handle
+//	input data.
+//=============================================================================
+
+class ACSimpleCodec
+:
+	public ACBaseCodec
+{
+
+//	Construction/Destruction
+public:
+						ACSimpleCodec(UInt32 inInputBufferByteSize, AudioComponentInstance inInstance);
+	virtual				~ACSimpleCodec();
+
+//	Data Handling
+public:
+	virtual void		Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize) = 0;
+	virtual void		Uninitialize();
+	virtual void		Reset();
+
+	virtual void		AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription);
+	virtual void		ZeroPadInputData(UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription);
+	virtual UInt32		GetInputBufferByteSize() const;
+	virtual UInt32		GetUsedInputBufferByteSize() const;
+	virtual void		GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable);
+	virtual void		SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData);
+
+protected:
+	void				ConsumeInputData(UInt32 inConsumedByteSize);	
+	Byte*				GetInputBufferStart() const { return mInputBuffer + mInputBufferStart; }
+	UInt32				GetInputBufferContiguousByteSize() const { return (mInputBufferStart <= mInputBufferEnd) ? (mInputBufferEnd - mInputBufferStart) : (mInputBufferByteSize - mInputBufferStart); }
+	virtual void		ReallocateInputBuffer(UInt32 inInputBufferByteSize);
+	
+	// returns a pointer to contiguous bytes. 
+	// will do some copying if the request wraps around the internal buffer.
+	// request must be less than available bytes
+	Byte*				GetBytes(UInt32& ioNumberBytes) const;
+
+private:	
+	Byte*				mInputBuffer;
+	UInt32				mInputBufferByteSize;
+	UInt32				mInputBufferStart;
+	UInt32				mInputBufferEnd;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp
new file mode 100644
index 0000000..8954c8d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp
@@ -0,0 +1,76 @@
+/*
+     File: GetCodecBundle.cpp
+ Abstract: GetCodecBundle.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "GetCodecBundle.h"
+
+#if TARGET_OS_WIN32
+	#include "CAWin32StringResources.h"
+#endif
+
+#if TARGET_OS_WIN32
+#define kCodecBundleID		"com.apple.audio.codecs.Components"
+#else
+const CFStringRef kCodecBundleID = CFSTR("com.apple.audio.codecs.Components");
+#endif
+
+CFBundleRef GetCodecBundle()
+{
+	static CFBundleRef sAudioCodecBundle = 0;
+	if (!sAudioCodecBundle) 
+	{
+	#if TARGET_OS_WIN32
+		sAudioCodecBundle = CFBundleGetBundleWithIdentifier(CFSTR(kCodecBundleID));
+	#else
+		sAudioCodecBundle = CFBundleGetBundleWithIdentifier(kCodecBundleID);
+	#endif
+		if (sAudioCodecBundle)
+		{
+			CFRetain(sAudioCodecBundle);
+		}
+	}
+	return sAudioCodecBundle;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h
new file mode 100644
index 0000000..96e3d9e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h
@@ -0,0 +1,60 @@
+/*
+     File: GetCodecBundle.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef _GetCodecBundle_
+#define _GetCodecBundle_
+
+#include <TargetConditionals.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CFBundle.h>
+#else
+	#include "CFBundle.h"
+#endif
+
+CFBundleRef GetCodecBundle();
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp
new file mode 100644
index 0000000..053da0a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp
@@ -0,0 +1,1040 @@
+/*
+     File: AudioFileComponentBase.cpp
+ Abstract: AudioFileComponentBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioToolbox/AudioFileComponent.h>
+#else
+	#include "AudioFileComponent.h"
+#endif
+
+#include "AudioFileComponentBase.h"
+
+#if TARGET_OS_MAC
+	#if __LP64__
+		// comp instance, parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index + 1];
+	#else
+		// parameters in reverse order, then comp instance
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+	#endif
+#elif TARGET_OS_WIN32
+		// (no comp instance), parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define AFC	((AudioFileComponentBase *)&ACPI->mInstanceStorage)
+
+//----------------------------------------------------------------------------------------
+
+static OSStatus CreateURL(
+								void *                            self,
+								CFURLRef							inFileRef,
+								const AudioStreamBasicDescription	*inFormat,
+								UInt32								inFlags)
+{
+	return AFC->AFAPI_CreateURL(inFileRef, inFormat, inFlags);
+}
+
+static OSStatus OpenURL(
+								void *                            self,
+								CFURLRef							inFileRef, 
+								SInt8								inPermissions, 
+								int									inFileDescriptor)
+{
+	return AFC->AFAPI_OpenURL(inFileRef, inPermissions, inFileDescriptor);
+}
+
+static OSStatus OpenWithCallbacks(
+								void *                            self,
+								void *								inRefCon, 
+								AudioFile_ReadProc					inReadFunc, 
+								AudioFile_WriteProc					inWriteFunc, 
+								AudioFile_GetSizeProc				inGetSizeFunc,
+								AudioFile_SetSizeProc				inSetSizeFunc)
+{
+	return AFC->AFAPI_OpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+}
+
+static OSStatus InitializeWithCallbacks(
+								void *                            self,
+								void *								inRefCon, 
+								AudioFile_ReadProc					inReadFunc, 
+								AudioFile_WriteProc					inWriteFunc, 
+								AudioFile_GetSizeProc				inGetSizeFunc,
+								AudioFile_SetSizeProc				inSetSizeFunc,
+								UInt32								inFileType,
+								const AudioStreamBasicDescription	*inFormat,
+								UInt32								inFlags)
+{
+	return AFC->AFAPI_InitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc, inFileType, inFormat, inFlags);
+}
+
+static OSStatus Close(
+								void *                            self)
+{
+	return AFC->AFAPI_Close();
+}
+
+static OSStatus Optimize(
+								void *                            self)
+{
+	return AFC->AFAPI_Optimize();
+}
+
+static OSStatus ReadBytes(
+								void *                            self,
+								Boolean			inUseCache,
+								SInt64			inStartingByte, 
+								UInt32			*ioNumBytes, 
+								void			*outBuffer)
+{
+	return AFC->AFAPI_ReadBytes(inUseCache, inStartingByte, ioNumBytes, outBuffer);
+}
+
+
+static OSStatus WriteBytes(
+								void *         self,
+								Boolean			inUseCache,
+								SInt64			inStartingByte, 
+								UInt32			*ioNumBytes, 
+								const void		*inBuffer)
+{
+	return AFC->AFAPI_WriteBytes(inUseCache, inStartingByte, ioNumBytes, inBuffer);
+}
+
+
+static OSStatus ReadPackets(
+								void *                        self,
+								Boolean							inUseCache,
+								UInt32							*outNumBytes,
+								AudioStreamPacketDescription	*outPacketDescriptions,
+								SInt64							inStartingPacket, 
+								UInt32							*ioNumPackets, 
+								void							*outBuffer)
+{
+	return AFC->AFAPI_ReadPackets(inUseCache, outNumBytes, outPacketDescriptions, 
+		inStartingPacket, ioNumPackets, outBuffer);
+}
+
+static OSStatus ReadPacketData(
+								void *                        self,
+								Boolean							inUseCache,
+								UInt32							*ioNumBytes,
+								AudioStreamPacketDescription	*outPacketDescriptions,
+								SInt64							inStartingPacket, 
+								UInt32							*ioNumPackets, 
+								void							*outBuffer)
+{
+	return AFC->AFAPI_ReadPacketData(inUseCache, ioNumBytes, outPacketDescriptions, 
+		inStartingPacket, ioNumPackets, outBuffer);
+}
+
+#if COREAUDIOTYPES_VERSION < 1050
+static OSStatus WritePackets(
+								void *                            self,
+								Boolean								inUseCache,
+								UInt32								inNumBytes,
+								AudioStreamPacketDescription		*inPacketDescriptions,
+								SInt64								inStartingPacket, 
+								UInt32								*ioNumPackets, 
+								const void							*inBuffer)
+#else
+static OSStatus WritePackets(
+								void *                            self,
+								Boolean								inUseCache,
+								UInt32								inNumBytes,
+								const AudioStreamPacketDescription	*inPacketDescriptions,
+								SInt64								inStartingPacket, 
+								UInt32								*ioNumPackets, 
+								const void							*inBuffer)
+#endif
+{
+	return AFC->AFAPI_WritePackets(inUseCache, inNumBytes, 
+		(const AudioStreamPacketDescription	*)inPacketDescriptions, // this should be const (and is in 10.5 headers)
+		inStartingPacket, ioNumPackets, inBuffer);
+}
+
+static OSStatus GetPropertyInfo(
+								void *                 self,
+								AudioFilePropertyID    inPropertyID,
+								UInt32					*outDataSize,
+								UInt32					*isWritable)
+{
+	return AFC->AFAPI_GetPropertyInfo(inPropertyID, outDataSize, isWritable);
+}
+
+static OSStatus GetProperty(
+								void *                 self,
+								AudioFilePropertyID		inPropertyID,
+								UInt32					*ioDataSize,
+								void					*ioData)
+{
+	return AFC->AFAPI_GetProperty(inPropertyID, ioDataSize, ioData);
+}
+
+
+static OSStatus SetProperty(
+								void *                 self,
+								AudioFilePropertyID		inPropertyID,
+								UInt32					inDataSize,
+								const void				*inData)
+{
+	return AFC->AFAPI_SetProperty(inPropertyID, inDataSize, inData);
+}
+
+static OSStatus CountUserData(
+								void *                 self,
+								UInt32					inUserDataID,
+								UInt32					*outNumberItems)
+{
+	return AFC->AFAPI_CountUserData(inUserDataID, outNumberItems);
+}
+
+static OSStatus GetUserDataSize(
+								void *                 self,
+								UInt32					inUserDataID,
+								UInt32					inIndex,
+								UInt32					*outDataSize)
+{
+	return AFC->AFAPI_GetUserDataSize(inUserDataID, inIndex, outDataSize);
+}
+
+static OSStatus GetUserData(
+								void *                 self,
+								UInt32					inUserDataID,
+								UInt32					inIndex,
+								UInt32					*ioUserDataSize,
+								void					*outUserData)
+{
+	return AFC->AFAPI_GetUserData(inUserDataID, inIndex, ioUserDataSize, outUserData);
+}
+
+static OSStatus SetUserData(
+								void *                 self,
+								UInt32					inUserDataID,
+								UInt32					inIndex,
+								UInt32					inUserDataSize,
+								const void				*inUserData)
+{
+	return AFC->AFAPI_SetUserData(inUserDataID, inIndex, inUserDataSize, inUserData);
+}
+
+static OSStatus RemoveUserData(
+								void *                 self,
+								UInt32					inUserDataID,
+								UInt32					inIndex)
+{
+	return AFC->AFAPI_RemoveUserData(inUserDataID, inIndex);
+}
+
+static OSStatus ExtensionIsThisFormat(
+								void *                 self,
+								CFStringRef				inExtension,
+								UInt32					*outResult)
+{
+	AudioFileFormatBase* aff = AFC->GetAudioFileFormatBase();
+	if (!aff) return kAudio_ParamError;
+	
+	UInt32 res = aff->ExtensionIsThisFormat(inExtension);
+	if (outResult) *outResult = res;
+	return noErr;
+}
+
+static OSStatus FileDataIsThisFormat(
+								void *                 self,
+								UInt32					inDataByteSize, 
+								const void*				inData,
+								UInt32					*outResult)
+{
+	AudioFileFormatBase* aff = AFC->GetAudioFileFormatBase();
+	if (!aff) return kAudio_ParamError;
+	
+	UncertainResult res = aff->FileDataIsThisFormat(inDataByteSize, inData);
+	if (outResult) *outResult = res;
+	return noErr;
+}
+
+static OSStatus GetGlobalInfoSize(
+								void *                 self,
+								AudioFilePropertyID	inPropertyID,
+								UInt32					inSpecifierSize,
+								const void*				inSpecifier,
+								UInt32					*outPropertySize)
+{
+	return AFC->AFAPI_GetGlobalInfoSize(inPropertyID, inSpecifierSize, inSpecifier, outPropertySize);
+}
+
+static OSStatus GetGlobalInfo(
+								void *                 self,
+								AudioFilePropertyID	inPropertyID,
+								UInt32					inSpecifierSize,
+								const void*				inSpecifier,
+								UInt32					*ioPropertySize,
+								void					*ioPropertyData)
+{
+	return AFC->AFAPI_GetGlobalInfo(inPropertyID, inSpecifierSize, inSpecifier, ioPropertySize, ioPropertyData);
+}
+
+//----------------------------------------------------------------------------------------
+
+
+AudioFileComponentBase::AudioFileComponentBase(AudioComponentInstance inInstance)
+	: ComponentBase(inInstance)
+{
+}
+
+AudioFileComponentBase::~AudioFileComponentBase()
+{
+}
+
+AudioFileObjectComponentBase::AudioFileObjectComponentBase(AudioComponentInstance inInstance)
+	: AudioFileComponentBase(inInstance), mAudioFileObject(0)
+{
+	// derived class should create an AudioFileObject here and if NULL, the AudioFormat as well.
+}
+
+AudioFileObjectComponentBase::~AudioFileObjectComponentBase()
+{
+	delete mAudioFileObject;
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_CreateURL(
+								CFURLRef							inFileRef, 
+                                const AudioStreamBasicDescription	*inFormat,
+                                UInt32								inFlags)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	
+	OSStatus result = mAudioFileObject->DoCreate (inFileRef, inFormat, inFlags);
+	return result;
+}
+
+								
+OSStatus AudioFileObjectComponentBase::AFAPI_OpenURL(
+									CFURLRef		inFileRef, 
+									SInt8  			inPermissions,
+									int				inFD)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	
+	OSStatus result = mAudioFileObject->DoOpen(inFileRef, inPermissions, inFD);
+ 	return result;
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_OpenWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->DoOpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_InitializeWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc,
+				UInt32								inFileType,
+				const AudioStreamBasicDescription	*inFormat,
+				UInt32								inFlags)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->DoInitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc, 
+											inFileType, inFormat, inFlags);
+}
+
+									
+OSStatus AudioFileObjectComponentBase::AFAPI_Close()
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->DoClose();
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_Optimize()
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->DoOptimize();
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadBytes(		
+											Boolean			inUseCache,
+											SInt64			inStartingByte, 
+											UInt32			*ioNumBytes, 
+											void			*outBuffer)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->ReadBytes(inUseCache, inStartingByte, ioNumBytes, outBuffer);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_WriteBytes(		
+											Boolean			inUseCache,
+											SInt64			inStartingByte, 
+											UInt32			*ioNumBytes, 
+											const void		*inBuffer)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->WriteBytes(inUseCache, inStartingByte, ioNumBytes, inBuffer);
+}
+
+
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadPackets(		
+											Boolean							inUseCache,
+											UInt32							*outNumBytes,
+											AudioStreamPacketDescription	*outPacketDescriptions,
+											SInt64							inStartingPacket, 
+											UInt32  						*ioNumPackets, 
+											void							*outBuffer)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->ReadPackets(inUseCache, outNumBytes, outPacketDescriptions,
+												inStartingPacket, ioNumPackets, outBuffer);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadPacketData(		
+											Boolean							inUseCache,
+											UInt32							*ioNumBytes,
+											AudioStreamPacketDescription	*outPacketDescriptions,
+											SInt64							inStartingPacket, 
+											UInt32  						*ioNumPackets, 
+											void							*outBuffer)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->ReadPacketData(inUseCache, ioNumBytes, outPacketDescriptions,
+												inStartingPacket, ioNumPackets, outBuffer);
+}
+
+									
+OSStatus AudioFileObjectComponentBase::AFAPI_WritePackets(	
+											Boolean								inUseCache,
+											UInt32								inNumBytes,
+											const AudioStreamPacketDescription	*inPacketDescriptions,
+											SInt64								inStartingPacket, 
+											UInt32								*ioNumPackets, 
+											const void							*inBuffer)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->WritePackets(inUseCache, inNumBytes, inPacketDescriptions,
+												inStartingPacket, ioNumPackets, inBuffer);
+}
+
+
+									
+OSStatus AudioFileObjectComponentBase::AFAPI_GetPropertyInfo(	
+											AudioFilePropertyID		inPropertyID,
+											UInt32					*outDataSize,
+											UInt32					*isWritable)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->GetPropertyInfo(inPropertyID, outDataSize, isWritable);
+}
+
+										
+OSStatus AudioFileObjectComponentBase::AFAPI_GetProperty(		
+											AudioFilePropertyID		inPropertyID,
+											UInt32					*ioPropertySize,
+											void					*ioPropertyData)
+{
+	OSStatus err = noErr;
+	
+	if (!ioPropertyData) return kAudio_ParamError;
+	
+	if (!mAudioFileObject) return kAudio_ParamError;
+	err = mAudioFileObject->GetProperty(inPropertyID, ioPropertySize, ioPropertyData);
+	return err;
+}
+
+									
+OSStatus AudioFileObjectComponentBase::AFAPI_SetProperty(		
+											AudioFilePropertyID		inPropertyID,
+											UInt32					inPropertySize,
+											const void				*inPropertyData)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->SetProperty(inPropertyID, inPropertySize, inPropertyData);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_CountUserData(		
+											UInt32				inUserDataID,
+											UInt32				*outNumberItems)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->CountUserData(inUserDataID, outNumberItems);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetUserDataSize(		
+											UInt32				inUserDataID,
+											UInt32				inIndex,
+											UInt32				*outUserDataSize)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->GetUserDataSize(inUserDataID, inIndex, outUserDataSize);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetUserData(		
+											UInt32				inUserDataID,
+											UInt32				inIndex,
+											UInt32				*ioUserDataSize,
+											void				*outUserData)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->GetUserData(inUserDataID, inIndex, ioUserDataSize, outUserData);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_SetUserData(		
+											UInt32				inUserDataID,
+											UInt32				inIndex,
+											UInt32				inUserDataSize,
+											const void			*inUserData)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->SetUserData(inUserDataID, inIndex, inUserDataSize, inUserData);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_RemoveUserData(		
+											UInt32				inUserDataID,
+											UInt32				inIndex)
+{
+	if (!mAudioFileObject) return kAudio_ParamError;
+	return mAudioFileObject->RemoveUserData(inUserDataID, inIndex);
+}
+
+
+OSStatus AudioFileComponentBase::AFAPI_GetGlobalInfoSize(		
+											AudioFilePropertyID		inPropertyID,
+											UInt32					inSpecifierSize,
+											const void*				inSpecifier,
+											UInt32					*outPropertySize)
+{
+	OSStatus err = noErr;
+		
+	switch (inPropertyID)
+	{
+		case kAudioFileComponent_CanRead :
+		case kAudioFileComponent_CanWrite :
+			*outPropertySize = sizeof(UInt32);
+			break;
+
+		case kAudioFileComponent_FileTypeName :
+			*outPropertySize = sizeof(CFStringRef);
+			break;
+
+		case kAudioFileComponent_ExtensionsForType :
+			*outPropertySize = sizeof(CFArrayRef);
+			break;
+			
+		case kAudioFileComponent_UTIsForType :
+			*outPropertySize = sizeof(CFArrayRef);
+			break;
+			
+		case kAudioFileComponent_MIMETypesForType :
+			*outPropertySize = sizeof(CFArrayRef);
+			break;
+			
+		case kAudioFileComponent_AvailableFormatIDs :
+		{
+			UInt32 size = 0xFFFFFFFF;
+			err = GetAudioFileFormatBase()->GetAvailableFormatIDs(&size, NULL);
+			if (!err) *outPropertySize = size;
+			break;
+		}
+		case kAudioFileComponent_HFSTypeCodesForType :
+		{
+			UInt32 size = 0xFFFFFFFF;
+			err = GetAudioFileFormatBase()->GetHFSCodes(&size, NULL);
+			if (!err) *outPropertySize = size;
+			break;
+		}
+		case kAudioFileComponent_AvailableStreamDescriptionsForFormat :
+			{
+				if (inSpecifierSize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+				UInt32 inFormatID = *(UInt32*)inSpecifier;
+				err = GetAudioFileFormatBase()->GetAvailableStreamDescriptions(inFormatID, outPropertySize, NULL);
+			}
+			break;
+			
+		default:
+			err = kAudioFileUnsupportedPropertyError;
+	}
+	return err;
+}
+
+
+OSStatus AudioFileComponentBase::AFAPI_GetGlobalInfo(		
+											AudioFilePropertyID		inPropertyID,
+											UInt32					inSpecifierSize,
+											const void*				inSpecifier,
+											UInt32					*ioPropertySize,
+											void					*ioPropertyData)
+{
+	OSStatus err = noErr;
+	
+	if (!ioPropertyData || !ioPropertySize) return kAudio_ParamError;
+	
+	switch (inPropertyID)
+	{
+		case kAudioFileComponent_CanRead :
+			{
+				if (*ioPropertySize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+				UInt32* flag = (UInt32*)ioPropertyData;
+				*flag = GetAudioFileFormatBase()->CanRead();
+			}
+			break;
+			
+		case kAudioFileComponent_CanWrite :
+			{
+				if (*ioPropertySize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+				UInt32* flag = (UInt32*)ioPropertyData;
+				*flag = GetAudioFileFormatBase()->CanWrite();
+			}
+			break;
+			
+		case kAudioFileComponent_FileTypeName :
+			{
+				if (*ioPropertySize != sizeof(CFStringRef)) return kAudioFileBadPropertySizeError;
+				CFStringRef* name = (CFStringRef*)ioPropertyData;
+				GetAudioFileFormatBase()->GetFileTypeName(name);
+			}
+			break;
+
+		case kAudioFileComponent_ExtensionsForType :
+			{
+				if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+				CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+				GetAudioFileFormatBase()->GetExtensions(array);
+			}
+			break;
+
+		case kAudioFileComponent_UTIsForType :
+			{
+				if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+				CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+				GetAudioFileFormatBase()->GetUTIs(array);
+			}
+			break;
+
+		case kAudioFileComponent_MIMETypesForType :
+			{
+				if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+				CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+				GetAudioFileFormatBase()->GetMIMETypes(array);
+			}
+			break;
+
+		case kAudioFileComponent_HFSTypeCodesForType :
+			{
+				err = GetAudioFileFormatBase()->GetHFSCodes(ioPropertySize, ioPropertyData);
+			}
+			break;
+			
+		case kAudioFileComponent_AvailableFormatIDs :
+			{
+				err = GetAudioFileFormatBase()->GetAvailableFormatIDs(ioPropertySize, ioPropertyData);
+			}
+			break;
+			
+		case kAudioFileComponent_AvailableStreamDescriptionsForFormat :
+			{
+				if (inSpecifierSize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+				UInt32 inFormatID = *(UInt32*)inSpecifier; 
+				err = GetAudioFileFormatBase()->GetAvailableStreamDescriptions(inFormatID, ioPropertySize, ioPropertyData);
+			}
+			break;
+						
+		default:
+			err = kAudioFileUnsupportedPropertyError;
+	}
+	return err;
+}
+
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus AudioFileComponentBase::ComponentEntryDispatch(ComponentParameters* params, AudioFileComponentBase* inThis)
+{
+	OSStatus		result = noErr;
+	if (inThis == NULL) return kAudio_ParamError;
+	
+	try
+	{
+		switch (params->what)
+		{						
+			case kComponentCanDoSelect:
+				switch (GetSelectorForCanDo(params))
+				{
+					case kAudioFileCreateURLSelect:
+					case kAudioFileOpenURLSelect:
+					case kAudioFileOpenWithCallbacksSelect:
+					case kAudioFileInitializeWithCallbacksSelect:
+					case kAudioFileCloseSelect:
+					case kAudioFileOptimizeSelect:
+					case kAudioFileReadBytesSelect:
+					case kAudioFileWriteBytesSelect:
+					case kAudioFileReadPacketsSelect:
+					case kAudioFileWritePacketsSelect:
+					case kAudioFileGetPropertyInfoSelect:
+					case kAudioFileGetPropertySelect:
+					case kAudioFileSetPropertySelect:
+					case kAudioFileExtensionIsThisFormatSelect:
+					case kAudioFileFileDataIsThisFormatSelect:
+					case kAudioFileGetGlobalInfoSizeSelect:
+					case kAudioFileGetGlobalInfoSelect:
+					
+					case kAudioFileCountUserDataSelect:
+					case kAudioFileGetUserDataSizeSelect:
+					case kAudioFileGetUserDataSelect:
+					case kAudioFileSetUserDataSelect:
+					case kAudioFileRemoveUserDataSelect:
+						result = 1;
+						break;
+					default:
+					 // these are no longer supported
+/*					case kAudioFileCreateSelect:
+					case kAudioFileOpenSelect:
+					case kAudioFileInitializeSelect:
+*/						result = ComponentBase::ComponentEntryDispatch(params, inThis);
+				};
+				break;
+
+				case kAudioFileCreateURLSelect:
+					{
+						PARAM(CFURLRef, inFileRef, 0, 3);
+						PARAM(const AudioStreamBasicDescription*, inFormat, 1, 3);
+						PARAM(UInt32, inFlags, 2, 3);
+						
+						result = inThis->AFAPI_CreateURL(inFileRef, inFormat, inFlags);
+					}
+					break;
+				case kAudioFileOpenURLSelect:
+					{
+						PARAM(CFURLRef, inFileRef, 0, 3);
+						PARAM(SInt32, inPermissions, 1, 3);
+						PARAM(int, inFileDescriptor, 2, 3);
+						
+						result = inThis->AFAPI_OpenURL(inFileRef, inPermissions, inFileDescriptor);
+					}
+					break;
+				case kAudioFileOpenWithCallbacksSelect:
+					{
+						PARAM(void*, inRefCon, 0, 5);
+						PARAM(AudioFile_ReadProc, inReadFunc, 1, 5);
+						PARAM(AudioFile_WriteProc, inWriteFunc, 2, 5);
+						PARAM(AudioFile_GetSizeProc, inGetSizeFunc, 3, 5);
+						PARAM(AudioFile_SetSizeProc, inSetSizeFunc, 4, 5);
+						
+						result = inThis->AFAPI_OpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc, 
+													inGetSizeFunc, inSetSizeFunc);
+					}
+					break;
+				case kAudioFileInitializeWithCallbacksSelect:
+					{
+						PARAM(void*, inRefCon, 0, 8);
+						PARAM(AudioFile_ReadProc, inReadFunc, 1, 8);
+						PARAM(AudioFile_WriteProc, inWriteFunc, 2, 8);
+						PARAM(AudioFile_GetSizeProc, inGetSizeFunc, 3, 8);
+						PARAM(AudioFile_SetSizeProc, inSetSizeFunc, 4, 8);
+						PARAM(UInt32, inFileType, 5, 8);
+						PARAM(const AudioStreamBasicDescription*, inFormat, 6, 8);
+						PARAM(UInt32, inFlags, 7, 8);
+						
+						result = inThis->AFAPI_InitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc, 
+													inGetSizeFunc, inSetSizeFunc,
+													inFileType, inFormat, inFlags);
+					}
+					break;
+				case kAudioFileCloseSelect:
+					{
+						result = inThis->AFAPI_Close();
+					}
+					break;
+				case kAudioFileOptimizeSelect:
+					{
+						result = inThis->AFAPI_Optimize();
+					}
+					break;
+				case kAudioFileReadBytesSelect:
+					{
+						PARAM(UInt32, inUseCache, 0, 4);
+						PARAM(SInt64*, inStartingByte, 1, 4);
+						PARAM(UInt32*, ioNumBytes, 2, 4);
+						PARAM(void*, outBuffer, 3, 4);
+						
+						result = inThis->AFAPI_ReadBytes(inUseCache, *inStartingByte, ioNumBytes,
+							outBuffer);
+					}
+					break;
+				case kAudioFileWriteBytesSelect:
+					{
+						PARAM(UInt32, inUseCache, 0, 4);
+						PARAM(SInt64*, inStartingByte, 1, 4);
+						PARAM(UInt32*, ioNumBytes, 2, 4);
+						PARAM(const void*, inBuffer, 3, 4);
+						
+						result = inThis->AFAPI_WriteBytes(inUseCache, *inStartingByte, ioNumBytes,
+							inBuffer);
+					}
+					break;
+				case kAudioFileReadPacketsSelect:
+					{
+						PARAM(UInt32, inUseCache, 0, 6);
+						PARAM(UInt32*, outNumBytes, 1, 6);
+						PARAM(AudioStreamPacketDescription*, outPacketDescriptions, 2, 6);
+						PARAM(SInt64*, inStartingPacket, 3, 6);
+						PARAM(UInt32*, ioNumPackets, 4, 6);
+						PARAM(void*, outBuffer, 5, 6);
+						
+						result = inThis->AFAPI_ReadPackets(inUseCache, outNumBytes, outPacketDescriptions, 
+							*inStartingPacket, ioNumPackets, outBuffer);
+					}
+					break;
+				case kAudioFileWritePacketsSelect:
+					{
+						PARAM(UInt32, inUseCache, 0, 6);
+						PARAM(UInt32, inNumBytes, 1, 6);
+						PARAM(const AudioStreamPacketDescription*, inPacketDescriptions, 2, 6);
+						PARAM(SInt64*, inStartingPacket, 3, 6);
+						PARAM(UInt32*, ioNumPackets, 4, 6);
+						PARAM(const void*, inBuffer, 5, 6);
+						
+						result = inThis->AFAPI_WritePackets(inUseCache, inNumBytes, inPacketDescriptions, 
+							*inStartingPacket, ioNumPackets, inBuffer);
+					}
+					break;
+					
+				case kAudioFileGetPropertyInfoSelect:
+					{
+						PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+						PARAM(UInt32*, outPropertySize, 1, 3);
+						PARAM(UInt32*, outWritable, 2, 3);
+						
+						result = inThis->AFAPI_GetPropertyInfo(inPropertyID, outPropertySize, outWritable);
+					}
+					break;
+					
+				case kAudioFileGetPropertySelect:
+					{
+						PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+						PARAM(UInt32*, ioPropertyDataSize, 1, 3);
+						PARAM(void*, outPropertyData, 2, 3);
+						
+						result = inThis->AFAPI_GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
+					}
+					break;
+				case kAudioFileSetPropertySelect:
+					{
+						PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+						PARAM(UInt32, inPropertyDataSize, 1, 3);
+						PARAM(const void*, inPropertyData, 2, 3);
+						
+						result = inThis->AFAPI_SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+					}
+					break;
+					
+				case kAudioFileGetGlobalInfoSizeSelect:
+					{
+						PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 4);
+						PARAM(UInt32, inSpecifierSize, 1, 4);
+						PARAM(const void*, inSpecifier, 2, 4);
+						PARAM(UInt32*, outPropertyDataSize, 3, 4);
+						
+						result = inThis->AFAPI_GetGlobalInfoSize(inPropertyID, inSpecifierSize, inSpecifier,
+							outPropertyDataSize);
+					}
+					break;
+				case kAudioFileGetGlobalInfoSelect:
+					{
+						PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 5);
+						PARAM(UInt32, inSpecifierSize, 1, 5);
+						PARAM(const void*, inSpecifier, 2, 5);
+						PARAM(UInt32*, ioPropertyDataSize, 3, 5);
+						PARAM(void*, outPropertyData, 4, 5);
+						
+						result = inThis->AFAPI_GetGlobalInfo(inPropertyID, inSpecifierSize, inSpecifier,
+							ioPropertyDataSize, outPropertyData);
+					}
+					break;
+					
+				case kAudioFileExtensionIsThisFormatSelect:
+					{
+						PARAM(CFStringRef, inExtension, 0, 2);
+						PARAM(UInt32*, outResult, 1, 2);
+						
+						AudioFileFormatBase* aff = inThis->GetAudioFileFormatBase();
+						if (!aff) return kAudio_ParamError;
+						
+						UInt32 res = aff->ExtensionIsThisFormat(inExtension);
+						if (outResult) *outResult = res;
+					}
+					break;
+					
+				case kAudioFileFileDataIsThisFormatSelect:
+					{
+						PARAM(UInt32, inDataByteSize, 0, 3);
+						PARAM(const void*, inData, 1, 3);
+						PARAM(UInt32*, outResult, 2, 3);
+						
+						AudioFileFormatBase* aff = inThis->GetAudioFileFormatBase();
+						if (!aff) return kAudio_ParamError;
+						
+						UncertainResult res = aff->FileDataIsThisFormat(inDataByteSize, inData);
+						if (outResult) *outResult = res;
+					}
+					break;
+
+				case kAudioFileCountUserDataSelect:
+					{
+						PARAM(UInt32, inUserDataID, 0, 2);
+						PARAM(UInt32*, outNumberItems, 1, 2);
+					
+						result = inThis->AFAPI_CountUserData(inUserDataID, outNumberItems);
+					}
+					break;
+					
+				case kAudioFileGetUserDataSizeSelect:
+					{
+						PARAM(UInt32, inUserDataID, 0, 3);
+						PARAM(UInt32, inIndex, 1, 3);
+						PARAM(UInt32*, outUserDataSize, 2, 3);
+						
+						result = inThis->AFAPI_GetUserDataSize(inUserDataID, inIndex, outUserDataSize);
+					}
+					break;
+					
+				case kAudioFileGetUserDataSelect:
+					{
+						PARAM(UInt32, inUserDataID, 0, 4);
+						PARAM(UInt32, inIndex, 1, 4);
+						PARAM(UInt32*, ioUserDataSize, 2, 4);
+						PARAM(void*, outUserData, 3, 4);
+						
+						result = inThis->AFAPI_GetUserData(inUserDataID, inIndex, 
+										ioUserDataSize, outUserData);
+					}
+					break;
+					
+				case kAudioFileSetUserDataSelect:
+					{
+						PARAM(UInt32, inUserDataID, 0, 4);
+						PARAM(UInt32, inIndex, 1, 4);
+						PARAM(UInt32, inUserDataSize, 2, 4);
+						PARAM(const void*, inUserData, 3, 4);
+						
+						result = inThis->AFAPI_SetUserData(inUserDataID, inIndex, 
+										inUserDataSize, inUserData);
+					}
+					break;
+	
+				case kAudioFileRemoveUserDataSelect:
+					{
+						PARAM(UInt32, inUserDataID, 0, 2);
+						PARAM(UInt32, inIndex, 1, 2);
+						
+						result = inThis->AFAPI_RemoveUserData(inUserDataID, inIndex);
+					}
+					break;
+	
+		
+				default:
+					result = ComponentBase::ComponentEntryDispatch(params, inThis);
+					break;
+		}
+	}
+	COMPONENT_CATCH
+	return result;
+} 
+#endif
+
+AudioComponentMethod AudioFileComponentLookup::Lookup (SInt16 selector)
+{
+	switch (selector) {
+	
+#define DefCase(NAME) case kAudioFile##NAME##Select: return (AudioComponentMethod)NAME
+
+		DefCase(OpenWithCallbacks);
+		DefCase(InitializeWithCallbacks);
+		DefCase(Close);
+		DefCase(Optimize);
+		DefCase(ReadBytes);
+		DefCase(WriteBytes);
+		DefCase(ReadPackets);
+		DefCase(WritePackets);
+		DefCase(GetPropertyInfo);
+		DefCase(GetProperty);
+		DefCase(SetProperty);
+		
+		DefCase(ExtensionIsThisFormat);
+		DefCase(GetGlobalInfoSize);
+		DefCase(GetGlobalInfo);
+
+		DefCase(CountUserData);
+		DefCase(GetUserDataSize);
+		DefCase(GetUserData);
+		DefCase(SetUserData);
+		DefCase(RemoveUserData);
+		DefCase(CreateURL);
+		DefCase(OpenURL);
+		DefCase(FileDataIsThisFormat);
+		DefCase(ReadPacketData);
+		
+		// These selectors are deprecated and do not appear: Create, Open, Initialize, FileIsThisFormat, DataIsThisFormat.
+
+		default:
+			break;
+	}
+	return NULL;
+}
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h
new file mode 100644
index 0000000..5a11934
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h
@@ -0,0 +1,311 @@
+/*
+     File: AudioFileComponentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AudioFileComponentBase_h__
+#define __AudioFileComponentBase_h__
+
+#include "ComponentBase.h"
+#include "AudioFileFormat.h"
+
+struct AudioFileComponentLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioFileComponentFactory : public APFactory<AudioFileComponentLookup, Implementor>
+{
+};
+
+/* subclass, override AudioFileComponentBase() and GetAudioFormat() and that's it. */
+
+class AudioFileComponentBase : public ComponentBase
+{
+public:
+	AudioFileComponentBase(AudioComponentInstance inInstance);
+	virtual ~AudioFileComponentBase();
+
+	virtual AudioFileFormatBase* GetAudioFileFormatBase() const = 0;
+	
+	/* Public API Function Support */
+	virtual OSStatus AFAPI_CreateURL(
+								CFURLRef							inFileRef,
+                                const AudioStreamBasicDescription	*inFormat,
+                                UInt32								inFlags) { return kAudio_UnimplementedError; }
+
+	virtual OSStatus AFAPI_OpenURL(
+									CFURLRef		inFileRef, 
+									SInt8  			inPermissions,
+									int				inFD) { return kAudio_UnimplementedError; }
+									
+
+	virtual OSStatus AFAPI_Create(
+								const FSRef							*inParentRef, 
+                                CFStringRef							inFileName,
+                                const AudioStreamBasicDescription	*inFormat,
+                                UInt32								inFlags,
+                                FSRef								*outNewFileRef) { return kAudio_UnimplementedError; }
+								
+	virtual OSStatus AFAPI_Initialize(
+									const FSRef							*inFileRef,
+                                    const AudioStreamBasicDescription	*inFormat,
+                                    UInt32								inFlags) { return kAudio_UnimplementedError; }
+								
+	virtual OSStatus AFAPI_Open(
+									const FSRef		*inFileRef, 
+									SInt8  			inPermissions,
+									SInt16			inRefNum) { return kAudio_UnimplementedError; }
+
+	virtual OSStatus AFAPI_OpenWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc)=0;
+
+	virtual OSStatus AFAPI_InitializeWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc,
+				UInt32								inFileType,
+				const AudioStreamBasicDescription	*inFormat,
+				UInt32								inFlags)=0;
+									
+	virtual OSStatus AFAPI_Close()=0;
+	virtual OSStatus AFAPI_Optimize()=0;
+	virtual OSStatus AFAPI_ReadBytes(		Boolean			inUseCache,
+											SInt64			inStartingByte, 
+											UInt32			*ioNumBytes, 
+											void			*outBuffer)=0;
+									
+	virtual OSStatus AFAPI_WriteBytes(		Boolean			inUseCache,
+											SInt64			inStartingByte, 
+											UInt32			*ioNumBytes, 
+											const void		*inBuffer)=0;
+									
+	virtual OSStatus AFAPI_ReadPackets(		Boolean							inUseCache,
+											UInt32							*outNumBytes,
+											AudioStreamPacketDescription	*outPacketDescriptions,
+											SInt64							inStartingPacket, 
+											UInt32  						*ioNumPackets, 
+											void							*outBuffer)=0;
+											
+	virtual OSStatus AFAPI_ReadPacketData(	Boolean							inUseCache,
+											UInt32							*ioNumBytes,
+											AudioStreamPacketDescription	*outPacketDescriptions,
+											SInt64							inStartingPacket, 
+											UInt32  						*ioNumPackets, 
+											void							*outBuffer)=0;
+									
+	virtual OSStatus AFAPI_WritePackets(	Boolean								inUseCache,
+											UInt32								inNumBytes,
+											const AudioStreamPacketDescription	*inPacketDescriptions,
+											SInt64								inStartingPacket, 
+											UInt32								*ioNumPackets, 
+											const void							*inBuffer)=0;
+									
+	virtual OSStatus AFAPI_GetPropertyInfo(	AudioFilePropertyID		inPropertyID,
+											UInt32					*outDataSize,
+											UInt32					*isWritable)=0;
+										
+	virtual OSStatus AFAPI_GetProperty(		AudioFilePropertyID		inPropertyID,
+											UInt32					*ioDataSize,
+											void					*ioPropertyData)=0;
+									
+	virtual OSStatus AFAPI_SetProperty(		AudioFilePropertyID		inPropertyID,
+											UInt32					inDataSize,
+											const void				*inPropertyData)=0;
+	virtual OSStatus AFAPI_GetGlobalInfoSize(		
+											AudioFilePropertyID		inPropertyID,
+											UInt32					inSpecifierSize,
+											const void*				inSpecifier,
+											UInt32					*outPropertySize);
+
+	virtual OSStatus AFAPI_GetGlobalInfo(		
+											AudioFilePropertyID		inPropertyID,
+											UInt32					inSpecifierSize,
+											const void*				inSpecifier,
+											UInt32					*ioPropertySize,
+											void					*ioPropertyData);
+
+	virtual OSStatus AFAPI_CountUserData(   UInt32					inUserDataID,
+											UInt32					*outNumberItems)=0;
+											
+	virtual OSStatus AFAPI_GetUserDataSize( UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					*outDataSize)=0;
+											
+	virtual OSStatus AFAPI_GetUserData(		UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					*ioDataSize,
+											void					*ioUserData)=0;
+											
+	virtual OSStatus AFAPI_SetUserData(		UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					inDataSize,
+											const void				*inUserData)=0;
+											
+	virtual OSStatus AFAPI_RemoveUserData(	UInt32				inUserDataID,
+											UInt32					inIndex)=0;
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	static OSStatus		ComponentEntryDispatch(ComponentParameters *p, AudioFileComponentBase *This);
+#endif
+
+protected:
+};
+
+
+
+class AudioFileObjectComponentBase : public AudioFileComponentBase
+{
+public:
+	AudioFileObjectComponentBase(AudioComponentInstance inInstance);
+	virtual ~AudioFileObjectComponentBase();
+
+	virtual AudioFileFormat* GetAudioFormat() const = 0;
+	virtual AudioFileFormatBase* GetAudioFileFormatBase() const { return GetAudioFormat(); }
+	
+	void SetAudioFileObject(AudioFileObject* inObject) { mAudioFileObject = inObject; }
+	
+	/* Public API Function Support */
+
+	virtual OSStatus AFAPI_CreateURL(
+								CFURLRef							inFileRef,
+                                const AudioStreamBasicDescription	*inFormat,
+                                UInt32								inFlags);
+
+	virtual OSStatus AFAPI_OpenURL(
+									CFURLRef		inFileRef, 
+									SInt8  			inPermissions,
+									int				inFD);
+
+	virtual OSStatus AFAPI_OpenWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc);
+
+	virtual OSStatus AFAPI_InitializeWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc,
+				UInt32								inFileType,
+				const AudioStreamBasicDescription	*inFormat,
+				UInt32								inFlags);
+									
+	virtual OSStatus AFAPI_Close();
+	virtual OSStatus AFAPI_Optimize();
+	virtual OSStatus AFAPI_ReadBytes(		Boolean			inUseCache,
+											SInt64			inStartingByte, 
+											UInt32			*ioNumBytes, 
+											void			*outBuffer);
+									
+	virtual OSStatus AFAPI_WriteBytes(		Boolean			inUseCache,
+											SInt64			inStartingByte, 
+											UInt32			*ioNumBytes, 
+											const void		*inBuffer);
+									
+	virtual OSStatus AFAPI_ReadPackets(		Boolean							inUseCache,
+											UInt32							*outNumBytes,
+											AudioStreamPacketDescription	*outPacketDescriptions,
+											SInt64							inStartingPacket, 
+											UInt32  						*ioNumPackets, 
+											void							*outBuffer);
+									
+	virtual OSStatus AFAPI_ReadPacketData(	Boolean							inUseCache,
+											UInt32							*ioNumBytes,
+											AudioStreamPacketDescription	*outPacketDescriptions,
+											SInt64							inStartingPacket, 
+											UInt32  						*ioNumPackets, 
+											void							*outBuffer);
+									
+	virtual OSStatus AFAPI_WritePackets(	Boolean								inUseCache,
+											UInt32								inNumBytes,
+											const AudioStreamPacketDescription	*inPacketDescriptions,
+											SInt64								inStartingPacket, 
+											UInt32								*ioNumPackets, 
+											const void							*inBuffer);
+									
+	virtual OSStatus AFAPI_GetPropertyInfo(	AudioFilePropertyID		inPropertyID,
+											UInt32					*outDataSize,
+											UInt32					*isWritable);
+										
+	virtual OSStatus AFAPI_GetProperty(		AudioFilePropertyID		inPropertyID,
+											UInt32					*ioDataSize,
+											void					*ioPropertyData);
+									
+	virtual OSStatus AFAPI_SetProperty(		AudioFilePropertyID		inPropertyID,
+											UInt32					inDataSize,
+											const void				*inPropertyData);
+
+	virtual OSStatus AFAPI_CountUserData(   UInt32					inUserDataID,
+											UInt32					*outNumberItems);
+											
+	virtual OSStatus AFAPI_GetUserDataSize( UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					*outDataSize);
+											
+	virtual OSStatus AFAPI_GetUserData(		UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					*ioDataSize,
+											void					*ioUserData);
+											
+	virtual OSStatus AFAPI_SetUserData(		UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					inDataSize,
+											const void				*inUserData);
+												
+	virtual OSStatus AFAPI_RemoveUserData(	UInt32					inUserDataID,
+											UInt32					inIndex);
+												
+protected:
+	AudioFileObject* mAudioFileObject;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp
new file mode 100644
index 0000000..ee6bedd
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp
@@ -0,0 +1,71 @@
+/*
+     File: AudioFileFormat.cpp
+ Abstract: AudioFileFormat.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AudioFileFormat.h"
+#include "DataSource.h"
+
+AudioFileFormatBase::AudioFileFormatBase(UInt32 inFileType) 
+	: mFileType(inFileType)
+{
+}
+
+AudioFileFormatBase::~AudioFileFormatBase()
+{
+}
+
+OSStatus AudioFileFormatBase::GetHFSCodes(UInt32* ioDataSize, void* outPropertyData)
+{
+	return kAudioFileUnsupportedPropertyError;
+}
+
+AudioFileFormat::AudioFileFormat(UInt32 inFileType) 
+	: AudioFileFormatBase(inFileType)
+{
+}
+
+AudioFileFormat::~AudioFileFormat()
+{
+}
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h
new file mode 100644
index 0000000..9436199
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h
@@ -0,0 +1,125 @@
+/*
+     File: AudioFileFormat.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef _AudioFileFormat_H_
+#define _AudioFileFormat_H_
+
+#include "AudioFileObject.h"
+
+// AudioFileFormat is a factory class for AudioFileObjects. 
+
+// UncertainResult is needed for DataIsThisFormat. 
+// In the case of SoundDesigner 2 we can't determine if the data is SoundDesigner 2 or not.
+
+typedef int UncertainResult;
+
+enum {
+	kFalse = 0,
+	kTrue = 1,
+	kCantDetermine = -1
+};
+
+class AudioFileHandle;
+class AudioFileFormat;
+class AudioFileFormatComponent;
+
+class AudioFileFormatBase
+{
+public:
+	AudioFileFormatBase(UInt32 inFileType);
+	virtual ~AudioFileFormatBase();
+	
+	// return true if extension is of this format type
+	virtual Boolean ExtensionIsThisFormat(CFStringRef inExtension) = 0;
+	
+	virtual UncertainResult FileDataIsThisFormat(
+				UInt32								/*inDataByteSize*/,
+				const void*							/*inData*/) = 0;
+	
+	// support SoundDesigner II files while minimizing opening and closing files.
+	virtual Boolean ResourceIsThisFormat(const FSRef* /*inRef*/) { return false; }
+
+	UInt32 GetFileType() const { return mFileType; }
+	
+	virtual UInt32 CanRead() const { return 1; }
+	virtual UInt32 CanWrite() const { return 1; }
+	virtual UInt32 HasResourceFork() const { return 0; }
+	
+	virtual void GetExtensions(CFArrayRef *outArray) = 0;
+	virtual void GetUTIs(CFArrayRef *outArray) {}
+	virtual void GetMIMETypes(CFArrayRef *outArray) {}
+	virtual void GetFileTypeName(CFStringRef *outName) = 0;
+	virtual OSStatus GetAvailableFormatIDs(UInt32* ioDataSize, void* outPropertyData) = 0;
+	virtual OSStatus GetAvailableStreamDescriptions(UInt32 inFormatID, UInt32* ioDataSize, void* outPropertyData) = 0;
+	virtual OSStatus GetHFSCodes(UInt32* ioDataSize, void* outPropertyData);
+	
+	virtual AudioFileFormat* AsAudioFileFormat() { return NULL; }
+	virtual AudioFileFormatComponent* AsAudioFileFormatComponent() { return NULL; }
+		
+private:
+	 UInt32 mFileType;
+};
+
+class AudioFileStreamObject;
+
+class AudioFileFormat : public AudioFileFormatBase
+{
+public:
+	AudioFileFormat(UInt32 inFileType);
+	virtual ~AudioFileFormat();
+	
+	// create an AudioFileObject for this format type.
+	virtual AudioFileObject* New() = 0; 
+	virtual AudioFileStreamObject* NewStream() { return NULL; }
+	
+	// return true if file is of this format type
+	virtual UncertainResult FileDataIsThisFormat(UInt32 inDataByteSize, const void* inData) = 0;				
+
+	virtual AudioFileFormat* AsAudioFileFormat() { return this; }
+};
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp
new file mode 100644
index 0000000..1a00f96
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp
@@ -0,0 +1,1966 @@
+/*
+     File: AudioFileObject.cpp
+ Abstract: AudioFileObject.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AudioFileObject.h"
+#include "CADebugMacros.h"
+#include <algorithm>
+#include <sys/stat.h>
+
+#define kAudioFileNoCacheMask		0x20
+
+const SInt64 kScanToEnd = 0x7fffFFFFffffFFFFLL;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+AudioFileObject::~AudioFileObject()
+{
+	delete mDataSource;
+	DeletePacketTable();
+	SetURL(NULL);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoCreate(		
+									CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat,
+									UInt32								inFlags)
+{
+	// common prologue
+	if (!IsDataFormatValid(inFormat))
+		return kAudioFileUnsupportedDataFormatError;
+
+	if (!IsDataFormatSupported(inFormat)) 
+		return kAudioFileUnsupportedDataFormatError;
+
+	SetPermissions(kAudioFileReadWritePermission);
+	
+	SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+	
+	// call virtual method for particular format.
+	return Create(inFileRef, inFormat);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                                
+OSStatus AudioFileObject::Create(		
+									CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat)
+{
+	int fileD;
+	OSStatus err = CreateDataFile (inFileRef, fileD);
+    FailIf (err != noErr, Bail, "CreateDataFile failed");
+	
+	SetURL (inFileRef);
+
+	err = OpenFile(kAudioFileReadWritePermission, fileD);
+    FailIf (err != noErr, Bail, "OpenFile failed");
+
+	err = SetDataFormat(inFormat);
+    FailIf (err != noErr, Bail, "SetDataFormat failed");
+	
+    mIsInitialized = false;
+	
+Bail:
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoOpen(	
+									CFURLRef		inFileRef, 
+									SInt8  			inPermissions,
+									int				inFD)
+{		
+	OSStatus err = noErr;
+	SetPermissions(inPermissions);
+	
+	err = Open(inFileRef, inPermissions, inFD);
+    FailIf (err != noErr, Bail, "Open failed");
+
+	err = ValidateFormatAndData();
+    FailIf (err != noErr, Bail, "ValidateFormatAndData failed");
+
+Bail:
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Open(			
+									CFURLRef		inFileRef, 
+									SInt8  			inPermissions,
+									int				inFD)
+{		
+	if (!(inPermissions & kAudioFileReadPermission))
+		return kAudioFilePermissionsError; // file must have read permissions
+ 
+	SetURL(inFileRef);
+	
+	OSStatus err = OpenFile(inPermissions, inFD);
+    FailIf (err != noErr, Bail, "OpenFile failed");
+		
+	err = OpenFromDataSource();
+    FailIf (err != noErr, Bail, "OpenFromDataSource failed");
+	
+Bail:
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ValidateFormatAndData()
+{
+	
+
+	AudioStreamBasicDescription asbd = GetDataFormat();
+
+	if (!IsDataFormatValid(&asbd))
+		return kAudioFileInvalidFileError;
+
+	if (asbd.mFormatID == kAudioFormatLinearPCM) 
+	{
+		SInt64 maxPackets = GetNumBytes() / asbd.mBytesPerPacket;
+		if (GetNumPackets() > maxPackets) 
+			return kAudioFileInvalidFileError;
+	}
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoOpenWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc)
+{
+	SInt8	perms = (inSetSizeFunc || inWriteFunc) ? kAudioFileReadWritePermission : kAudioFileReadPermission;
+	SetPermissions(perms);
+	
+	DataSource* dataSource = new Seekable_DataSource(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+	SetDataSource(dataSource);
+	return OpenFromDataSource();
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+							
+OSStatus AudioFileObject::OpenFromDataSource(void)
+{		
+	return noErr;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoInitializeWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc,
+                UInt32								inFileType,
+				const AudioStreamBasicDescription	*inFormat,
+				UInt32								inFlags)
+{		
+	DataSource* dataSource = new Seekable_DataSource(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+	if (!dataSource->CanWrite()) return -54/*permErr*/;
+	dataSource->SetSize(0);
+	SetDataSource(dataSource);
+	SetPermissions(kAudioFileReadWritePermission);
+
+	SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+	OSStatus err = SetDataFormat(inFormat);
+	if (err) return err;
+	
+	return InitializeDataSource(inFormat, inFlags);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+					
+OSStatus AudioFileObject::DoInitialize(	
+									CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat,
+									UInt32			inFlags)
+{
+	SetURL (inFileRef);
+	SetPermissions(kAudioFileReadWritePermission);
+
+	SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+	return Initialize(inFileRef, inFormat, inFlags);
+}
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+					
+OSStatus AudioFileObject::Initialize(	
+									CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat,
+									UInt32								inFlags)
+{
+	OSStatus err = noErr;
+		
+	UInt8 fPath[FILENAME_MAX];	
+	if (!CFURLGetFileSystemRepresentation (inFileRef, true, fPath, FILENAME_MAX))
+		return kAudio_FileNotFoundError;
+
+#if TARGET_OS_WIN32
+	int filePerms = 0;
+	int flags = O_TRUNC | O_RDWR | O_BINARY;
+#else
+	mode_t filePerms = 0;
+	int flags = O_TRUNC | O_RDWR;
+#endif
+
+	int fileD = open((const char*)fPath, flags, filePerms);
+	if (fileD < 0)
+		return AudioFileTranslateErrno(errno);
+	
+	err = OpenFile(kAudioFileReadWritePermission, fileD);
+    FailIf (err != noErr, Bail, "OpenFile failed");
+	
+		// don't need to do this as open has an option to truncate the file
+//	GetDataSource()->SetSize(0);
+
+	err = SetDataFormat(inFormat);
+    FailIf (err != noErr, Bail, "SetDataFormat failed");
+
+	InitializeDataSource(inFormat, inFlags);
+	
+Bail:	
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+							
+OSStatus AudioFileObject::InitializeDataSource(const AudioStreamBasicDescription	*inFormat, UInt32 /*inFlags*/)
+{		
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoClose()
+{
+	OSStatus err = UpdateSizeIfNeeded();
+	if (err) return err;
+	
+	return Close();
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Close()
+{
+    try {
+		delete mDataSource;
+		mDataSource = 0;
+	} catch (OSStatus err) {
+		return err;
+	} catch (...) {
+		return kAudioFileUnspecifiedError;
+	}
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+OSStatus AudioFileObject::Optimize()
+{
+	// default is that nothing needs to be done. This happens to be true for Raw, SD2 and NeXT/Sun types.
+	SetIsOptimized(true); 
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+OSStatus AudioFileObject::DoOptimize()
+{
+	if (!CanWrite()) return kAudioFilePermissionsError;
+
+	OSStatus err = UpdateSizeIfNeeded();
+	if (err) return err;
+	
+	if (IsOptimized()) return noErr;
+
+	err = Optimize();
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateNumBytes(SInt64 inNumBytes)	
+{
+    OSStatus err = noErr;
+	if (inNumBytes != GetNumBytes()) {
+		SetNumBytes(inNumBytes);
+        
+        // #warning " this will not work for vbr formats"
+		SetNumPackets(GetNumBytes() / mDataFormat.mBytesPerPacket);
+		SizeChanged();
+	}
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateNumPackets(SInt64 inNumPackets)	
+{
+    OSStatus err = noErr;
+	if (inNumPackets != GetNumPackets()) {
+		// sync current state.
+		SetNeedsSizeUpdate(true);
+		UpdateSizeIfNeeded();
+		SetNumPackets(inNumPackets);
+        
+        // #warning " this will not work for vbr formats"
+		SetNumBytes(GetNumPackets() * mDataFormat.mBytesPerFrame);
+		SizeChanged();
+	}
+	return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::PacketToFrame(SInt64 inPacket, SInt64& outFirstFrameInPacket)
+{
+	if (mDataFormat.mFramesPerPacket == 0)
+	{
+		OSStatus err = ScanForPackets(inPacket+1); // the packet count must be one greater than the packet index
+		if (err) return err;
+		
+		SInt64 packetTableSize = GetPacketTableSize();
+		
+		if (mPacketTable && inPacket >= packetTableSize)
+			return kAudioFileEndOfFileError;
+		
+		CompressedPacketTable* packetTable = GetPacketTable();
+		if (!packetTable)
+			return kAudioFileInvalidPacketOffsetError;
+			
+		if (inPacket < 0 || inPacket >= packetTableSize)
+			return kAudioFileInvalidPacketOffsetError;
+			
+		outFirstFrameInPacket = (*packetTable)[(size_t)inPacket].mFrameOffset;
+	}
+	else
+	{
+		outFirstFrameInPacket = inPacket * mDataFormat.mFramesPerPacket;
+	}
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::FrameToPacket(SInt64 inFrame, SInt64& outPacket, UInt32& outFrameOffsetInPacket)
+{
+	if (mDataFormat.mFramesPerPacket == 0)
+	{
+		CompressedPacketTable* packetTable = GetPacketTable();
+		if (!packetTable)
+			return kAudioFileInvalidPacketOffsetError;
+			
+		// search packet table
+		AudioStreamPacketDescriptionExtended pext;
+		memset(&pext, 0, sizeof(pext));
+		pext.mFrameOffset = inFrame;
+		CompressedPacketTable::iterator iter = std::lower_bound(packetTable->begin(), packetTable->end(), pext);
+		
+		if (iter == packetTable->end())
+			return kAudioFileInvalidPacketOffsetError;
+		
+		if (iter > packetTable->begin()) --iter;
+		
+		outPacket = iter - packetTable->begin();
+		outFrameOffsetInPacket = (UInt32)(inFrame - iter->mFrameOffset);
+	}
+	else
+	{
+		outPacket = inFrame / mDataFormat.mFramesPerPacket;
+		outFrameOffsetInPacket = (UInt32)(inFrame % mDataFormat.mFramesPerPacket);
+	}
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::PacketToByte(AudioBytePacketTranslation* abpt)
+{
+    if (abpt->mPacket < 0)
+        return kAudioFileInvalidPacketOffsetError;
+    
+	if (mDataFormat.mBytesPerPacket == 0)
+	{
+		CompressedPacketTable* packetTable = GetPacketTable();
+		if (!packetTable)
+			return kAudioFileInvalidPacketOffsetError;
+			
+		if (abpt->mPacket < GetPacketTableSize()) {
+			abpt->mByte = (*packetTable)[(int)abpt->mPacket].mStartOffset;
+			abpt->mFlags = 0;
+		} else {
+			SInt64 numPackets = packetTable->size();
+			if (numPackets < 8) 
+				return 'more' /*kAudioFileStreamError_DataUnavailable*/ ;
+				
+			const AudioStreamPacketDescriptionExtended lastPacket = (*packetTable)[numPackets - 1];
+			SInt64 bytesReadSoFar = lastPacket.mStartOffset + lastPacket.mDataByteSize;
+			double averageBytesPerPacket = (double)(bytesReadSoFar - GetDataOffset()) / (double)numPackets;
+			abpt->mByte = (SInt64)floor((double)abpt->mPacket * averageBytesPerPacket);
+			abpt->mFlags = kBytePacketTranslationFlag_IsEstimate;
+		}
+	}
+	else
+	{
+		abpt->mByte = abpt->mPacket * mDataFormat.mBytesPerPacket;
+		abpt->mFlags = 0;
+	}
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline bool byte_less_than (const AudioStreamPacketDescriptionExtended& a, const AudioStreamPacketDescriptionExtended& b)
+{
+	return a.mStartOffset < b.mStartOffset;
+}
+
+OSStatus AudioFileObject::ByteToPacket(AudioBytePacketTranslation* abpt)
+{
+    if (abpt->mByte < 0)
+        return kAudioFileInvalidPacketOffsetError;
+
+	if (mDataFormat.mBytesPerPacket == 0)
+	{
+		CompressedPacketTable* packetTable = GetPacketTable();
+		if (!packetTable)
+			return kAudioFileInvalidPacketOffsetError;
+			// search packet table
+		AudioStreamPacketDescriptionExtended pext;
+		memset(&pext, 0, sizeof(pext));
+		pext.mStartOffset = abpt->mByte;
+		CompressedPacketTable::iterator iter = std::lower_bound(packetTable->begin(), packetTable->end(), pext, byte_less_than);
+		
+		if (iter == packetTable->end()) {
+			SInt64 numPackets = packetTable->size();
+			if (numPackets < 8) 
+				return 'more' /*kAudioFileStreamError_DataUnavailable*/ ;
+				
+			const AudioStreamPacketDescriptionExtended lastPacket = (*packetTable)[numPackets - 1];
+			SInt64 bytesReadSoFar = lastPacket.mStartOffset + lastPacket.mDataByteSize;
+			double averageBytesPerPacket = (double)(bytesReadSoFar - GetDataOffset()) / (double)numPackets;
+			
+			double fpacket = (double)abpt->mByte / averageBytesPerPacket;
+			abpt->mPacket = (SInt64)floor(fpacket);
+			abpt->mByteOffsetInPacket = (UInt32)floor((fpacket - (double)abpt->mPacket) * averageBytesPerPacket);
+			abpt->mFlags = kBytePacketTranslationFlag_IsEstimate;
+			
+		} else {
+			if (iter > packetTable->begin()) --iter;
+			abpt->mPacket = iter - packetTable->begin();
+			abpt->mByteOffsetInPacket = (UInt32)(abpt->mByte - iter->mStartOffset);
+			abpt->mFlags = 0;
+		}
+	}
+	else
+	{
+		abpt->mPacket = abpt->mByte / mDataFormat.mBytesPerPacket;
+		abpt->mByteOffsetInPacket = (UInt32)(abpt->mByte % mDataFormat.mBytesPerPacket);
+		abpt->mFlags = 0;
+	}
+	return noErr;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadBytes(		
+								Boolean			inUseCache,
+								SInt64			inStartingByte, 
+								UInt32			*ioNumBytes, 
+								void			*outBuffer)
+{
+    OSStatus		err = noErr;
+    UInt16			mode = SEEK_SET;
+	SInt64 			fileOffset = mDataOffset + inStartingByte;
+    bool			readingPastEnd = false;
+	
+    FailWithAction((ioNumBytes == NULL) || (outBuffer == NULL), err = kAudio_ParamError, 
+		Bail, "invalid num bytes parameter");
+
+	//printf("inStartingByte %lld  GetNumBytes %lld\n", inStartingByte, GetNumBytes());
+
+	if (inStartingByte >= GetNumBytes()) 
+	{
+		*ioNumBytes = 0;
+		return kAudioFileEndOfFileError;
+	}
+
+	if ((fileOffset + *ioNumBytes) > (GetNumBytes() + mDataOffset)) 
+	{
+		*ioNumBytes = (UInt32)(GetNumBytes() + mDataOffset - fileOffset);
+		readingPastEnd = true;
+	}
+	//printf("fileOffset %lld  mDataOffset %lld  readingPastEnd %d\n", fileOffset, mDataOffset, readingPastEnd);
+
+    if (!inUseCache)
+        mode |= kAudioFileNoCacheMask;
+	
+    err = GetDataSource()->ReadBytes(mode, fileOffset, *ioNumBytes, outBuffer, ioNumBytes);
+	
+	if (readingPastEnd && err == noErr)
+		err = kAudioFileEndOfFileError;
+
+Bail:
+    return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::WriteBytes(	
+								Boolean			inUseCache,
+								SInt64			inStartingByte, 
+								UInt32			*ioNumBytes, 
+								const void		*inBuffer)
+{
+    OSStatus		err = noErr;
+    UInt16			mode = SEEK_SET;
+	bool			extendingTheAudioData;
+
+	if (!CanWrite()) return kAudioFilePermissionsError;
+
+    FailWithAction((ioNumBytes == NULL) || (inBuffer == NULL), err = kAudioFileUnspecifiedError, Bail, "invalid parameters");
+
+    // Do not try to write to a postion greater than 32 bits for some file types
+    // see if starting byte + ioNumBytes is greater than 32 bits
+    // if so, see if file type supports this and bail if not
+    err = IsValidFilePosition(inStartingByte + *ioNumBytes);
+    FailIf(err != noErr, Bail, "invalid file position");
+    
+    extendingTheAudioData = inStartingByte + *ioNumBytes > GetNumBytes();
+    
+    // if file is not optimized, then do not write data that would overwrite chunks following the sound data chunk
+    FailWithAction(	extendingTheAudioData && !IsOptimized(), 
+                    err = kAudioFileNotOptimizedError, Bail, "Can't write more data until the file is optimized");
+
+    if (!inUseCache)
+        mode |= kAudioFileNoCacheMask;
+    
+    err = GetDataSource()->WriteBytes(mode, mDataOffset + inStartingByte, *ioNumBytes, 
+                        inBuffer, ioNumBytes);
+	
+    FailIf(err != noErr, Bail, "couldn't write new data");
+    
+    if (extendingTheAudioData) {
+        SInt64		nuEOF;						// Get the total bytes of audio data
+        SInt64		nuByteTotal;
+
+		err = GetDataSource()->GetSize(nuEOF);
+		FailIf(err != noErr, Bail, "GetSize failed");
+            
+		nuByteTotal = nuEOF - mDataOffset;
+		err = UpdateNumBytes(nuByteTotal);
+    }
+    
+Bail:
+    return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPackets(	
+								Boolean							inUseCache,
+								UInt32							*outNumBytes,
+								AudioStreamPacketDescription	*outPacketDescriptions,
+								SInt64							inStartingPacket, 
+								UInt32  						*ioNumPackets, 
+								void							*outBuffer)
+{
+	// This only works with CBR. To suppport VBR you must override.
+    OSStatus		err = noErr;
+    
+    FailWithAction(outBuffer == NULL, err = kAudio_ParamError, Bail, "NULL buffer");
+	
+    FailWithAction((ioNumPackets == NULL) || (*ioNumPackets < 1), err = kAudio_ParamError, Bail, "invalid num packets parameter");
+    
+	{
+		UInt32			byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+		SInt64			startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+			
+		err = ReadBytes (inUseCache, startingByte, &byteCount, outBuffer);
+		if ((err == noErr) || (err == kAudioFileEndOfFileError))
+		{
+			if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket))
+			{
+				*ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+				byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+			}
+
+			if (outNumBytes)
+				*outNumBytes = byteCount;
+			
+			if (err == kAudioFileEndOfFileError)
+				err = noErr;
+		}
+	}
+Bail:
+    return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketData(	
+								Boolean							inUseCache,
+								UInt32							*ioNumBytes,
+								AudioStreamPacketDescription	*outPacketDescriptions,
+								SInt64							inStartingPacket, 
+								UInt32  						*ioNumPackets, 
+								void							*outBuffer)
+{
+	OSStatus		err = noErr;
+	FailWithAction(ioNumPackets == NULL || *ioNumPackets < 1, err = kAudio_ParamError, Bail, "invalid ioNumPackets parameter");
+	FailWithAction(ioNumBytes   == NULL || *ioNumBytes   < 1, err = kAudio_ParamError, Bail, "invalid ioNumBytes parameter");
+	if (mDataFormat.mBytesPerPacket) {
+	 	// CBR
+		FailWithAction(outBuffer    == NULL, err = kAudio_ParamError, Bail, "NULL buffer");
+		UInt32 maxPackets = *ioNumBytes / mDataFormat.mBytesPerPacket;
+		if (*ioNumPackets > maxPackets) *ioNumPackets = maxPackets;
+
+		if (outBuffer) {
+			UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+			SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+			err = ReadBytes (inUseCache, startingByte, &byteCount, outBuffer);
+			if (err == noErr || err == kAudioFileEndOfFileError) {
+				if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket)) {
+					*ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+					byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+				}
+				*ioNumBytes = byteCount;
+			}
+		}
+	} else {
+		FailWithAction(outPacketDescriptions   == NULL, err = kAudio_ParamError, Bail, "invalid outPacketDescriptions parameter");
+		err = ReadPacketDataVBR(inUseCache, ioNumBytes, outPacketDescriptions, inStartingPacket, ioNumPackets, outBuffer);
+	}
+Bail:
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketDataVBR(	
+								Boolean							inUseCache,
+								UInt32							*ioNumBytes,
+								AudioStreamPacketDescription	*outPacketDescriptions,
+								SInt64							inStartingPacket, 
+								UInt32  						*ioNumPackets, 
+								void							*outBuffer)
+{
+	OSStatus err = ScanForPackets(inStartingPacket+1); // need to scan packets up to start
+	if (err && err != kAudioFileEndOfFileError)
+		return err;
+
+	SInt64 dataOffset = GetDataOffset();
+
+	CompressedPacketTable* packetTable = GetPacketTable();
+    if (!packetTable) 
+		return kAudioFileInvalidFileError;
+
+	SInt64 packetTableSize = GetPacketTableSize();
+
+	if (inStartingPacket >= packetTableSize) {
+		*ioNumBytes = 0;
+		*ioNumPackets = 0;
+		return kAudioFileEndOfFileError;
+	}
+	
+	if (inStartingPacket + *ioNumPackets <= packetTableSize) {
+		err = ReadPacketDataVBR_InTable(inUseCache, ioNumBytes, outPacketDescriptions, inStartingPacket, ioNumPackets, outBuffer);
+	} else {
+
+		AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+		SInt64 firstPacketOffset = firstPacket.mStartOffset;
+		UInt32 bytesRead = *ioNumBytes;
+		SInt64 fileSize = 0;
+		GetDataSource()->GetSize(fileSize);
+		SInt64 remainingBytesInFile = fileSize - firstPacketOffset - dataOffset;
+		if (bytesRead > remainingBytesInFile)
+			bytesRead = (UInt32)remainingBytesInFile;
+		
+		err = ReadBytes (inUseCache, firstPacketOffset, &bytesRead, outBuffer);
+		if (err && err != kAudioFileEndOfFileError) {
+			*ioNumBytes = 0;
+			*ioNumPackets = 0;
+			return err;
+		}
+		
+		Buffer_DataSource bufSrc(bytesRead, outBuffer, dataOffset + firstPacketOffset);
+		
+		OSStatus scanErr = ScanForPackets(kScanToEnd, &bufSrc, false);
+		if (scanErr && scanErr != kAudioFileEndOfFileError)
+			return scanErr;
+		packetTableSize = packetTable->size();
+		
+		UInt32 numPacketsRead = 0;
+		UInt32 endOfData = 0;
+		SInt64 packetNumber = inStartingPacket;
+		for (; numPacketsRead < *ioNumPackets && packetNumber < packetTableSize; ++numPacketsRead, ++packetNumber) {
+			AudioStreamPacketDescription curPacket = (*packetTable)[numPacketsRead + inStartingPacket];
+			SInt64 curPacketOffset = curPacket.mStartOffset - firstPacketOffset;
+			SInt64 endOfPacket = curPacketOffset + curPacket.mDataByteSize;
+			if (endOfPacket > bytesRead) break;
+			endOfData = (UInt32)endOfPacket;
+			outPacketDescriptions[numPacketsRead] = curPacket;				
+			outPacketDescriptions[numPacketsRead].mStartOffset = curPacketOffset;
+		}
+		
+		*ioNumBytes = endOfData;
+		*ioNumPackets = numPacketsRead;
+	}
+    return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AudioFileObject::HowManyPacketsCanBeReadIntoBuffer(UInt32* ioNumBytes, SInt64 inStartingPacket, UInt32 *ioNumPackets)
+{		
+	CompressedPacketTable*	packetTable = GetPacketTable();
+	SInt64 packetTableSize = GetPacketTableSize();
+
+	if (inStartingPacket + *ioNumPackets > (SInt64)packetTableSize) {
+		*ioNumPackets = (UInt32)(packetTableSize - inStartingPacket);
+	}
+	
+	AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+
+	if (*ioNumBytes < firstPacket.mDataByteSize) {
+		*ioNumBytes = 0;
+		*ioNumPackets = 0;
+		return kAudio_ParamError;
+	}
+
+	SInt64 lastPacketIndex = inStartingPacket + *ioNumPackets - 1;
+	if (lastPacketIndex >= packetTableSize) 
+		lastPacketIndex = packetTableSize - 1;
+		
+	AudioStreamPacketDescription lastPacket = (*packetTable)[lastPacketIndex];
+	
+	SInt64 readBytes = lastPacket.mStartOffset + lastPacket.mDataByteSize - firstPacket.mStartOffset;
+	if (readBytes <= *ioNumBytes) {
+		*ioNumBytes = (UInt32)readBytes;
+		return noErr;
+	}
+	
+	SInt64 lowBound = inStartingPacket;
+	SInt64 highBound = lastPacketIndex + 1;
+	SInt64 okIndex = lowBound;
+	while (highBound >= lowBound) {		
+		SInt64 tryBound = (lowBound + highBound) >> 1;
+		if (tryBound > lastPacketIndex) 
+			break;
+		AudioStreamPacketDescription tryPacket = (*packetTable)[tryBound];
+		
+		SInt64 readBytes = tryPacket.mStartOffset + tryPacket.mDataByteSize - firstPacket.mStartOffset;
+		
+		if (readBytes > (SInt64)*ioNumBytes) {
+			highBound = tryBound - 1;
+		} else if (readBytes < (SInt64)*ioNumBytes) {
+			okIndex = tryBound;
+			lowBound = tryBound + 1;
+		} else {
+			okIndex = tryBound;
+			break;
+		}
+	}	
+	
+	SInt64 numPackets = okIndex - inStartingPacket + 1;
+	if (numPackets > *ioNumPackets) {
+		numPackets = *ioNumPackets;
+		okIndex = inStartingPacket + numPackets - 1;
+	}
+	
+	AudioStreamPacketDescription packet = (*packetTable)[okIndex];
+	*ioNumBytes = (UInt32)(packet.mStartOffset + packet.mDataByteSize - firstPacket.mStartOffset);
+	*ioNumPackets = (UInt32)numPackets;
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketDataVBR_InTable(	
+								Boolean							inUseCache,
+								UInt32							*ioNumBytes,
+								AudioStreamPacketDescription	*outPacketDescriptions,
+								SInt64							inStartingPacket, 
+								UInt32  						*ioNumPackets, 
+								void							*outBuffer)
+{
+	CompressedPacketTable* packetTable = GetPacketTable();
+    if (!packetTable) 
+		return kAudioFileInvalidFileError;
+	
+	OSStatus err = HowManyPacketsCanBeReadIntoBuffer(ioNumBytes, inStartingPacket, ioNumPackets);
+	if (err) return err;
+			
+	AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+	SInt64 firstPacketOffset = firstPacket.mStartOffset;
+	UInt32 bytesRead = *ioNumBytes;
+	
+	if (outBuffer) {
+		err = ReadBytes (inUseCache, firstPacketOffset, &bytesRead, outBuffer);
+		if (err && err != kAudioFileEndOfFileError) {
+			*ioNumBytes = 0;
+			*ioNumPackets = 0;
+			return err;
+		}
+		*ioNumBytes = bytesRead;
+	}
+	
+	// fill out packet descriptions
+	if (outPacketDescriptions) {						
+		for (UInt32 i = 0; i < *ioNumPackets; i++) {
+			AudioStreamPacketDescription curPacket = (*packetTable)[i + inStartingPacket];
+			outPacketDescriptions[i] = curPacket;				
+			outPacketDescriptions[i].mStartOffset = curPacket.mStartOffset - firstPacketOffset;
+		}
+	}
+
+    return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::WritePackets(	
+									Boolean								inUseCache,
+                                    UInt32								inNumBytes,
+                                    const AudioStreamPacketDescription	*inPacketDescriptions,
+                                    SInt64								inStartingPacket, 
+                                    UInt32								*ioNumPackets, 
+                                    const void							*inBuffer)
+{
+	// This only works with CBR. To suppport VBR you must override.
+    OSStatus		err = noErr;
+    
+    FailWithAction(inStartingPacket > GetNumPackets(), err = kAudioFileInvalidPacketOffsetError, Bail, "write past end");
+    FailWithAction((ioNumPackets == NULL) || (inBuffer == NULL), err = kAudioFileUnspecifiedError, Bail, "invalid parameter");
+	
+	{
+		UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+		SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+
+		err = WriteBytes(inUseCache, startingByte, &byteCount, inBuffer);
+		FailIf (err != noErr, Bail, "Write Bytes Failed");
+
+		if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket))
+			*ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+	}
+Bail:
+    return (err);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetBitRate(			UInt32					*outBitRate)
+{
+	
+	if (!outBitRate) return kAudioFileUnspecifiedError;
+    
+	UInt32 bytesPerPacket = GetDataFormat().mBytesPerPacket;
+	UInt32 framesPerPacket = GetDataFormat().mFramesPerPacket;
+	Float64 sampleRate = GetDataFormat().mSampleRate;
+	const Float64 bitsPerByte = 8.;
+	
+	if (bytesPerPacket && framesPerPacket) {
+		*outBitRate = (UInt32)(bitsPerByte * (Float64)bytesPerPacket * sampleRate / (Float64)framesPerPacket);
+	} else {		
+		SInt64 numPackets = GetNumPackets();
+		SInt64 numBytes = GetNumBytes();
+		SInt64 numFrames = 0;
+		
+		if (framesPerPacket) {
+			numFrames = numPackets * framesPerPacket;
+		} else {
+			// count frames
+			CompressedPacketTable* packetTable = GetPacketTable();
+			if (packetTable) {
+                if (packetTable->size() != numPackets) {
+                    return kAudioFileInvalidFileError;
+                }
+#if !TARGET_OS_WIN32
+				for (ssize_t i = 0; i < numPackets; i++)
+#else
+				for (int i = 0; i < numPackets; i++)
+#endif
+				{
+					numFrames += (*packetTable)[i].mVariableFramesInPacket;
+				}		
+			} else {
+				return kAudioFileUnsupportedPropertyError;
+			}
+		}
+        
+        if (numFrames == 0 || (sampleRate == 0.)) {
+            *outBitRate = 0;
+            return noErr;
+        }
+		Float64 duration = (Float64)numFrames / sampleRate;
+		*outBitRate = (UInt32)(bitsPerByte * (Float64)numBytes / duration);
+	}
+
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMagicCookieDataSize(
+												UInt32					*outDataSize,
+												UInt32					*isWritable)
+{
+	if (outDataSize)  *outDataSize = 0;
+	if (isWritable)  *isWritable = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMagicCookieData(
+												UInt32					*ioDataSize,
+												void					*ioPropertyData)
+{
+	*ioDataSize = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetMagicCookieData(	UInt32					/*inDataSize*/,
+												const void				*inPropertyData)
+{
+	return kAudioFileInvalidChunkError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMarkerListSize(
+												UInt32					*outDataSize,
+												UInt32					*isWritable)
+{
+	if (outDataSize) *outDataSize = 0;
+	if (isWritable) *isWritable = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMarkerList(
+												UInt32					*ioDataSize,
+												AudioFileMarkerList*	/*ioPropertyData*/)
+{
+	*ioDataSize = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetMarkerList(	UInt32						/*inDataSize*/,
+											const AudioFileMarkerList*  /*inPropertyData*/)
+{
+	return kAudioFileUnsupportedPropertyError;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetRegionListSize(
+												UInt32					*outDataSize,
+												UInt32					*isWritable)
+{
+	if (outDataSize) *outDataSize = 0;
+	if (isWritable) *isWritable = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetRegionList(
+												UInt32					*ioDataSize,
+												AudioFileRegionList		*ioPropertyData)
+{
+	*ioDataSize = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetRegionList(	UInt32						/*inDataSize*/,
+											const AudioFileRegionList*   /*inPropertyData*/)
+{
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetChannelLayoutSize(
+												UInt32					*outDataSize,
+												UInt32					*isWritable)
+{
+	if (outDataSize) *outDataSize = 0;
+	if (isWritable) *isWritable = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetChannelLayout(
+												UInt32						*ioDataSize,
+												AudioChannelLayout*			/*ioPropertyData*/)
+{
+	*ioDataSize = 0;
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetChannelLayout(	UInt32						/*inDataSize*/,
+											const AudioChannelLayout*   /*inPropertyData*/)
+{
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetInfoDictionarySize(		UInt32						*outDataSize,
+									UInt32						*isWritable)
+{
+	if (outDataSize) *outDataSize = sizeof(CFDictionaryRef);
+	if (isWritable) *isWritable = 0;
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+												
+OSStatus AudioFileObject::GetInfoDictionary(CACFDictionary  *infoDict)
+{	
+	Float64 fl;
+	if (GetEstimatedDuration(&fl) == noErr)
+		return AddDurationToInfoDictionary(infoDict, fl);
+		
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+												
+OSStatus AudioFileObject::SetInfoDictionary(CACFDictionary *infoDict)
+{
+	return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AudioFileObject::GetEstimatedDuration(Float64*		duration)
+{
+	// calculate duration
+	AudioStreamBasicDescription		ASBD = GetDataFormat();
+		
+	*duration  = (ASBD.mFramesPerPacket != 0) ? (GetNumPackets() * ASBD.mFramesPerPacket) / ASBD.mSampleRate : 0.0;
+	
+	/*
+		For now, assume that any ASBD that has zero in the frames per packet field has been subclassed for this
+		method. i.e. A CAF file has a frame count in one of it's chunks.
+		
+		MP3 has been subclassed because it guesstimates a duration so the entire file does not 
+		need to be parsed in order to calculate the total frames.
+	*/
+	
+	return noErr;
+
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetPropertyInfo	(	
+                                        AudioFilePropertyID		inPropertyID,
+                                        UInt32					*outDataSize,
+                                        UInt32					*isWritable)
+{
+    OSStatus		err = noErr;
+    UInt32			writable = 0;
+        
+    switch (inPropertyID)
+    {
+		case kAudioFilePropertyDeferSizeUpdates :
+            if (outDataSize) *outDataSize = sizeof(UInt32);
+            writable = 1;
+            break;
+
+        case kAudioFilePropertyFileFormat:
+            if (outDataSize) *outDataSize = sizeof(UInt32);
+            writable = 0;
+            break;
+
+        case kAudioFilePropertyDataFormat:
+            if (outDataSize) *outDataSize = sizeof(AudioStreamBasicDescription);
+            writable = 1;
+            break;
+                        
+		case kAudioFilePropertyFormatList:
+			err = GetFormatListInfo(*outDataSize, writable);
+            break;
+		
+		case kAudioFilePropertyPacketSizeUpperBound:
+        case kAudioFilePropertyIsOptimized:
+        case kAudioFilePropertyMaximumPacketSize:
+            if (outDataSize) *outDataSize = sizeof(UInt32);
+            writable = 0;
+            break;
+
+        case kAudioFilePropertyAudioDataByteCount:
+        case kAudioFilePropertyAudioDataPacketCount:
+            writable = 1;
+            if (outDataSize) *outDataSize = sizeof(SInt64);
+            break;
+
+		case kAudioFilePropertyDataOffset:
+            writable = 0;
+            if (outDataSize) *outDataSize = sizeof(SInt64);
+            break;
+
+		case kAudioFilePropertyBitRate:            
+            writable = 0;
+            if (outDataSize) *outDataSize = sizeof(UInt32);
+			break;
+
+		case kAudioFilePropertyMagicCookieData:            
+            err = GetMagicCookieDataSize(outDataSize, &writable);
+			break;
+
+		case kAudioFilePropertyMarkerList :
+            err = GetMarkerListSize(outDataSize, &writable);			
+			break;
+			
+		case kAudioFilePropertyRegionList :
+            err = GetRegionListSize(outDataSize, &writable);			
+			break;
+			
+		case kAudioFilePropertyChannelLayout :
+            err = GetChannelLayoutSize(outDataSize, &writable);			
+			break;
+
+		case kAudioFilePropertyPacketToFrame :
+		case kAudioFilePropertyFrameToPacket :
+            if (outDataSize) *outDataSize = sizeof(AudioFramePacketTranslation);
+            writable = 0;
+			break;
+
+		case kAudioFilePropertyPacketToByte :
+		case kAudioFilePropertyByteToPacket :
+            if (outDataSize) *outDataSize = sizeof(AudioBytePacketTranslation);
+            writable = 0;
+			break;
+
+        case kAudioFilePropertyInfoDictionary :
+            err = GetInfoDictionarySize(outDataSize, &writable);			
+            break;
+
+        case kTEMPAudioFilePropertySoundCheckDictionary :
+            err = GetSoundCheckDictionarySize(outDataSize, &writable);			
+            break;
+
+		case kTEMPAudioFilePropertyGenerateLoudnessInfo :
+            err = GetLoudnessInfoSize(outDataSize, &writable);
+            writable = 0;
+            break;
+
+		case kTEMPAudioFilePropertyLoudnessInfo :
+            err = GetLoudnessInfoSize(outDataSize, &writable);
+            break;
+
+		case kAudioFilePropertyEstimatedDuration :
+            if (outDataSize) *outDataSize = sizeof(Float64);
+            writable = 0;
+			break;
+
+		case 'LYRC':
+			if (outDataSize) *outDataSize = sizeof(CFStringRef);
+			if (isWritable) *isWritable = 0;
+			break;
+
+		case 'eof?':
+			if (outDataSize) *outDataSize = sizeof(UInt32);
+			if (isWritable) *isWritable = 0;
+			break;
+
+		case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+			if (outDataSize) *outDataSize = sizeof(SInt32);
+			if (isWritable) *isWritable = CanWrite();
+			break;
+		
+        default:
+            writable = 0;
+            err = kAudioFileUnsupportedPropertyError;
+            break;
+    }
+
+    if (isWritable)
+        *isWritable = writable;
+    return (err);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus	AudioFileObject::GetProperty(
+                                    AudioFilePropertyID		inPropertyID,
+                                    UInt32					*ioDataSize,
+                                    void					*ioPropertyData)
+{
+    OSStatus		err = noErr;
+	UInt32			neededSize;
+    UInt32			writable;
+	
+    switch (inPropertyID)
+    {
+        case kAudioFilePropertyFileFormat:
+            FailWithAction(*ioDataSize != sizeof(UInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+				
+            *(UInt32 *) ioPropertyData = GetFileType();
+            break;
+
+		case kAudioFilePropertyFormatList:
+			err = GetFormatList(*ioDataSize, (AudioFormatListItem*)ioPropertyData);
+            break;
+		
+        case kAudioFilePropertyDataFormat:
+            FailWithAction(*ioDataSize != sizeof(AudioStreamBasicDescription), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+				
+            memcpy(ioPropertyData, &mDataFormat, sizeof(AudioStreamBasicDescription));
+            break;
+		case kAudioFilePropertyDataOffset:
+            FailWithAction(*ioDataSize != sizeof(SInt64), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+            *(SInt64 *) ioPropertyData = mDataOffset;
+			break;
+        case kAudioFilePropertyIsOptimized:
+            FailWithAction(*ioDataSize != sizeof(UInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+            *(UInt32 *) ioPropertyData = mIsOptimized;
+            break;
+
+        case kAudioFilePropertyAudioDataByteCount:
+            FailWithAction(*ioDataSize != sizeof(SInt64), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+            *(SInt64 *)ioPropertyData = GetNumBytes();
+            break;
+
+        case kAudioFilePropertyAudioDataPacketCount:
+            FailWithAction(*ioDataSize != sizeof(SInt64), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+            *(SInt64 *)ioPropertyData = GetNumPackets();
+            break;
+
+		case kAudioFilePropertyPacketSizeUpperBound:
+            FailWithAction(*ioDataSize != sizeof(UInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+            *(UInt32 *)ioPropertyData = GetPacketSizeUpperBound();
+            break;
+			
+        case kAudioFilePropertyMaximumPacketSize:
+            FailWithAction(*ioDataSize != sizeof(UInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+            *(UInt32 *)ioPropertyData = FindMaximumPacketSize();
+            break;
+
+
+         case kAudioFilePropertyBitRate:            
+            FailWithAction(*ioDataSize != sizeof(UInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+			err = GetBitRate((UInt32*)ioPropertyData);
+            break;
+
+         case kAudioFilePropertyMagicCookieData:            
+            
+			err = GetMagicCookieData(ioDataSize, ioPropertyData);
+            break;
+
+		case kAudioFilePropertyMarkerList :
+            err = GetMarkerList(ioDataSize, static_cast<AudioFileMarkerList*>(ioPropertyData));			
+			break;
+			
+		case kAudioFilePropertyRegionList :
+			memset(ioPropertyData, 0, *ioDataSize);
+            err = GetRegionList(ioDataSize, static_cast<AudioFileRegionList*>(ioPropertyData));			
+			break;
+			
+		case kAudioFilePropertyChannelLayout :
+			err = GetChannelLayoutSize(&neededSize, &writable);
+            FailIf(err, Bail, "GetChannelLayoutSize failed");
+            FailWithAction(*ioDataSize != neededSize, err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+			
+            err = GetChannelLayout(ioDataSize, static_cast<AudioChannelLayout*>(ioPropertyData));			
+			break;
+						
+		case kAudioFilePropertyDeferSizeUpdates :
+            FailWithAction(*ioDataSize != sizeof(UInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+				
+            *(UInt32 *) ioPropertyData = DeferSizeUpdates();
+            break;
+
+		case kAudioFilePropertyPacketToFrame : 
+		{
+            FailWithAction(*ioDataSize != sizeof(AudioFramePacketTranslation), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+			
+			AudioFramePacketTranslation* afpt = (AudioFramePacketTranslation*)ioPropertyData;
+			err = PacketToFrame(afpt->mPacket, afpt->mFrame);
+			break;
+		}	
+		case kAudioFilePropertyFrameToPacket :
+		{
+            FailWithAction(*ioDataSize != sizeof(AudioFramePacketTranslation), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			AudioFramePacketTranslation* afpt = (AudioFramePacketTranslation*)ioPropertyData;
+			err = FrameToPacket(afpt->mFrame, afpt->mPacket, afpt->mFrameOffsetInPacket);
+			break;
+		}
+
+		case kAudioFilePropertyPacketToByte : 
+		{
+            FailWithAction(*ioDataSize != sizeof(AudioBytePacketTranslation), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+			
+			AudioBytePacketTranslation* abpt = (AudioBytePacketTranslation*)ioPropertyData;
+			err = PacketToByte(abpt);
+			break;
+		}	
+		case kAudioFilePropertyByteToPacket :
+		{
+            FailWithAction(*ioDataSize != sizeof(AudioBytePacketTranslation), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			AudioBytePacketTranslation* abpt = (AudioBytePacketTranslation*)ioPropertyData;
+			err = ByteToPacket(abpt);
+			break;
+		}
+
+        case kAudioFilePropertyInfoDictionary :
+		{
+            FailWithAction(*ioDataSize != sizeof(CFDictionaryRef), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			CACFDictionary		afInfoDictionary(true);
+
+            err = GetInfoDictionary(&afInfoDictionary);			
+            
+			if (!err)
+			{
+				*(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+			}
+            break;
+		}
+
+        case kTEMPAudioFilePropertySoundCheckDictionary :
+		{
+            FailWithAction(*ioDataSize != sizeof(CFDictionaryRef), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			CACFDictionary		afInfoDictionary(true);
+
+            err = GetSoundCheckDictionary(&afInfoDictionary);
+            if (err) {
+				OSStatus err2 = GetSoundCheckDictionaryFromLoudnessInfo(&afInfoDictionary);
+				if (err2 == noErr) err = noErr; // else report original error from GetSoundCheckDictionary.
+			}
+            
+			if (!err)
+			{
+				*(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+			}
+            break;
+		}
+
+        case kTEMPAudioFilePropertyLoudnessInfo :
+		{
+            FailWithAction(*ioDataSize != sizeof(CFDictionaryRef), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			CACFDictionary		afInfoDictionary(true);
+
+            err = GetLoudnessInfo(&afInfoDictionary);
+            if (err) {
+				OSStatus err2 = GetLoudnessInfoFromSoundCheckDictionary(&afInfoDictionary);
+				if (err2 == noErr) err = noErr; // else report original error from GetLoudnessInfo.
+			}
+			
+			if (!err) 
+			{
+				*(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+			}
+            break;
+		}
+
+		case kTEMPAudioFilePropertyGenerateLoudnessInfo :
+		{
+            FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			CACFDictionary		afInfoDictionary(true);
+
+            err = GenerateLoudnessInfo(&afInfoDictionary);			
+            
+			if (!err)
+			{
+				*(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+			}
+            break;
+		}
+
+		case kAudioFilePropertyEstimatedDuration :
+		{
+            FailWithAction(*ioDataSize != sizeof(Float64), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+		
+			err = GetEstimatedDuration((Float64*)ioPropertyData); 
+			break;
+		}
+
+        case 'LYRC' :
+            if (*ioDataSize < sizeof(CFStringRef))
+                return kAudioFileBadPropertySizeError;
+
+			*ioDataSize = sizeof(CFStringRef);
+			err = GetLyrics((CFStringRef*) ioPropertyData);
+			break;
+	
+		case 'eof?' : 
+		{
+            if (*ioDataSize != sizeof(UInt32))
+                return kAudioFileBadPropertySizeError;
+			
+			SInt64 pos;
+			err = GetDataSource()->GetPos(pos);
+			if (err) break;
+			
+			SInt64 endOfData = GetDataOffset() + GetNumBytes();
+			*(UInt32*)ioPropertyData = pos >= endOfData;
+			
+			break;
+		}	
+		case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+		{
+            if (*ioDataSize != sizeof(SInt32))
+                return kAudioFileBadPropertySizeError;
+
+			SInt32 outValue = 0;
+			err = GetSourceBitDepth(outValue);
+			if ((err || outValue == 0) && GetDataFormat().mFormatID == kAudioFormatLinearPCM) {
+				// if there was no stored source bit depth, and this file is LPCM, then report this file's bit depth.
+				err = noErr;
+				outValue = GetDataFormat().mBitsPerChannel;
+				if (GetDataFormat().mFormatFlags & kAudioFormatFlagIsFloat) 
+					outValue = -outValue;
+			} else if (err) 
+				break;
+			
+			*(SInt32 *) ioPropertyData = outValue;
+			
+			break;
+		}	
+		default:
+            err = kAudioFileUnsupportedPropertyError;			
+            break;
+    }
+
+Bail:
+    return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus	AudioFileObject::SetProperty(
+                                    AudioFilePropertyID		inPropertyID,
+                                    UInt32					inDataSize,
+                                    const void				*inPropertyData)
+{
+    OSStatus		err = noErr;
+
+    switch (inPropertyID)
+    {
+        case kAudioFilePropertyDataFormat:
+            FailWithAction(inDataSize != sizeof(AudioStreamBasicDescription), 
+				err = kAudioFileBadPropertySizeError, Bail, "Incorrect data size");
+            err = UpdateDataFormat((AudioStreamBasicDescription *) inPropertyData);
+			break;
+		case kAudioFilePropertyFormatList:
+			err = SetFormatList(inDataSize, (AudioFormatListItem*)inPropertyData);
+            break;
+		
+        case kAudioFilePropertyAudioDataByteCount: {
+            FailWithAction(inDataSize != sizeof(SInt64), err = kAudioFileBadPropertySizeError, Bail, "Incorrect data size");
+            SInt64 numBytes = *(SInt64 *) inPropertyData;
+			if (numBytes > GetNumBytes()) {
+				// can't use this to increase data size.
+				return kAudioFileOperationNotSupportedError;
+			}
+			UInt32 saveDefer = DeferSizeUpdates();
+			SetDeferSizeUpdates(0); // force an update.
+			err = UpdateNumBytes(numBytes);
+			SetDeferSizeUpdates(saveDefer);
+		} break;
+
+		case kAudioFilePropertyAudioDataPacketCount: {
+			SInt64 numPackets = *(SInt64 *) inPropertyData;
+			if (numPackets > GetNumPackets()) {
+				// can't use this to increase data size.
+				return kAudioFileOperationNotSupportedError;
+			}
+			err = UpdateNumPackets(numPackets);
+		} break;
+		
+		case kAudioFilePropertyMagicCookieData:            
+			err = SetMagicCookieData(inDataSize, inPropertyData);
+			break;
+
+
+		case kAudioFilePropertyMarkerList :
+            err = SetMarkerList(inDataSize, static_cast<const AudioFileMarkerList*>(inPropertyData));			
+			break;
+			
+		case kAudioFilePropertyRegionList :
+            err = SetRegionList(inDataSize, static_cast<const AudioFileRegionList*>(inPropertyData));			
+			break;
+			
+		case kAudioFilePropertyChannelLayout :
+            err = SetChannelLayout(inDataSize, static_cast<const AudioChannelLayout*>(inPropertyData));			
+			break;
+
+		case kAudioFilePropertyDeferSizeUpdates :
+            FailWithAction(inDataSize != sizeof(UInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+            SetDeferSizeUpdates(*(UInt32 *) inPropertyData);
+            break;
+
+        case kAudioFilePropertyInfoDictionary :
+		{
+            FailWithAction(inDataSize != sizeof(CFDictionaryRef), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			// pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+			// Let the caller release their own CFObject so pass false for th erelease parameter
+			CACFDictionary		afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+            err = SetInfoDictionary(&afInfoDictionary);			
+            
+            break;
+		}
+			
+        case kTEMPAudioFilePropertySoundCheckDictionary :
+		{
+            FailWithAction(inDataSize != sizeof(CFDictionaryRef), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			// pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+			// Let the caller release their own CFObject so pass false for the release parameter
+			CACFDictionary		afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+            err = SetSoundCheckDictionary(&afInfoDictionary);			
+            
+            break;
+		}
+
+        case kTEMPAudioFilePropertyLoudnessInfo :
+		{
+            FailWithAction(inDataSize != sizeof(CFDictionaryRef), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			// pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+			// Let the caller release their own CFObject so pass false for the release parameter
+			CACFDictionary		afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+            err = SetLoudnessInfo(&afInfoDictionary);			
+            
+            break;
+		}
+			
+  		case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+		{
+            FailWithAction(inDataSize != sizeof(SInt32), 
+				err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+			SInt32 inValue = *(SInt32 *)inPropertyData;
+			err = SetSourceBitDepth(inValue);
+			
+			break;
+		}	
+
+      default:
+            err = kAudioFileUnsupportedPropertyError;			
+		break;
+    }
+
+Bail:
+    return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetDataFormat(const AudioStreamBasicDescription* inStreamFormat)
+{
+	OSStatus err = noErr;
+	
+	if (!IsDataFormatValid(inStreamFormat))
+		return kAudioFileUnsupportedDataFormatError;
+
+	if (!IsDataFormatSupported(inStreamFormat)) 
+		return kAudioFileUnsupportedDataFormatError;
+	
+	UInt32 prevBytesPerPacket = mDataFormat.mBytesPerPacket;
+	
+	mDataFormat = *inStreamFormat;
+	
+	// if CBR and bytes per packet changes, we need to change the number of packets we think we have.
+	if (mDataFormat.mBytesPerPacket && mDataFormat.mBytesPerPacket != prevBytesPerPacket)
+	{
+		SInt64 numPackets = GetNumBytes() / mDataFormat.mBytesPerPacket;
+		SetNumPackets(numPackets);
+		SetMaximumPacketSize(mDataFormat.mBytesPerPacket);
+
+		if (!mFirstSetFormat)
+			SizeChanged();
+	}
+	
+	mFirstSetFormat = false;
+	
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetFormatListInfo(	UInt32				&outDataSize,
+													UInt32				&outWritable)
+{
+	// default implementation is to just return the data format
+	outDataSize = sizeof(AudioFormatListItem);
+	outWritable = false;
+	return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetFormatList(	UInt32									&ioDataSize,
+												AudioFormatListItem						*ioPropertyData)
+{
+	// default implementation is to just return the data format
+	if (ioDataSize < sizeof(AudioFormatListItem))
+		return kAudioFileBadPropertySizeError;
+	
+	AudioFormatListItem afli;
+	afli.mASBD = mDataFormat;
+	AudioChannelLayoutTag layoutTag = /*kAudioChannelLayoutTag_Unknown*/ 0xFFFF0000 | mDataFormat.mChannelsPerFrame;
+	UInt32 layoutSize, isWritable;
+	OSStatus err = GetChannelLayoutSize(&layoutSize, &isWritable);
+	if (err == noErr)
+	{
+		CAAutoFree<AudioChannelLayout> layout;
+		layout.allocBytes(layoutSize);
+		err = GetChannelLayout(&layoutSize, layout());
+		if (err == noErr) {
+			layoutTag = layout->mChannelLayoutTag;
+		}
+	}
+	afli.mChannelLayoutTag = layoutTag;	
+	
+	memcpy(ioPropertyData, &afli, sizeof(AudioFormatListItem));
+	
+	ioDataSize = sizeof(AudioFormatListItem);
+	return noErr;
+}
+										
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetFormatList(	UInt32									inDataSize,
+											const AudioFormatListItem				*inPropertyData)
+{
+	return kAudioFileOperationNotSupportedError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateDataFormat(const AudioStreamBasicDescription* inStreamFormat)
+{
+	return SetDataFormat(inStreamFormat);
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Boolean AudioFileObject::IsDataFormatValid(AudioStreamBasicDescription const* inDesc)
+{
+	if (inDesc->mSampleRate < 0.)
+		return false;
+
+	if (inDesc->mSampleRate > 3e6)
+		return false;
+
+	if (inDesc->mChannelsPerFrame < 1 || inDesc->mChannelsPerFrame > 0x000FFFFF)
+		return false;
+
+	if (inDesc->mFormatID == kAudioFormatLinearPCM)
+	{			
+		if (inDesc->mBitsPerChannel < 1 || inDesc->mBitsPerChannel > 64)
+			return false;
+			
+		if (inDesc->mFramesPerPacket != 1)
+			return false;
+			
+		if (inDesc->mBytesPerPacket == 0) 
+			return false;
+
+		if (inDesc->mBytesPerFrame != inDesc->mBytesPerPacket)
+			return false;
+			
+		// [3605260] we assume here that a packet is an integer number of frames.
+		UInt32 minimumBytesPerPacket = (inDesc->mBitsPerChannel * inDesc->mChannelsPerFrame + 7) / 8;
+		if (inDesc->mBytesPerPacket < minimumBytesPerPacket) 
+			return false;
+	}
+	return true;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void AudioFileObject::SetDataSource(DataSource* inDataSource)	
+{
+	if (mDataSource != inDataSource) {
+		delete mDataSource;
+		mDataSource = inDataSource;
+	}
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void	AudioFileObject::SetURL (CFURLRef inURL)
+{
+	if (mFileRef == inURL) return;
+	if (inURL) CFRetain (inURL);
+	if (mFileRef) CFRelease(mFileRef);
+	mFileRef = inURL;
+}
+
+OSStatus AudioFileObject::OpenFile(SInt8 inPermissions, int inFD)
+{
+	OSStatus err = noErr;
+
+	SetDataSource(new Cached_DataSource(new UnixFile_DataSource(inFD, inPermissions, true)));
+	
+	mFileD = inFD;
+	SetPermissions (inPermissions);
+
+	return err;
+}
+								
+OSStatus AudioFileObject::CreateDataFile (CFURLRef	inFileRef, int	&outFileD)
+{	 
+	UInt8 fPath[FILENAME_MAX];	
+	if (!CFURLGetFileSystemRepresentation (inFileRef, true, fPath, FILENAME_MAX))
+		return kAudio_FileNotFoundError;
+	
+	struct stat stbuf;
+	if (stat ((const char*)fPath, &stbuf) == 0) 
+		return kAudioFilePermissionsError;
+
+#if TARGET_OS_WIN32
+	int filePerms = S_IREAD | S_IWRITE;
+	int flags = O_CREAT | O_EXCL | O_RDWR | O_BINARY;
+#else
+	mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+	int flags = O_CREAT | O_EXCL | O_RDWR;
+#endif
+	outFileD = open((const char*)fPath, flags, filePerms);
+	if (outFileD < 0)
+		return AudioFileTranslateErrno(errno);
+
+	return noErr;
+}
+
+OSStatus AudioFileObject::AddDurationToInfoDictionary(CACFDictionary *infoDict, Float64 &inDuration)
+{
+#if !TARGET_OS_WIN32
+	CFLocaleRef currentLocale = CFLocaleGetSystem();
+	CFNumberFormatterRef numberFormatter = NULL;
+	numberFormatter = CFNumberFormatterCreate(kCFAllocatorDefault, currentLocale, kCFNumberFormatterDecimalStyle);
+	CFStringRef cfStr = CFNumberFormatterCreateStringWithValue( kCFAllocatorDefault, numberFormatter, kCFNumberFloat64Type, &inDuration);
+	if (cfStr)
+	{
+		if (CFStringGetLength(cfStr) != 0)
+			infoDict->AddString(CFSTR(kAFInfoDictionary_ApproximateDurationInSeconds), cfStr);
+		CFRelease(cfStr);
+	}
+	CFRelease(numberFormatter);
+#endif
+	return noErr;
+}
+
+OSStatus AudioFileObject::SizeChanged()
+{
+	OSStatus err = noErr;
+	if (mPermissions & kAudioFileWritePermission) 
+	{
+		if (DeferSizeUpdates())
+			SetNeedsSizeUpdate(true);
+		else
+			err = UpdateSize();
+	}
+	return err;
+}
+
+OSStatus AudioFileObject::UpdateSizeIfNeeded()
+{		
+	if (GetNeedsSizeUpdate()) 
+	{
+		OSStatus err = UpdateSize();
+		if (err) return err;
+		SetNeedsSizeUpdate(false);
+	}
+	return noErr;
+}
+
+OSStatus AudioFileObject::CountUserData(	UInt32					/*inUserDataID*/,
+											UInt32*					/*outNumberItems*/)
+{
+	return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::GetUserDataSize(  UInt32					/*inUserDataID*/,
+											UInt32					/*inIndex*/,
+											UInt32*					/*outDataSize*/)
+{
+	return kAudioFileOperationNotSupportedError;
+}
+											
+OSStatus AudioFileObject::GetUserData(		UInt32					/*inUserDataID*/,
+											UInt32					/*inIndex*/,
+											UInt32*					/*ioDataSize*/,
+											void*					/*ioUserData*/)
+{
+	return kAudioFileOperationNotSupportedError;
+}
+											
+OSStatus AudioFileObject::SetUserData(		UInt32					/*inUserDataID*/,
+											UInt32					/*inIndex*/,
+											UInt32					/*inDataSize*/,
+											const void*				/*inUserData*/)
+{
+	return kAudioFileOperationNotSupportedError;
+}
+											
+OSStatus AudioFileObject::RemoveUserData(	UInt32					/*inUserDataID*/,
+											UInt32					/*inIndex*/)
+{
+	return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::MoveData(SInt64 fromPos, SInt64 toPos, SInt64 size)
+{
+	if (fromPos == toPos) 
+		return noErr;
+
+	OSStatus err = noErr;
+	CAAutoFree<char> audioData(kCopySoundDataBufferSize, true);
+
+	SInt64 bytesRemaining = size;
+	if (fromPos < toPos) {
+		while (bytesRemaining > 0)
+		{
+			// read from old file
+			UInt32 byteCount;
+			SInt64 count = (bytesRemaining < kCopySoundDataBufferSize) ? bytesRemaining : kCopySoundDataBufferSize; 
+			err = GetDataSource()->ReadBytes(SEEK_SET, fromPos+(bytesRemaining-count), (UInt32)count, audioData(), &byteCount);
+			FailIf (err != noErr, Bail, "MoveData ReadBytes failed");
+
+			err = GetDataSource()->WriteBytes(SEEK_SET, toPos+(bytesRemaining-count), (UInt32)count, audioData(), &byteCount);
+			FailIf (err != noErr, Bail, "WriteBytes failed");
+			
+			bytesRemaining -= count;
+		}
+	} else {
+		while (bytesRemaining > 0)
+		{
+			// read from old file
+			UInt32 byteCount;
+			SInt64 count = (bytesRemaining < kCopySoundDataBufferSize) ? bytesRemaining : kCopySoundDataBufferSize; 
+			err = GetDataSource()->ReadBytes(SEEK_SET, fromPos+(size - bytesRemaining), (UInt32)count, audioData(), &byteCount);
+			FailIf (err != noErr, Bail, "MoveData ReadBytes failed");
+			
+			err = GetDataSource()->WriteBytes(SEEK_SET, toPos+(size - bytesRemaining), (UInt32)count, audioData(), &byteCount);
+			FailIf (err != noErr, Bail, "WriteBytes failed");
+			
+			bytesRemaining -= count;
+		}
+	}
+	
+Bail:
+	return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h
new file mode 100644
index 0000000..6d7c868
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h
@@ -0,0 +1,667 @@
+/*
+     File: AudioFileObject.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef _AudioFileObject_H_
+#define _AudioFileObject_H_
+
+#include <TargetConditionals.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <AudioToolbox/AudioFile.h>
+	#include <AudioToolbox/AudioFormat.h>
+#else
+	#include "CoreAudioTypes.h"
+	#include "AudioFile.h"
+	#include "AudioFormat.h"
+#endif
+
+#include "CompressedPacketTable.h"
+#include "CACFDictionary.h"
+#include "DataSource.h"
+#include <vector>
+#include <fcntl.h>
+
+#if TARGET_OS_WIN32
+#include <io.h>
+#endif
+
+/*
+	These are structs defined in 10.5. They are included here for compatibility with sources
+*/
+#if COREAUDIOTYPES_VERSION < 1050
+
+struct AudioFormatListItem
+{
+	AudioStreamBasicDescription		mASBD;
+	AudioChannelLayoutTag			mChannelLayoutTag;
+};
+typedef struct AudioFormatListItem AudioFormatListItem;
+
+struct AudioFormatInfo
+{
+	AudioStreamBasicDescription		mASBD;
+	const void*						mMagicCookie;
+	UInt32							mMagicCookieSize;
+};
+typedef struct AudioFormatInfo AudioFormatInfo;
+
+enum {
+
+	kAudioFormatProperty_FormatList						= 'flst',
+		//	Returns a list of AudioFormatListItem structs describing the audio formats contained within the compressed bit stream
+		//	as described by the magic cookie.
+		//	The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
+		//	may be filled in.
+		
+	kAudioFormatProperty_OutputFormatList				= 'ofls',
+		//	Returns a list of AudioFormatListItem structs describing the audio formats which may be obtained by decoding the format
+		//	described by the specifier.
+		//	The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
+		//	may be filled in. If there is no magic cookie, then the number of channels and sample rate should be filled in. 
+
+};
+
+enum {
+	kAudioFilePropertyPacketSizeUpperBound  =	'pkub',
+	kAudioFilePropertyFormatList			=	'flst',
+	kAudioFilePropertyEstimatedDuration		=	'edur',
+	kAudioFilePropertyBitRate				=	'brat'
+};
+
+enum {
+	kAudioFileCreateURLSelect					= 0x0019,
+	kAudioFileOpenURLSelect						= 0x001A,
+	kAudioFileFileDataIsThisFormatSelect		= 0x001B
+};
+#endif
+
+enum {
+	kTEMPAudioFilePropertySoundCheckDictionary = 'scdc',
+	kTEMPAudioFilePropertyLoudnessInfo = 'loud',
+	kTEMPAudioFilePropertyGenerateLoudnessInfo = 'glou'
+};
+
+const UInt32 kCopySoundDataBufferSize = 1024 * 1024;
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// some files encode these as upper case
+enum {
+  kUpperCase_IMACompression               = 'IMA4', /*IMA 4:1*/
+  kUpperCase_ULawCompression              = 'ULAW', /*µLaw 2:1*/
+  kUpperCase_ALawCompression              = 'ALAW', /*aLaw 2:1*/
+  
+  kUpperCase_Float32					  = 'FL32',
+  kUpperCase_Float64					  = 'FL64'
+};
+
+enum
+{
+	// in what header is this defined? what is it?
+	kGSM = 'agsm', 
+	kUpperCase_GSM = 'GSM '
+};
+
+#define	kPackedBESInt	(kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
+#define	kPackedLESInt	(kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked)
+#define kPackedBEFloat	(kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
+#define kPackedLEFloat	(kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked)
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline int TransformPerm_FS_O (SInt8 inPerm)
+{
+	switch (inPerm) {
+		case kAudioFileReadPermission: return O_RDONLY;
+		case kAudioFileWritePermission: return O_WRONLY;
+		case kAudioFileReadWritePermission: return O_RDWR;
+	}
+	return O_RDONLY;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#pragma mark "File Error Handling"
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#include <errno.h>
+#include <CoreAudio/CoreAudioTypes.h>
+
+inline OSErr AudioFileTranslateErrno(int err)
+{
+    switch (err) {
+#if !TARGET_OS_WIN32
+    case ENFILE:
+#endif
+    case EMFILE:
+        return -42 /* kAudio_TooManyFilesOpenError */;
+#if !TARGET_OS_WIN32
+    case EPERM:
+    case EROFS:
+#endif
+    case EACCES:
+    case EEXIST:
+        return -54 /* kAudio_FilePermissionError */;
+#if !TARGET_OS_WIN32
+    case EMLINK:
+        return (OSErr)'!pth' /* kAudio_BadFilePathError */;
+    case ENOTDIR:
+    case ELOOP:
+#endif
+    case ENOENT:
+    default:
+			return (OSErr)kAudioFileUnspecifiedError;
+        }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class AudioFileObject
+{
+protected:
+
+private:
+	SInt64							mNumBytes;				// total bytes of audio data in the audio file
+	SInt64							mNumPackets;			// total frames of audio data in the audio file
+	AudioStreamBasicDescription		mDataFormat;		// format of the audio data
+	SInt64							mDataOffset;		// position if the file where audio data begins
+	UInt32							mIsOptimized;		// 1 if there is nothing in the file following the audio data, 0 if there is
+	UInt32							mFileType;			// file type of the audio file (i.e. AIFF, WAVE, etc.)			
+	CFURLRef						mFileRef;				// URL of the file passed to AudioFileOpen or AudioFileCreate
+	int								mFileD;			// Ref num of the file after opening within Audio File 
+	SInt8							mPermissions;		// file permissions indicated by the caller, passed by AudioFileOpen or set with SetProperty function
+	Boolean							mIsInitialized;		// has the AudioFileObject for this file been intialized?
+	DataSource						*mDataSource;
+    UInt32							mMaximumPacketSize;
+    CompressedPacketTable			*mPacketTable;
+	UInt32							mDeferSizeUpdates;
+	Boolean							mNeedsSizeUpdate;
+	Boolean							mFirstSetFormat;
+	Boolean							mAlignDataWithFillerChunks;
+	
+public:    
+  
+	AudioFileObject (UInt32 inFileType)
+		: mNumBytes(0),
+		  mNumPackets(0),
+		  mDataOffset(0),
+		  mIsOptimized(1),
+		  mFileType(inFileType),
+		  mFileRef(NULL),
+		  mFileD(-1),
+		  mPermissions(0),
+		  mIsInitialized (false),
+		  mDataSource(0),
+          mMaximumPacketSize(0),
+          mPacketTable(NULL),
+		  mDeferSizeUpdates(1),
+		  mNeedsSizeUpdate(false),
+		  mFirstSetFormat(true),
+		  mAlignDataWithFillerChunks(true)
+		  {
+			memset(&mDataFormat, 0, sizeof(mDataFormat));
+		  }
+	
+	virtual ~AudioFileObject();
+
+	
+/* Public API Function Implementation */
+	// The DoSomething() versions of these functions are wrappers that perform a standard prologue.
+	// The Something() methods are those which should be overridden in the subclasses.
+	
+	OSStatus DoCreate(				CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat,
+									UInt32								inFlags);
+                                
+	virtual OSStatus Create(		CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat);
+                                
+	OSStatus DoOpen(				CFURLRef		inFileRef, 
+									SInt8  			inPermissions,
+									int				inFD);
+									
+	virtual OSStatus Open(			CFURLRef		inFileRef, 
+									SInt8  			inPermissions,
+									int				inFD);
+
+	OSStatus DoOpenWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc);
+				
+									
+	OSStatus DoInitialize(			CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat,
+									UInt32								inFlags);
+	
+	virtual OSStatus Initialize(	CFURLRef							inFileRef,
+									const AudioStreamBasicDescription	*inFormat,
+									UInt32								inFlags);
+										
+	OSStatus DoInitializeWithCallbacks(
+				void *								inRefCon, 
+				AudioFile_ReadProc					inReadFunc, 
+				AudioFile_WriteProc					inWriteFunc, 
+				AudioFile_GetSizeProc				inGetSizeFunc,
+				AudioFile_SetSizeProc				inSetSizeFunc,
+				UInt32								inFileType,
+				const AudioStreamBasicDescription	*inFormat,
+				UInt32								inFlags);
+				
+	virtual OSStatus OpenFromDataSource(void);
+						
+	virtual OSStatus InitializeDataSource(const AudioStreamBasicDescription	*inFormat, UInt32 inFlags);
+	
+	OSStatus DoClose();
+	
+	virtual OSStatus Close();
+	
+	OSStatus DoOptimize();
+	
+	virtual OSStatus Optimize();
+	
+	virtual OSStatus ReadBytes(		Boolean			inUseCache,
+									SInt64			inStartingByte, 
+									UInt32			*ioNumBytes, 
+									void			*outBuffer);
+	
+	virtual OSStatus WriteBytes(	Boolean			inUseCache,
+									SInt64			inStartingByte, 
+									UInt32			*ioNumBytes, 
+									const void		*inBuffer);
+	
+	virtual OSStatus ReadPackets(	Boolean							inUseCache,
+									UInt32							*outNumBytes,
+									AudioStreamPacketDescription	*outPacketDescriptions,
+									SInt64							inStartingPacket, 
+									UInt32  						*ioNumPackets, 
+									void							*outBuffer);
+
+	virtual OSStatus ReadPacketData(	
+									Boolean							inUseCache,
+									UInt32							*ioNumBytes,
+									AudioStreamPacketDescription	*outPacketDescriptions,
+									SInt64							inStartingPacket, 
+									UInt32  						*ioNumPackets, 
+									void							*outBuffer);
+	
+	virtual OSStatus ReadPacketDataVBR(	
+									Boolean							inUseCache,
+									UInt32							*ioNumBytes,
+									AudioStreamPacketDescription	*outPacketDescriptions,
+									SInt64							inStartingPacket, 
+									UInt32  						*ioNumPackets, 
+									void							*outBuffer);
+
+    virtual OSStatus	HowManyPacketsCanBeReadIntoBuffer(UInt32* ioNumBytes, SInt64 inStartingPacket, UInt32 *ioNumPackets);
+
+    virtual OSStatus	ReadPacketDataVBR_InTable(	
+                                    Boolean							inUseCache,
+                                    UInt32							*ioNumBytes,
+                                    AudioStreamPacketDescription	*outPacketDescriptions,
+                                    SInt64							inStartingPacket, 
+                                    UInt32  						*ioNumPackets, 
+                                    void							*outBuffer);
+	
+	virtual OSStatus WritePackets(	Boolean								inUseCache,
+                                    UInt32								inNumBytes,
+                                    const AudioStreamPacketDescription	*inPacketDescriptions,
+                                    SInt64								inStartingPacket, 
+                                    UInt32								*ioNumPackets, 
+                                    const void							*inBuffer);
+/* Property Support */
+
+	virtual OSStatus GetPropertyInfo	(	
+                                        AudioFilePropertyID		inPropertyID,
+                                        UInt32					*outDataSize,
+                                        UInt32					*isWritable);
+										
+	virtual OSStatus GetProperty	(	AudioFilePropertyID		inPropertyID,
+										UInt32					*ioDataSize,
+										void					*ioPropertyData);
+										
+	virtual OSStatus SetProperty	(	AudioFilePropertyID		inPropertyID,
+										UInt32					inDataSize,
+										const void				*inPropertyData);
+										
+	UInt32 GetFileType() const { return mFileType; }
+	void SetFileType(UInt32 inFileType) { mFileType = inFileType; }
+	
+	// this will set the format in memory only.
+	virtual OSStatus SetDataFormat(const AudioStreamBasicDescription* inStreamFormat);
+	
+	// this will update the format info on disk and in memory.
+	virtual OSStatus UpdateDataFormat(const AudioStreamBasicDescription* inStreamFormat);
+	
+	const UInt32 GetBytesPerPacket() const { return mDataFormat.mBytesPerPacket; }
+	
+	const AudioStreamBasicDescription &GetDataFormat() const { return mDataFormat; }
+	
+	virtual OSStatus GetFormatListInfo(	UInt32				&outDataSize,
+											UInt32				&outWritable);
+										
+	virtual OSStatus GetFormatList(	UInt32									&ioDataSize,
+									AudioFormatListItem				*ioPropertyData);
+										
+	virtual OSStatus SetFormatList(	UInt32									inDataSize,
+									const AudioFormatListItem		*inPropertyData);
+	
+	virtual OSStatus UpdateSize() { return noErr; }
+	UInt32	DeferSizeUpdates() { return mDeferSizeUpdates; }
+	void SetDeferSizeUpdates(UInt32 inFlag) { mDeferSizeUpdates = inFlag; }
+	OSStatus UpdateSizeIfNeeded();
+	OSStatus SizeChanged();
+	
+	Boolean IsOptimized() const { return mIsOptimized != 0; }
+	void SetIsOptimized(Boolean inIsOptimized) { mIsOptimized = inIsOptimized ? 1 : 0; }
+
+	Boolean AlignDataWithFillerChunks() const { return mAlignDataWithFillerChunks; }
+
+	virtual SInt64 GetNumBytes() { return mNumBytes; }
+	virtual void SetNumBytes(SInt64 inNumBytes) { mNumBytes = inNumBytes; }
+
+	// this will update the header size info on disk
+	OSStatus UpdateNumBytes(SInt64 inNumBytes);
+	
+	virtual SInt64 GetNumPackets(){ return mNumPackets; }
+	virtual void SetNumPackets(SInt64 inNumPackets) { mNumPackets = inNumPackets; }
+	
+	// this will update the header size info on disk
+	OSStatus UpdateNumPackets(SInt64 inNumPackets);
+
+	virtual OSStatus PacketToFrame(SInt64 inPacket, SInt64& outFirstFrameInPacket);
+	virtual OSStatus FrameToPacket(SInt64 inFrame, SInt64& outPacket, UInt32& outFrameOffsetInPacket);
+	
+	virtual OSStatus PacketToByte(AudioBytePacketTranslation* abpt);
+	
+	virtual OSStatus ByteToPacket(AudioBytePacketTranslation* abpt);
+	
+	virtual OSStatus GetBitRate(				UInt32					*outBitRate);
+		
+	virtual OSStatus GetMagicCookieDataSize(	UInt32					*outDataSize,
+												UInt32					*isWritable);
+	                      
+	virtual OSStatus GetMagicCookieData(		UInt32					*ioDataSize,
+												void					*ioPropertyData);
+	                      
+	virtual OSStatus SetMagicCookieData(		UInt32					inDataSize,
+												const void				*inPropertyData);
+
+	virtual OSStatus GetMarkerListSize(			UInt32						*outDataSize,
+												UInt32						*isWritable);
+	                      
+	virtual OSStatus GetMarkerList(				UInt32						*ioDataSize,
+												AudioFileMarkerList			*ioMarkerList);
+	                      
+	virtual OSStatus SetMarkerList(				UInt32						inDataSize,
+												const AudioFileMarkerList	*inMarkerList);
+
+
+	virtual OSStatus GetRegionListSize(			UInt32						*outDataSize,
+												UInt32						*isWritable);
+	                      
+	virtual OSStatus GetRegionList(				UInt32						*ioDataSize,
+												AudioFileRegionList			*ioRegionList);
+	                      
+	virtual OSStatus SetRegionList(				UInt32						inDataSize,
+												const AudioFileRegionList	*inRegionList);
+
+	virtual OSStatus GetChannelLayoutSize(		UInt32						*outDataSize,
+												UInt32						*isWritable);
+	                      
+	virtual OSStatus GetChannelLayout(			UInt32						*ioDataSize,
+												AudioChannelLayout			*ioChannelLayout);
+	                      
+	virtual OSStatus SetChannelLayout(			UInt32						inDataSize,
+												const AudioChannelLayout	*inChannelLayout);
+
+
+	virtual OSStatus GetInfoDictionarySize(		UInt32						*outDataSize,
+												UInt32						*isWritable);
+												
+	virtual OSStatus GetInfoDictionary(			CACFDictionary  *infoDict);
+												
+	virtual OSStatus SetInfoDictionary(			CACFDictionary  *infoDict);
+
+	virtual OSStatus GetSoundCheckDictionarySize(		UInt32						*outDataSize,
+														UInt32						*isWritable) { return kAudioFileUnsupportedPropertyError; }
+														
+	virtual OSStatus GetSoundCheckDictionary(	CACFDictionary  *infoDict) { return kAudioFileUnsupportedPropertyError; }
+												
+	virtual OSStatus SetSoundCheckDictionary(	CACFDictionary  *infoDict) { return kAudioFileUnsupportedPropertyError; }
+														
+	virtual OSStatus GetLoudnessInfo(	CACFDictionary  *infoDict) { return kAudioFileUnsupportedPropertyError; }
+	
+	virtual OSStatus GetSoundCheckDictionaryFromLoudnessInfo(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
+	virtual OSStatus GetLoudnessInfoFromSoundCheckDictionary(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
+	
+	virtual OSStatus SetLoudnessInfo(	CACFDictionary  *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+	virtual OSStatus GetLoudnessInfoSize(				UInt32			*outDataSize,
+														UInt32			*isWritable) { return kAudioFileUnsupportedPropertyError; }
+
+	virtual OSStatus GenerateLoudnessInfo(	CACFDictionary  *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+	virtual OSStatus GetEstimatedDuration(		Float64*		duration);
+
+	virtual OSStatus CountUserData(			UInt32					inUserDataID,
+											UInt32					*outNumberItems);
+											
+	virtual OSStatus GetUserDataSize(		UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					*outDataSize);
+											
+	virtual OSStatus GetUserData(			UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					*ioDataSize,
+											void					*ioUserData);
+											
+	virtual OSStatus SetUserData(			UInt32					inUserDataID,
+											UInt32					inIndex,
+											UInt32					inDataSize,
+											const void				*inUserData);
+
+	virtual OSStatus RemoveUserData(		UInt32					inUserDataID,
+											UInt32					inIndex);
+
+	virtual OSStatus GetLyrics(CFStringRef  *outLyrics) { return kAudioFileUnsupportedPropertyError; }
+
+
+	Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+	Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+
+	void SetPermissions(SInt8 inPermissions) { mPermissions = inPermissions; }
+		
+/* Other Helper Methods: (some may not be necessary depending on how things are refactored) */
+	
+	OSStatus OpenFile(SInt8 inPermissions, int inFD);
+
+	OSStatus CreateDataFile (CFURLRef	inFileRef, int	&outFileD);
+
+	OSStatus AddDurationToInfoDictionary(CACFDictionary *infoDict, Float64 &inDuration);	
+
+	virtual Boolean IsDataFormatSupported(const AudioStreamBasicDescription	*inFormat) = 0;
+	virtual Boolean IsDataFormatValid(const AudioStreamBasicDescription	*inFormat);
+
+	virtual OSStatus IsValidFilePosition(SInt64 /*position*/) { return noErr; }
+
+	OSStatus MoveData(SInt64 fromPos, SInt64 toPos, SInt64 size);
+
+/* Accessors: */
+	Boolean IsInitialized() const { return mIsInitialized; }
+	void SetInitialized(Boolean inFlag) { mIsInitialized = inFlag; }
+			
+	DataSource* GetDataSource() const { return mDataSource; }
+	void SetDataSource(DataSource *inDataSource);
+    
+	void	SetURL (CFURLRef inURL);
+	
+    virtual UInt32	GetMaximumPacketSize() { return mMaximumPacketSize; }
+    virtual UInt32	FindMaximumPacketSize() { return mMaximumPacketSize; }
+    virtual void	SetMaximumPacketSize(const UInt32 inPacketSize) { mMaximumPacketSize = inPacketSize; }
+    	
+    virtual UInt32	GetPacketSizeUpperBound() { return GetMaximumPacketSize (); }
+    	
+	SInt64 GetDataOffset() const { return mDataOffset; }	
+	void SetDataOffset(SInt64 inOffset) { mDataOffset = inOffset; }	
+    
+	// I like this idiom better than DoesPacketTableExist+NewPacketTable:
+	CompressedPacketTable* GetPacketTable(Boolean inCreateIt = false)
+	{
+		if (!mPacketTable && inCreateIt)
+			mPacketTable = new CompressedPacketTable(mDataFormat.mFramesPerPacket);
+		return mPacketTable;
+	}
+	void ClearPacketTable() 
+	{
+		DeletePacketTable();
+		GetPacketTable(true);
+	}
+	
+	virtual OSStatus ScanForPackets(SInt64  inToPacketCount, DataSource* inDataSrc = NULL, bool fullyParsedIfEndOfDataReached = true) 
+	{
+		// In formats that read packets lazily, this will be overridden to scan for packets up to the index.
+		if (inToPacketCount > GetNumPackets())
+			return kAudioFileEndOfFileError;
+		
+		return noErr; 
+	}
+		
+    void AppendPacket(const AudioStreamPacketDescription &inPacket) 
+		{
+			CompressedPacketTable* packetTable = GetPacketTable(true);
+			UInt32 numFramesInPacket = mDataFormat.mFramesPerPacket ? mDataFormat.mFramesPerPacket : inPacket.mVariableFramesInPacket;
+			
+			AudioStreamPacketDescriptionExtended pext;
+			memset(&pext, 0, sizeof(pext));
+			pext.mStartOffset = inPacket.mStartOffset;
+			pext.mDataByteSize = inPacket.mDataByteSize;
+			pext.mVariableFramesInPacket = inPacket.mVariableFramesInPacket;
+			pext.mFrameOffset = numFramesInPacket + (packetTable->size() ? packetTable->back().mFrameOffset : 0);
+			
+			packetTable->push_back(pext); 
+			if (inPacket.mDataByteSize > mMaximumPacketSize) 
+				mMaximumPacketSize = inPacket.mDataByteSize;
+		}
+    void DeletePacketTable() { delete mPacketTable; mPacketTable = NULL;}
+    SInt64	GetPacketTableSize() { return mPacketTable ? mPacketTable->size() : 0; }
+    OSStatus GetPacketDescriptions(UInt32   inStartingPacket, UInt32   *ioDataSize, AudioStreamPacketDescription    *outPacketDescriptions)
+        {
+			if (outPacketDescriptions == NULL) return kAudioFileUnspecifiedError;
+            if (mPacketTable)
+			{
+				// only get as many packet descriptions as can fit in outPacketDescriptions
+				UInt32	count = *ioDataSize / sizeof(AudioStreamPacketDescription);
+				if (count + inStartingPacket  > GetPacketTableSize()) 
+					count = (UInt32)(GetPacketTableSize() - inStartingPacket);
+					
+				*ioDataSize = 0;
+				for (UInt32 i = inStartingPacket; i < (count + inStartingPacket); i++)
+				{
+					AudioStreamPacketDescription    curPacket =  (*mPacketTable)[i];
+					outPacketDescriptions[i].mStartOffset = curPacket.mStartOffset - GetDataOffset();
+					outPacketDescriptions[i].mVariableFramesInPacket = curPacket.mVariableFramesInPacket;
+					outPacketDescriptions[i].mDataByteSize = curPacket.mDataByteSize;
+					*ioDataSize += sizeof(AudioStreamPacketDescription);
+				}
+			}
+			else
+				*ioDataSize = 0;
+
+            return noErr;
+        }
+
+#if DEBUG
+	void DumpPacketTable()
+		{
+            if (mPacketTable) {
+				SInt64 size = mPacketTable->size();
+				printf("PacketTable size %d\n", (int)size);
+				for (SInt64 i = 0; i < size; i++) {
+					AudioStreamPacketDescription    curPacket =  (*mPacketTable)[i];
+					printf("dpkt %5qd %8qd %5d %5d\n", i, curPacket.mStartOffset, (int)curPacket.mDataByteSize, (int)curPacket.mVariableFramesInPacket);
+				}
+			}
+		}
+#endif
+
+	Boolean GetNeedsSizeUpdate() const { return mNeedsSizeUpdate; }
+	void SetNeedsSizeUpdate(Boolean inNeedsSizeUpdate) { mNeedsSizeUpdate = inNeedsSizeUpdate; }
+	
+	CFURLRef GetURL () const { return mFileRef; }
+
+	virtual OSStatus			GetSourceBitDepth(SInt32& outValue) { outValue = 0; return kAudioFileUnsupportedPropertyError; }
+	virtual OSStatus			SetSourceBitDepth(SInt32 inValue) { return kAudioFileUnsupportedPropertyError; }
+
+	virtual OSStatus	GetAlbumArtwork(CFDataRef& outValue) { outValue = NULL; return kAudioFileUnsupportedPropertyError; }
+	virtual OSStatus	SetAlbumArtwork(CFDataRef inValue){ return kAudioFileUnsupportedPropertyError; }
+
+private:
+
+	void SetAlignDataWithFillerChunks(Boolean inFlag) { mAlignDataWithFillerChunks = inFlag; }
+
+	OSStatus ValidateFormatAndData();
+	
+/* debug */
+//	virtual void PrintFile (FILE* inFile, const char *indent) = 0;
+};
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline Boolean cfstrcmpi(CFStringRef a, CFStringRef b)
+{
+	// case insensitive CFString compare
+	return CFStringCompare(a, b, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
+}
+
+CFBundleRef GetAudioToolboxBundle();
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp
new file mode 100644
index 0000000..ba07580
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp
@@ -0,0 +1,216 @@
+/*
+     File: CompressedPacketTable.cpp
+ Abstract: CompressedPacketTable.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CompressedPacketTable.h"
+#include "CAAutoDisposer.h"
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+const UInt32 CompressedPacketTable::kShift = 5;
+const UInt32 CompressedPacketTable::kMask = 31;
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+CompressedPacketTable::~CompressedPacketTable()
+{
+	size_t size = mBases.size();
+	for (size_t i = 0; i < size; ++i) {
+		free(mBases[i].mDescs);
+	}
+}
+
+void CompressedPacketTable::push_back(const AudioStreamPacketDescriptionExtended& inDesc)
+{
+	SInt64 baseIndex = mSize >> kShift;
+	UInt32 packetIndex = (UInt32)(mSize & kMask);
+	
+	if (packetIndex == 0) {
+		// first packet in a new sequence. create a new PacketBase.
+		PacketBase newBase;
+		newBase.mBaseOffset = 0;
+		newBase.mDescs = CA_malloc((kMask+1) * sizeof(AudioStreamPacketDescriptionExtended));
+		newBase.mDescType = kExtendedPacketDescription;
+		mBases.push_back(newBase);
+	}
+	
+	PacketBase& base = mBases[(size_t)baseIndex];
+	AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+	descs[packetIndex] = inDesc;
+	
+	if (packetIndex == kMask) {
+		// last packet in a sequence. compress the sequence.
+		Compress(base);
+	}
+	
+	mSize++;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#define ACCESS_TYPE(TYPE) \
+		case k##TYPE##ContiguousPacketDescription : { \
+			TYPE##ContiguousPacketDescription* descs = (TYPE##ContiguousPacketDescription*)base.mDescs; \
+			packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \
+			packetSize = (UInt32)(descs[packetIndex].mNextOffset - packetOffset); \
+		} break; \
+		case k##TYPE##DiscontiguousPacketDescription : { \
+			TYPE##DiscontiguousPacketDescription* descs = (TYPE##DiscontiguousPacketDescription*)base.mDescs; \
+			packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \
+			packetSize = descs[packetIndex].mDataByteSize; \
+		} break;
+
+const AudioStreamPacketDescriptionExtended CompressedPacketTable::operator[](SInt64 inPacketIndex) const
+{
+	SInt64 baseIndex = inPacketIndex >> kShift;
+	UInt32 packetIndex = (UInt32)(inPacketIndex & kMask);
+
+	if ((size_t)baseIndex >= mBases.size())
+		throw -1;
+		
+	const PacketBase& base = mBases[(size_t)baseIndex];
+	
+	SInt64 packetOffset = 0;
+	UInt32 packetSize = 0;
+		
+	switch (base.mDescType) 
+	{
+		ACCESS_TYPE(Tiny)
+		ACCESS_TYPE(Small)
+		ACCESS_TYPE(Big)
+		case kExtendedPacketDescription :
+			return ((AudioStreamPacketDescriptionExtended*)base.mDescs)[packetIndex];
+	}
+	
+	AudioStreamPacketDescriptionExtended outDesc;
+	outDesc.mStartOffset = base.mBaseOffset + packetOffset;
+	outDesc.mDataByteSize = packetSize;
+	outDesc.mVariableFramesInPacket = 0;
+	outDesc.mFrameOffset = mFramesPerPacket * inPacketIndex;
+
+	//printf("get %d %10qd   %10qd %2d   %10qd %6d %10qd\n", base.mDescType, inPacketIndex, baseIndex, packetIndex, outDesc.mStartOffset, outDesc.mDataByteSize, outDesc.mFrameOffset);
+	
+	return outDesc;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+bool CompressedPacketTable::isContiguous(PacketBase& base)
+{	
+	AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+	SInt64 expectedOffset = descs[0].mStartOffset + descs[0].mDataByteSize;
+	for (UInt32 i = 1; i <= kMask; ++i) {
+		if (expectedOffset != descs[i].mStartOffset) return false;
+		expectedOffset += descs[i].mDataByteSize;
+	}
+	return true;
+}
+
+bool CompressedPacketTable::hasVariableFrames(PacketBase& base)
+{	
+	AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+	for (UInt32 i = 0; i <= kMask; ++i) {
+		if (descs[i].mVariableFramesInPacket) return true;
+	}
+	return false;
+}
+
+UInt32 CompressedPacketTable::largestPacket(PacketBase& base)
+{	
+	UInt32 maxPacketSize = 0;
+	AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+	for (UInt32 i = 0; i <= kMask; ++i) {
+		UInt32 packetSize = descs[i].mDataByteSize;
+		if (packetSize > maxPacketSize) maxPacketSize = packetSize;
+	}
+	return maxPacketSize;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#define COMPRESS_TYPE(TYPE, BITS) \
+	if (contiguous) { \
+		TYPE##ContiguousPacketDescription* newDescs = (TYPE##ContiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##ContiguousPacketDescription)); \
+		base.mDescs = newDescs; \
+		base.mDescType = k##TYPE##ContiguousPacketDescription; \
+		for (UInt32 i = 0; i <= kMask; ++i) { \
+			newDescs[i].mNextOffset = (BITS)(descs[i].mStartOffset + descs[i].mDataByteSize - baseOffset); \
+		} \
+		free(descs); \
+	} else { \
+		TYPE##DiscontiguousPacketDescription* newDescs = (TYPE##DiscontiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##DiscontiguousPacketDescription)); \
+		base.mDescs = newDescs; \
+		base.mDescType = k##TYPE##DiscontiguousPacketDescription; \
+		for (UInt32 i = 0; i <= kMask; ++i) { \
+			newDescs[i].mNextOffset = i == kMask ? 0 : (BITS)(descs[i+1].mStartOffset - baseOffset); \
+			newDescs[i].mDataByteSize = descs[i].mDataByteSize; \
+		} \
+		free(descs); \
+	} \
+	return;
+
+void CompressedPacketTable::Compress(PacketBase& base)
+{
+	if (hasVariableFrames(base)) 
+		return;
+	
+	bool contiguous = isContiguous(base);
+	
+	AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+	SInt64 delta = descs[kMask].mStartOffset + descs[kMask].mDataByteSize - descs[0].mStartOffset;
+		
+	SInt64 baseOffset = descs[0].mStartOffset;
+	base.mBaseOffset = baseOffset;
+	
+	if (delta <= 65535LL) {
+		COMPRESS_TYPE(Tiny, UInt16)
+	} else if (delta <= 4294967295LL && largestPacket(base) <= 65535) {
+		COMPRESS_TYPE(Small, UInt32)
+	} else {
+		COMPRESS_TYPE(Big, SInt64)
+	}
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h
new file mode 100644
index 0000000..47e28ca
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h
@@ -0,0 +1,186 @@
+/*
+     File: CompressedPacketTable.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include <iterator>
+#include <vector>
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include "CoreAudioTypes.h"
+#endif
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+struct  AudioStreamPacketDescriptionExtended : AudioStreamPacketDescription
+{
+    SInt64  mFrameOffset; // this is the sum of the mVariableFramesInPacket up to this point so we can binary search.
+};
+typedef struct AudioStreamPacketDescriptionExtended AudioStreamPacketDescriptionExtended;
+
+inline bool operator < (const AudioStreamPacketDescriptionExtended& a, const AudioStreamPacketDescriptionExtended& b)
+{
+	return a.mFrameOffset < b.mFrameOffset;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class CompressedPacketTable
+{
+public:
+	CompressedPacketTable(UInt32 inFramesPerPacket) : mSize(0), mFramesPerPacket(inFramesPerPacket) {}
+	~CompressedPacketTable();
+	
+	SInt64 size() const { return mSize; }
+	void push_back(const AudioStreamPacketDescriptionExtended& inDesc);
+	
+	const AudioStreamPacketDescriptionExtended operator[](SInt64 inPacketIndex) const;
+	const AudioStreamPacketDescriptionExtended front() const { return (*this)[0]; }
+	const AudioStreamPacketDescriptionExtended back() const { return (*this)[mSize-1]; }
+	
+	//SInt64 PacketForByte(SInt64 inByteOffset) const;
+	SInt64 ByteForPacket(SInt64 inPacketIndex) const { return (*this)[inPacketIndex].mStartOffset; }
+		
+	class iterator {
+		public:
+			typedef std::input_iterator_tag iterator_category;
+			typedef iterator pointer;
+			typedef SInt64 difference_type;
+			typedef AudioStreamPacketDescriptionExtended value_type;
+			typedef value_type& reference;
+			
+			iterator() : mTable(NULL), mIndex(0) {}
+			iterator(const CompressedPacketTable* table, SInt64 index) : mTable(table), mIndex(index) {}
+			iterator(const iterator& that) : mTable(that.mTable), mIndex(that.mIndex) {}
+			
+			iterator& operator=(const iterator& that) { mTable = that.mTable; mIndex = that.mIndex; return *this; }
+			
+			const AudioStreamPacketDescriptionExtended operator*() const { return (*mTable)[mIndex]; }
+			const AudioStreamPacketDescriptionExtended* const operator->() { mValue = (*mTable)[mIndex]; return &mValue; }
+			iterator& operator++() { ++mIndex; return *this; }
+			iterator& operator--() { --mIndex; return *this; }
+			
+			SInt64 operator-(const iterator& that) { return mIndex - that.mIndex; }
+			const iterator operator-(SInt64 index) { return iterator(mTable, mIndex - index); }
+			const iterator operator+(SInt64 index) { return iterator(mTable, mIndex + index); }
+			bool operator==(const iterator& that) { return mIndex == that.mIndex; }
+			bool operator!=(const iterator& that) { return mIndex != that.mIndex; }
+			bool operator>(const iterator& that) { return mIndex > that.mIndex; }
+			bool operator<(const iterator& that) { return mIndex < that.mIndex; }
+		private:
+			const CompressedPacketTable* mTable;
+			SInt64 mIndex;
+			AudioStreamPacketDescriptionExtended mValue; // in order to support operator-> .
+	};
+	
+	iterator begin() const { return iterator(this, 0); }
+	iterator end() const { return iterator(this, mSize); }
+	
+private:
+	struct TinyContiguousPacketDescription
+	{
+		UInt16 mNextOffset;
+	};
+	
+	struct TinyDiscontiguousPacketDescription : TinyContiguousPacketDescription
+	{
+		UInt16 mDataByteSize;
+	};
+	
+	// There could be a 24 bit packet description. But ALAC is who usually needs SmallContiguousPacketDescription and 
+	// it already uses 8x fewer packet descriptions than AAC due to the mFramesPerPacket being 8x greater. 
+	// So there isn't as great a need for saving space. 4 bytes per packet is OK for ALAC.
+	
+	struct SmallContiguousPacketDescription
+	{
+		UInt32 mNextOffset;
+	};
+	
+	struct SmallDiscontiguousPacketDescription : SmallContiguousPacketDescription
+	{
+		UInt16 mDataByteSize;
+	};
+	
+	struct BigContiguousPacketDescription
+	{
+		UInt64 mNextOffset;
+	};
+	
+	struct BigDiscontiguousPacketDescription : BigContiguousPacketDescription
+	{
+		UInt32 mDataByteSize;
+	};
+	
+	struct PacketBase
+	{
+		SInt64 mBaseOffset;
+		UInt8 mDescType;
+		void* mDescs;
+	};
+	
+	enum {
+		kTinyContiguousPacketDescription,
+		kTinyDiscontiguousPacketDescription,
+		kSmallContiguousPacketDescription,
+		kSmallDiscontiguousPacketDescription,
+		kBigContiguousPacketDescription,
+		kBigDiscontiguousPacketDescription,
+		kExtendedPacketDescription
+	};
+	static const UInt32 kShift;
+	static const UInt32 kMask;
+	
+	bool isContiguous(PacketBase& base);
+	bool hasVariableFrames(PacketBase& base);
+	UInt32 largestPacket(PacketBase& base);
+	
+	void Compress(PacketBase& base);
+
+private:	
+	std::vector<PacketBase> mBases;
+	UInt64 mSize;
+	UInt32 mFramesPerPacket;
+};
+
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp
new file mode 100644
index 0000000..c8a93d2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp
@@ -0,0 +1,689 @@
+/*
+     File: DataSource.cpp
+ Abstract: DataSource.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "DataSource.h"
+#if TARGET_OS_WIN32
+	#include <io.h>
+#else
+	#include <unistd.h>
+	#include <fcntl.h>
+#endif
+#include <sys/stat.h>
+#include <algorithm>
+
+#define VERBOSE 0
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+const UInt16 kPositionModeMask = 3;
+
+DataSource::DataSource(Boolean inCloseOnDelete)
+	: mCloseOnDelete(inCloseOnDelete)
+{
+}
+
+DataSource::~DataSource()
+{
+}
+
+SInt64 DataSource::CalcOffset(	UInt16 positionMode, 
+								SInt64 positionOffset,
+								SInt64 currentOffset,
+								SInt64 size)
+{
+	SInt64 newOffset = 0;
+	switch (positionMode & kPositionModeMask) {
+		//case fsAtMark : newOffset = currentOffset; break;
+		case SEEK_SET : newOffset = positionOffset; break;
+		case SEEK_END : newOffset = size + positionOffset; break;
+		case SEEK_CUR : newOffset = positionOffset + currentOffset; break;
+	}
+	return newOffset;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+
+MacFile_DataSource::MacFile_DataSource( FSIORefNum inForkRefNum, SInt8 inPermissions, Boolean inCloseOnDelete)
+	: DataSource(inCloseOnDelete), mFileNum(inForkRefNum), mPermissions(inPermissions)
+{
+}
+
+MacFile_DataSource::~MacFile_DataSource()
+{
+	if (mCloseOnDelete) FSCloseFork(mFileNum);
+}
+
+
+OSStatus MacFile_DataSource::GetSize(SInt64& outSize)
+{
+	outSize = -1; // in case of error
+	OSStatus err = FSGetForkSize(mFileNum, &outSize);
+	return err;
+}
+
+OSStatus MacFile_DataSource::GetPos(SInt64& outPos) const
+{
+	return FSGetForkPosition(mFileNum, &outPos);
+}
+
+OSStatus MacFile_DataSource::SetSize(SInt64 inSize)
+{
+	return FSSetForkSize(mFileNum, SEEK_SET, inSize);
+}
+
+
+OSStatus MacFile_DataSource::ReadBytes(
+					UInt16 positionMode, 
+					SInt64 positionOffset, 
+					UInt32 requestCount, 
+					void *buffer, 
+					UInt32* actualCount)
+{
+	if (actualCount) *actualCount = 0;
+	if (!buffer) return kAudio_ParamError;
+	ByteCount bc_actualCount = 0;
+	OSStatus err = FSReadFork(mFileNum, positionMode, positionOffset, requestCount, buffer, &bc_actualCount);
+	if (actualCount) *actualCount = (UInt32)bc_actualCount;
+	return err;
+}
+
+OSStatus MacFile_DataSource::WriteBytes(
+					UInt16 positionMode, 
+					SInt64 positionOffset, 
+					UInt32 requestCount, 
+					const void *buffer, 
+					UInt32* actualCount)
+{
+	if (!buffer) return kAudio_ParamError;
+	ByteCount bc_actualCount = 0;
+	OSStatus err =  FSWriteFork(mFileNum, positionMode, positionOffset, requestCount, buffer, &bc_actualCount);
+	if (actualCount) *actualCount = (UInt32)bc_actualCount;
+	return err;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define kAudioFileNoCacheMask		0x20
+
+UnixFile_DataSource::UnixFile_DataSource( int inFD, SInt8 inPermissions, Boolean inCloseOnDelete)
+	: DataSource(inCloseOnDelete), mFileD(inFD), mPermissions(inPermissions), mNoCache(0), mCachedSize(-1), mFilePointer(0)
+{
+}
+
+UnixFile_DataSource::~UnixFile_DataSource()
+{
+	if (mCloseOnDelete) close(mFileD);
+}
+	
+OSStatus	UnixFile_DataSource::GetSize(SInt64& outSize)
+{
+#if 0 // 6764274 using the cached file size causes a regression for apps that play a file while writing to it.
+	if (mCachedSize >= 0) {
+		outSize = mCachedSize;
+		return noErr;
+	}
+#endif
+	outSize = -1; // in case of error
+	struct stat stbuf;
+	if (fstat (mFileD, &stbuf) == -1) return kAudio_FileNotFoundError;
+	outSize = mCachedSize = stbuf.st_size;
+	return noErr;
+}
+
+OSStatus	UnixFile_DataSource::SetSize(SInt64 inSize)
+{
+	mCachedSize = -1;
+#if TARGET_OS_WIN32
+	if (chsize (mFileD, inSize)) return kAudioFilePermissionsError;
+#else
+	if (ftruncate (mFileD, inSize) == -1) return kAudioFilePermissionsError;
+#endif
+	mCachedSize = inSize;
+	return noErr;
+}
+
+
+OSStatus	UnixFile_DataSource::GetPos(SInt64& outPos) const
+{
+	outPos = mFilePointer;
+	return noErr;
+}
+
+SInt64		UnixFile_DataSource::UFCurrentOffset (UInt16	positionMode, 
+												SInt64		positionOffset)
+{
+	SInt64 offset = -1;
+	switch (positionMode & kPositionModeMask) 
+	{
+		/*case fsAtMark : 
+		{
+			SInt64 pos;
+			OSStatus result = GetPos (pos);
+				if (result) return result;
+			offset = pos; 
+			break;
+		}*/
+		case SEEK_SET :
+		{
+			offset = positionOffset; 
+			break;
+		}
+		case SEEK_END : 
+		{
+			SInt64 size;
+			OSStatus result = GetSize (size);
+				if (result) return result;
+			offset = size + positionOffset; 
+			break;
+		}
+		case SEEK_CUR :
+		{
+			SInt64 pos;
+			OSStatus result = GetPos (pos);
+				if (result) return result;
+			offset = positionOffset + pos; 
+			break;
+		}
+	}
+	return offset;
+}
+	
+OSStatus	UnixFile_DataSource::ReadBytes(	UInt16 positionMode,
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								void *buffer, 
+								UInt32* actualCount)
+{
+	if (actualCount) *actualCount = 0;
+	if (!buffer) return kAudio_ParamError;
+
+		// can't use current offset as we need to go to the disk too much		
+	SInt64 offset = UFCurrentOffset (positionMode, positionOffset);
+		if (offset < 0) return kAudioFilePositionError;
+
+#if 0 // 6571050 fstat-ing the file every read causes a performance regression
+	// 5931571 check that read may exceed eof and curtail it.
+	do {
+		SInt64 size;
+		OSStatus serr = GetSize(size);
+		if (serr) break;
+		SInt64 remain = size - offset;
+		if (remain < 0) requestCount = 0;
+		else if (requestCount > remain) requestCount = remain;
+	} while (false);
+#endif
+	
+	if (requestCount <= 0) {
+		if (actualCount) *actualCount = 0;
+		return noErr;
+	}
+
+#if !TARGET_OS_WIN32
+	UInt32 noCache = positionMode & kAudioFileNoCacheMask ? 1 : 0;
+	if (noCache != mNoCache) {
+		mNoCache = noCache;
+		fcntl(mFileD, F_NOCACHE, mNoCache);
+	}
+#endif
+
+	size_t readBytes = requestCount;
+#if TARGET_OS_WIN32
+	lseek(mFileD, offset, SEEK_SET);
+	int numBytes = read (mFileD, buffer, readBytes);
+#else
+	ssize_t numBytes = pread (mFileD, buffer, readBytes, offset);
+#endif
+	if (numBytes == -1) return kAudioFilePositionError;
+	mFilePointer = offset + numBytes;
+	
+	if (actualCount) *actualCount = (UInt32)numBytes;
+	return noErr;
+}
+						
+OSStatus	UnixFile_DataSource::WriteBytes(UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								const void *buffer, 
+								UInt32* actualCount)
+{
+	if (!buffer) return kAudio_ParamError;
+
+		// can't use current offset as we need to go to the disk too much		
+	SInt64 offset = UFCurrentOffset (positionMode, positionOffset);
+		if (offset < 0) return kAudioFilePositionError;
+
+	mCachedSize = -1;
+
+	size_t writeBytes = requestCount;
+
+#if !TARGET_OS_WIN32
+	UInt32 noCache = positionMode & kAudioFileNoCacheMask ? 1 : 0;
+	if (noCache != mNoCache) {
+		mNoCache = noCache;
+		fcntl(mFileD, F_NOCACHE, mNoCache);
+	}
+#endif
+
+#if TARGET_OS_WIN32
+	lseek(mFileD, offset, SEEK_SET);
+	int numBytes = write (mFileD, buffer, writeBytes);
+#else
+	ssize_t numBytes = pwrite (mFileD, buffer, writeBytes, offset);
+#endif
+	if (numBytes == -1) return kAudioFilePositionError;
+	mFilePointer = offset + numBytes;
+	
+	if (actualCount) *actualCount = (UInt32)numBytes;
+	return noErr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define NO_CACHE 0
+
+OSStatus Cached_DataSource::ReadFromHeaderCache(
+					SInt64 offset, 
+					UInt32 requestCount,
+					void *buffer, 
+					UInt32* actualCount)
+{
+	if (actualCount) *actualCount = 0;
+	OSStatus err = noErr;
+	ByteCount theActualCount = 0;
+
+#if VERBOSE	
+	printf("read from header %lld %lu   %lld %lu\n", offset, requestCount, 0LL, mHeaderCacheSize);
+#endif
+
+	if (!mHeaderCache()) 
+	{
+		mHeaderCache.allocBytes(mHeaderCacheSize, true);
+		err = mDataSource->ReadBytes(SEEK_SET, 0, mHeaderCacheSize, mHeaderCache(), &mHeaderCacheSize);
+		if (err == kAudioFileEndOfFileError) err = noErr;
+		if (err) return err;
+	}
+	
+	ByteCount firstPart = std::min((ByteCount)requestCount, (ByteCount)(mHeaderCacheSize - offset));
+	ByteCount secondPart = requestCount - firstPart;
+	
+	memcpy(buffer, mHeaderCache + (ByteCount)offset, firstPart);
+	theActualCount = firstPart;
+	
+	if (secondPart) {
+		UInt32 secondPartActualCount = 0;
+		err = mDataSource->ReadBytes(SEEK_SET, mHeaderCacheSize, static_cast<UInt32>(secondPart), (char*)buffer + firstPart, &secondPartActualCount);
+		theActualCount += secondPartActualCount;
+	}
+	
+	if (actualCount) *actualCount = (UInt32)theActualCount;
+	mOffset = offset + theActualCount;
+	
+	return err;
+}
+
+OSStatus Cached_DataSource::ReadBytes(
+					UInt16 positionMode, 
+					SInt64 positionOffset, 
+					UInt32 requestCount, 
+					void *buffer, 
+					UInt32* actualCount)
+{
+	if (actualCount) *actualCount = 0;
+	OSStatus err = noErr;
+	SInt64 size;
+	UInt32 theActualCount = 0;
+
+	if (!buffer) return kAudio_ParamError;
+
+	if ((positionMode & kPositionModeMask) != SEEK_END) size = 0; // not used in this case
+	else 
+	{
+		err = GetSize(size);
+		if (err) return err;
+	}
+
+	SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+	if (offset < 0) return kAudioFilePositionError;
+	
+	if (offset < mHeaderCacheSize) {
+		return ReadFromHeaderCache(offset, requestCount, buffer, actualCount);
+	}
+
+#if NO_CACHE
+	err = mDataSource->ReadBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+	mOffset = offset + theActualCount;
+#else
+
+	SInt64 cacheEnd = mBodyCacheOffset + mBodyCacheCurSize;
+	if (mBodyCache() && requestCount < mBodyCacheSize && offset >= mBodyCacheOffset && offset < cacheEnd)
+	{
+		if (offset + requestCount <= cacheEnd) 
+		{
+			// request is entirely within cache
+#if VERBOSE	
+			printf("request is entirely within cache %lld %lu   %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+			memcpy(buffer, mBodyCache + (size_t)(offset - mBodyCacheOffset), requestCount);
+			theActualCount = requestCount;
+		}
+		else
+		{
+			// part of request is within cache. copy, read next cache block, copy.
+#if VERBOSE	
+			printf("part of request is within cache %lld %lu   %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+			
+			// copy first part.
+			ByteCount firstPart = (ByteCount)(cacheEnd - offset);
+			ByteCount secondPart = requestCount - firstPart;
+#if VERBOSE	
+			printf("memcpy   offset %lld  mBodyCacheOffset %lld  offset - mBodyCacheOffset %lld  firstPart %lu   requestCount %lu\n", 
+						offset, mBodyCacheOffset, offset - mBodyCacheOffset, firstPart, requestCount);
+#endif
+			memcpy(buffer, mBodyCache + (size_t)(offset - mBodyCacheOffset), firstPart);
+			
+			theActualCount = static_cast<UInt32>(firstPart);
+			
+			// read new block
+			SInt64 nextOffset = mBodyCacheOffset + mBodyCacheCurSize;
+			err = mDataSource->ReadBytes(SEEK_SET, nextOffset, mBodyCacheSize, mBodyCache(), &mBodyCacheCurSize);
+			
+			if (err == kAudioFileEndOfFileError) err = noErr;
+			if (err) goto leave;
+
+			mBodyCacheOffset = nextOffset;
+
+			// copy second part
+			secondPart = std::min(secondPart, (ByteCount)mBodyCacheCurSize);
+			if (secondPart) memcpy((char*)buffer + firstPart, mBodyCache(), secondPart);
+			theActualCount = static_cast<UInt32>(firstPart + secondPart);
+		}
+	}
+	else 
+	{
+		if (requestCount > mBodyCacheSize)
+		{
+#if VERBOSE	
+			printf("large request %lld %lu   %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+			// the request is larger than we normally cache, just do a read and don't cache.
+			err = mDataSource->ReadBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+			mOffset = offset + theActualCount;
+		}
+		else
+		{
+			// request is outside cache. read new block.
+#if VERBOSE	
+			printf("request is outside cache %lld %lu   %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+			if (!mBodyCache()) 
+			{
+				mBodyCache.allocBytes(mBodyCacheSize, true);
+#if VERBOSE	
+				printf("alloc mBodyCache %08X\n", mBodyCache());
+#endif
+			}
+			mBodyCacheOffset = offset;
+			err = mDataSource->ReadBytes(SEEK_SET, mBodyCacheOffset, mBodyCacheSize, mBodyCache(), &mBodyCacheCurSize);
+#if VERBOSE	
+			printf("read %08X %d    mBodyCacheOffset %lld   %lu %lu\n", err, err, mBodyCacheOffset, mBodyCacheSize, mBodyCacheCurSize);
+#endif
+			if (err == kAudioFileEndOfFileError) err = noErr;
+			if (err) return err;
+
+			theActualCount = std::min(requestCount, mBodyCacheCurSize);
+			memcpy(buffer, mBodyCache(), theActualCount);
+		}
+		
+	}
+
+leave:
+#endif
+	if (actualCount) *actualCount = (UInt32)theActualCount;
+#if VERBOSE	
+	printf("<<read err %d  actualCount %lu\n", err, *actualCount);
+#endif
+	return err;
+}
+
+OSStatus Cached_DataSource::WriteBytes(
+					UInt16 positionMode, 
+					SInt64 positionOffset, 
+					UInt32 requestCount, 
+					const void *buffer, 
+					UInt32* actualCount)
+{
+	OSStatus err = noErr;
+	SInt64 size;
+
+	if (!buffer) return kAudio_ParamError;
+	
+	if ((positionMode & kPositionModeMask) != SEEK_END) size = 0; // not used in this case
+	else 
+	{
+		err = GetSize(size);
+		if (err) return err;
+	}
+
+	SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+	if (offset < 0) return kAudioFilePositionError;
+	
+	if (mHeaderCache() && offset < mHeaderCacheSize) 
+	{
+		// header cache write through
+		ByteCount firstPart = std::min((ByteCount)requestCount, (ByteCount)(mHeaderCacheSize - offset));
+#if VERBOSE	
+		printf("header cache write through %lu %lu\n", mHeaderCacheSize, firstPart);
+#endif
+		memcpy(mHeaderCache + (size_t)offset, buffer, firstPart);
+	}
+		
+#if VERBOSE	
+	printf("write %lld %lu    %lld %d %lld\n", offset, requestCount, mOffset, positionMode, positionOffset);
+#endif
+
+	SInt64 cacheEnd = mBodyCacheOffset + mBodyCacheCurSize;
+	if (mBodyCache() && offset >= mBodyCacheOffset && offset < cacheEnd)
+	{
+		// body cache write through
+		ByteCount firstPart = std::min((SInt64)requestCount, cacheEnd - offset);
+#if VERBOSE	
+		printf("body cache write through %lld %lu  %lld %lu\n", mBodyCacheOffset, mBodyCacheCurSize, offset, firstPart);
+#endif
+		memcpy(mBodyCache + (offset - mBodyCacheOffset), buffer, firstPart);
+	}
+	
+	UInt32 theActualCount;
+	err = mDataSource->WriteBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+	
+	mOffset = offset + theActualCount;
+	if (actualCount) *actualCount = (UInt32)theActualCount;
+	
+	return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+Seekable_DataSource::Seekable_DataSource(	void * inClientData,
+							AudioFile_ReadProc					inReadFunc, 
+							AudioFile_WriteProc					inWriteFunc, 
+							AudioFile_GetSizeProc				inGetSizeFunc,
+							AudioFile_SetSizeProc				inSetSizeFunc)
+	: DataSource(false), mClientData(inClientData), mReadFunc(inReadFunc), mWriteFunc(inWriteFunc), 
+		mSizeFunc(inGetSizeFunc), mSetSizeFunc(inSetSizeFunc)
+{
+}
+
+Seekable_DataSource::~Seekable_DataSource()
+{
+}
+
+
+OSStatus Seekable_DataSource::GetSize(SInt64& outSize)
+{
+	if (!mSizeFunc) {
+		outSize = LLONG_MAX;
+	} else {
+		outSize = (*mSizeFunc)(mClientData);
+	}
+	return noErr;
+}
+
+OSStatus Seekable_DataSource::SetSize(SInt64 inSize)
+{
+	if (!mSetSizeFunc) return kAudioFileOperationNotSupportedError;
+	return (*mSetSizeFunc)(mClientData, inSize);
+}
+
+OSStatus Seekable_DataSource::ReadBytes(	
+							UInt16 positionMode, 
+							SInt64 positionOffset, 
+							UInt32 requestCount, 
+							void *buffer, 
+							UInt32* actualCount)
+{
+	OSStatus err;
+	
+	if (actualCount) *actualCount = 0;
+	if (!mReadFunc) return kAudioFileOperationNotSupportedError;
+	if (!buffer) return kAudio_ParamError;
+
+	positionMode &= kPositionModeMask;
+
+	SInt64 size;
+	err = GetSize(size);
+	if (err) return err;
+
+	SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+	
+	// request is outside bounds of file
+	if (offset < 0) 
+		return kAudioFilePositionError;
+	if (offset >= size) 
+		return kAudioFileEndOfFileError;
+	
+	// reduce request if it exceeds the amount available
+	requestCount = static_cast<UInt32>(std::min((SInt64)requestCount, size - offset));
+	
+	UInt32 theActualCount = 0;
+	err = (*mReadFunc)(mClientData, offset, requestCount, buffer, &theActualCount);
+	if (actualCount) *actualCount = theActualCount;
+	mOffset = offset + theActualCount;
+	return err;
+}
+
+					
+OSStatus Seekable_DataSource::WriteBytes(
+							UInt16 positionMode, 
+							SInt64 positionOffset, 
+							UInt32 requestCount, 
+							const void *buffer, 
+							UInt32* actualCount)
+{
+	OSStatus err;
+	
+	if (!mWriteFunc) return kAudioFileOperationNotSupportedError;
+	if (!buffer) return kAudio_ParamError;
+
+	SInt64 size;
+	positionMode &= kPositionModeMask;
+	if (positionMode != SEEK_END) size = 0; // not used in this case
+	else 
+	{
+		err = GetSize(size);
+		if (err) return err;
+	}
+
+	SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+	if (offset < 0) return kAudioFilePositionError;
+	
+	UInt32 theActualCount;
+	err = (*mWriteFunc)(mClientData, offset, requestCount, buffer, &theActualCount);
+	if (err) return err;
+	if (actualCount) *actualCount = theActualCount;
+	mOffset = offset + theActualCount;
+	return noErr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+OSStatus Buffer_DataSource::ReadBytes(
+								UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								void *buffer, 
+								UInt32* actualCount)
+{
+	if (actualCount) *actualCount = 0;
+	SInt64 offsetWithinBuffer = CalcOffset(positionMode, positionOffset, mOffset, mDataByteSize + mStartOffset) - mStartOffset;		
+	if (offsetWithinBuffer < 0 || offsetWithinBuffer >= mDataByteSize) return kAudioFilePositionError;
+	
+	SInt64 bytesAfterOffset = mDataByteSize - offsetWithinBuffer;
+	SInt64 theActualCount = std::min(bytesAfterOffset, (SInt64)requestCount);
+
+	if (theActualCount <= 0) {
+		if (actualCount) *actualCount = 0;
+		return kAudio_ParamError;
+	}
+
+	memcpy(buffer, mData + offsetWithinBuffer, theActualCount);
+	
+	if (actualCount) *actualCount = static_cast<UInt32>(theActualCount);
+	mOffset = offsetWithinBuffer + theActualCount;
+
+	return noErr;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h
new file mode 100644
index 0000000..6c79c94
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h
@@ -0,0 +1,372 @@
+/*
+     File: DataSource.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __DataSource_h__
+#define __DataSource_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioToolbox/AudioFile.h>
+#else
+	#include <ConditionalMacros.h>
+	#include "AudioFile.h"
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdexcept>
+#include "CAAutoDisposer.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class DataSource
+{
+public:
+	
+	DataSource(Boolean inCloseOnDelete);
+	virtual ~DataSource();
+		
+	virtual OSStatus GetSize32(UInt32& outSize)
+	{
+		SInt64 size64;
+		OSStatus err = GetSize(size64);
+		if (err) return err;
+		if (size64 > 0x00000000FFFFffffLL) return kAudioFileDoesNotAllow64BitDataSizeError;
+		outSize = (UInt32)size64;
+		return noErr;
+	}
+	
+	virtual OSStatus GetSize(SInt64& outSize) =0;
+	
+	virtual OSStatus SetSize(SInt64 inSize)=0;
+	
+	virtual OSStatus GetPos(SInt64& outPos) const=0; 
+	
+	/* non seekable data sources should use fsAtMark for the positionMode (or SEEK_CUR with offset zero, 
+		or SEEK_SET with offset equal to the current position in the stream, in other words no seeking from the 
+		current position is allowed.)
+	*/
+	
+	virtual OSStatus ReadBytes(	UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								void *buffer, 
+								UInt32* actualCount)=0;
+						
+	virtual OSStatus WriteBytes(UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								const void *buffer, 
+								UInt32* actualCount)=0;
+	
+	virtual void SetCloseOnDelete(Boolean inFlag) { mCloseOnDelete = inFlag; }
+	
+	virtual Boolean CanSeek() const=0;
+	virtual Boolean CanGetSize() const=0;
+	virtual Boolean CanSetSize() const=0;
+	virtual Boolean CanRead() const=0;
+	virtual Boolean CanWrite() const=0;
+	
+protected:
+	Boolean mCloseOnDelete;
+	
+	/* utility method */
+	SInt64 CalcOffset(	UInt16 positionMode, 
+						SInt64 positionOffset,
+						SInt64 currentOffset,
+						SInt64 size);
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+	Initialize with a Macintosh file fork ref num as obtained from FSOpenFork.
+*/
+
+#if 0
+
+class MacFile_DataSource : public DataSource
+{
+	FSIORefNum mFileNum;
+	SInt8 mPermissions;
+	
+public:
+
+	MacFile_DataSource(	FSIORefNum inForkRefNum, SInt8 inPermissions, Boolean inCloseOnDelete);
+	virtual ~MacFile_DataSource();
+	
+	virtual OSStatus GetSize(SInt64& outSize);
+	virtual OSStatus GetPos(SInt64& outPos) const; 
+	
+	virtual OSStatus SetSize(SInt64 inSize);
+	
+	virtual OSStatus ReadBytes(	UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								void *buffer, 
+								UInt32* actualCount);
+						
+	virtual OSStatus WriteBytes(UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								const void *buffer, 
+								UInt32* actualCount);
+	
+	virtual Boolean CanSeek() const { return true; }
+	virtual Boolean CanGetSize() const { return true; }
+	virtual Boolean CanSetSize() const { return true; }
+	
+	virtual Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+	virtual Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+};
+#endif
+
+
+class UnixFile_DataSource : public DataSource
+{
+	int	  mFileD;
+	SInt8 mPermissions;
+	UInt32 mNoCache;
+	SInt64 mCachedSize;
+	SInt64 mFilePointer;
+	
+public:
+
+	UnixFile_DataSource( int inFD, SInt8 inPermissions, Boolean inCloseOnDelete);
+	virtual ~UnixFile_DataSource();
+	
+	virtual OSStatus GetSize(SInt64& outSize);
+	virtual OSStatus GetPos(SInt64& outPos) const; 
+	
+	virtual OSStatus SetSize(SInt64 inSize);
+	
+	virtual OSStatus ReadBytes(	UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								void *buffer, 
+								UInt32* actualCount);
+						
+	virtual OSStatus WriteBytes(UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								const void *buffer, 
+								UInt32* actualCount);
+	
+	virtual Boolean CanSeek() const { return true; }
+	virtual Boolean CanGetSize() const { return true; }
+	virtual Boolean CanSetSize() const { return true; }
+	
+	virtual Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+	virtual Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+
+private:
+
+	SInt64	UFCurrentOffset (UInt16		positionMode, 
+							SInt64		positionOffset);
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+	A wrapper that caches the wrapped source's header.
+*/
+class Cached_DataSource : public DataSource
+{
+	DataSource* mDataSource;
+	CAAutoFree<UInt8> mHeaderCache;
+	UInt32 mHeaderCacheSize;
+	CAAutoFree<UInt8> mBodyCache;
+	UInt32 mBodyCacheSize;
+	UInt32 mBodyCacheCurSize;
+	SInt64 mBodyCacheOffset;
+	SInt64 mOffset;
+	Boolean mOwnDataSource;
+	
+public:
+
+	Cached_DataSource(DataSource* inDataSource, UInt32 inHeaderCacheSize = 4096, UInt32 inBodyCacheSize = 32768, Boolean inOwnDataSource = true)
+					: DataSource(false), 
+					mDataSource(inDataSource), mHeaderCacheSize(inHeaderCacheSize), 
+					mBodyCacheSize(inBodyCacheSize), mBodyCacheCurSize(0), mBodyCacheOffset(-1), 
+					mOffset(0),
+					mOwnDataSource(inOwnDataSource)
+				{
+				}
+				
+	virtual ~Cached_DataSource()
+				{
+					if (mOwnDataSource) delete mDataSource;
+				}
+
+	
+	virtual OSStatus GetSize(SInt64& outSize) { return mDataSource->GetSize(outSize); }
+	virtual OSStatus GetPos(SInt64& outPos) const { return mDataSource->GetPos(outPos); } 
+	
+	virtual OSStatus SetSize(SInt64 inSize) { return mDataSource->SetSize(inSize); }
+	
+	virtual OSStatus ReadBytes(		UInt16 positionMode, 
+									SInt64 positionOffset, 
+									UInt32 requestCount, 
+									void *buffer, 
+									UInt32* actualCount);
+						
+	virtual OSStatus WriteBytes(	UInt16 positionMode, 
+									SInt64 positionOffset, 
+									UInt32 requestCount, 
+									const void *buffer, 
+									UInt32* actualCount);
+	
+	OSStatus ReadFromHeaderCache(	SInt64 offset, 
+									UInt32 requestCount,
+									void *buffer, 
+									UInt32* actualCount);
+	
+	virtual Boolean CanSeek() const { return mDataSource->CanSeek(); }
+	virtual Boolean CanGetSize() const { return mDataSource->CanGetSize(); }
+	virtual Boolean CanSetSize() const { return mDataSource->CanSetSize(); }
+	
+	virtual Boolean CanRead() const { return mDataSource->CanRead(); }
+	virtual Boolean CanWrite() const { return mDataSource->CanWrite(); }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+/* This class calls user supplied routines on demand. */
+
+class Seekable_DataSource : public DataSource
+{
+	void * mClientData;
+	SInt64 mOffset;
+	
+	AudioFile_ReadProc mReadFunc;
+	AudioFile_WriteProc mWriteFunc;
+	AudioFile_GetSizeProc mSizeFunc;
+	AudioFile_SetSizeProc mSetSizeFunc;
+	
+public:
+	Seekable_DataSource(	void * 								inClientData,
+							AudioFile_ReadProc					inReadFunc, 
+							AudioFile_WriteProc					inWriteFunc, 
+							AudioFile_GetSizeProc				inGetSizeFunc,
+							AudioFile_SetSizeProc				inSetSizeFunc
+					);
+	
+	virtual ~Seekable_DataSource();
+	
+	virtual OSStatus GetSize(SInt64& outSize);
+	virtual OSStatus GetPos(SInt64& outPos) const { outPos = mOffset; return noErr; }; 
+	
+	virtual OSStatus SetSize(SInt64 inSize);
+	
+	virtual OSStatus ReadBytes(	UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								void *buffer, 
+								UInt32* actualCount);
+						
+	virtual OSStatus WriteBytes(UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								const void *buffer, 
+								UInt32* actualCount);
+
+	virtual Boolean CanSeek() const { return true; }
+	virtual Boolean CanGetSize() const { return mSizeFunc != 0; }
+	virtual Boolean CanSetSize() const { return mSetSizeFunc != 0; }
+	virtual Boolean CanRead() const { return mReadFunc != 0; }
+	virtual Boolean CanWrite() const { return mWriteFunc != 0; }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class Buffer_DataSource : public DataSource
+{
+	UInt32 mDataByteSize;
+	const char * mData;
+
+	SInt64 mStartOffset;
+	SInt64 mOffset;
+public:
+	Buffer_DataSource(	UInt32			inDataByteSize,
+						const void *	inData,
+						SInt64			inStartOffset = 0
+					) : DataSource(false), mDataByteSize(inDataByteSize), mData((const char*)inData), mStartOffset(inStartOffset), mOffset(mStartOffset) {}
+	
+	virtual ~Buffer_DataSource() {}
+	
+	virtual OSStatus GetSize(SInt64& outSize) { outSize = mDataByteSize + mStartOffset; return noErr; }
+	virtual OSStatus GetPos(SInt64& outPos) const { outPos = mOffset; return noErr; }; 
+	
+	virtual OSStatus SetSize(SInt64 inSize) { throw std::runtime_error("not writable"); }
+	
+	virtual OSStatus ReadBytes(	UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								void *buffer, 
+								UInt32* actualCount);
+						
+	virtual OSStatus WriteBytes(UInt16 positionMode, 
+								SInt64 positionOffset, 
+								UInt32 requestCount, 
+								const void *buffer, 
+								UInt32* actualCount) { throw std::runtime_error("not writable"); }
+
+	virtual Boolean CanSeek() const { return true; }
+	virtual Boolean CanGetSize() const { return true; }
+	virtual Boolean CanSetSize() const { return false; }
+	virtual Boolean CanRead() const { return true; }
+	virtual Boolean CanWrite() const { return false; }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp
new file mode 100644
index 0000000..612bc4d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp
@@ -0,0 +1,2393 @@
+/*
+     File: AUBase.cpp
+ Abstract: AUBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUBase.h"
+#include "AUDispatch.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include <algorithm>
+#include <syslog.h>
+#include "CAAudioChannelLayout.h"
+#include "CAHostTimeBase.h"
+#include "CAVectorUnit.h"
+#include "CAXException.h"
+
+
+
+#if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+	// our compiler does ALL floating point with SSE
+	inline int  GETCSR ()    { int _result; asm volatile ("stmxcsr %0" : "=m" (*&_result) ); return _result; }
+	inline void SETCSR (int a)    { int _temp = a; asm volatile( "ldmxcsr %0" : : "m" (*&_temp ) ); }
+
+	#define DISABLE_DENORMALS int _savemxcsr = GETCSR(); SETCSR(_savemxcsr | 0x8040);
+	#define RESTORE_DENORMALS SETCSR(_savemxcsr);
+#else
+	#define DISABLE_DENORMALS
+	#define RESTORE_DENORMALS
+#endif
+
+static bool sAUBaseCFStringsInitialized = false;
+// this is used for the presets
+static CFStringRef kUntitledString = NULL;
+//these are the current keys for the class info document
+static CFStringRef kVersionString = NULL;
+static CFStringRef kTypeString = NULL;
+static CFStringRef kSubtypeString = NULL;
+static CFStringRef kManufacturerString = NULL;
+static CFStringRef kDataString = NULL;
+static CFStringRef kNameString = NULL;
+static CFStringRef kRenderQualityString = NULL;
+static CFStringRef kCPULoadString = NULL;
+static CFStringRef kElementNameString = NULL;
+static CFStringRef kPartString = NULL;
+
+SInt32 AUBase::sVectorUnitType = kVecUninitialized;
+
+//_____________________________________________________________________________
+//
+AUBase::AUBase(	AudioComponentInstance			inInstance, 
+				UInt32							numInputElements,
+				UInt32							numOutputElements,
+				UInt32							numGroupElements) :
+	ComponentBase(inInstance),
+	mElementsCreated(false),
+	mInitialized(false),
+	mHasBegunInitializing(false),
+	mInitNumInputEls(numInputElements), mInitNumOutputEls(numOutputElements), 
+#if !CA_BASIC_AU_FEATURES
+	mInitNumGroupEls(numGroupElements),
+#endif
+	mRenderCallbacksTouched(false),
+	mRenderThreadID (NULL),
+	mWantsRenderThreadID (false),
+	mLastRenderError(0),
+	mUsesFixedBlockSize(false),
+	mBuffersAllocated(false),
+	mLogString (NULL),
+    mNickName (NULL),
+	mAUMutex(NULL)
+	#if !CA_NO_AU_UI_FEATURES
+		,
+		mContextName(NULL)
+	#endif
+{
+	ResetRenderTime ();
+	
+	if(!sAUBaseCFStringsInitialized)
+	{
+		kUntitledString = CFSTR("Untitled");
+		kVersionString = CFSTR(kAUPresetVersionKey);
+		kTypeString = CFSTR(kAUPresetTypeKey);
+		kSubtypeString = CFSTR(kAUPresetSubtypeKey);
+		kManufacturerString = CFSTR(kAUPresetManufacturerKey);
+		kDataString = CFSTR(kAUPresetDataKey);
+		kNameString = CFSTR(kAUPresetNameKey);
+		kRenderQualityString = CFSTR(kAUPresetRenderQualityKey);
+		kCPULoadString = CFSTR(kAUPresetCPULoadKey);
+		kElementNameString = CFSTR(kAUPresetElementNameKey);
+		kPartString = CFSTR(kAUPresetPartKey);
+		sAUBaseCFStringsInitialized = true;
+	}
+
+	if (sVectorUnitType == kVecUninitialized) {
+		sVectorUnitType = CAVectorUnit::GetVectorUnitType() ;
+	}
+
+	mAudioUnitAPIVersion = 2;
+	
+	SetMaxFramesPerSlice(kAUDefaultMaxFramesPerSlice);
+
+	GlobalScope().Initialize(this, kAudioUnitScope_Global, 1);
+	
+#if !CA_NO_AU_UI_FEATURES
+	memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+#endif
+
+
+	mCurrentPreset.presetNumber = -1;
+	mCurrentPreset.presetName = kUntitledString;
+	CFRetain (mCurrentPreset.presetName);
+}
+
+//_____________________________________________________________________________
+//
+AUBase::~AUBase()
+{
+	if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+#if !CA_NO_AU_UI_FEATURES
+	if (mContextName) CFRelease (mContextName);
+#endif
+	if (mLogString) delete [] mLogString;
+    if (mNickName) CFRelease(mNickName);
+}
+
+//_____________________________________________________________________________
+//
+void	AUBase::CreateElements()
+{
+	if (!mElementsCreated) {
+		Inputs().Initialize(this, kAudioUnitScope_Input, mInitNumInputEls);
+		Outputs().Initialize(this, kAudioUnitScope_Output, mInitNumOutputEls);
+#if !CA_BASIC_AU_FEATURES
+		Groups().Initialize(this, kAudioUnitScope_Group, mInitNumGroupEls);
+#endif
+		CreateExtendedElements();
+		
+		mElementsCreated = true;
+	}
+}
+
+//_____________________________________________________________________________
+//
+void	AUBase::SetMaxFramesPerSlice(UInt32 nFrames)
+{
+	mMaxFramesPerSlice = nFrames;
+	if (mBuffersAllocated)
+		ReallocateBuffers();
+	PropertyChanged(kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0);
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::CanSetMaxFrames() const
+{
+	return IsInitialized() ? kAudioUnitErr_Initialized : OSStatus(noErr);
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::ReallocateBuffers()
+{
+	CreateElements();
+	
+	UInt32 nOutputs = Outputs().GetNumberOfElements();
+	for (UInt32 i = 0; i < nOutputs; ++i) {
+		AUOutputElement *output = GetOutput(i);
+		output->AllocateBuffer();	// does no work if already allocated
+	}
+	UInt32 nInputs = Inputs().GetNumberOfElements();
+	for (UInt32 i = 0; i < nInputs; ++i) {
+		AUInputElement *input = GetInput(i);
+		input->AllocateBuffer();	// does no work if already allocated
+	}
+	mBuffersAllocated = true;
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::DeallocateIOBuffers()
+{
+	if (!mBuffersAllocated)
+		return;
+
+	UInt32 nOutputs = Outputs().GetNumberOfElements();
+	for (UInt32 i = 0; i < nOutputs; ++i) {
+		AUOutputElement *output = GetOutput(i);
+		output->DeallocateBuffer();
+	}
+	UInt32 nInputs = Inputs().GetNumberOfElements();
+	for (UInt32 i = 0; i < nInputs; ++i) {
+		AUInputElement *input = GetInput(i);
+		input->DeallocateBuffer();
+	}
+	mBuffersAllocated = false;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::DoInitialize()
+{
+	OSStatus result = noErr;
+	
+	if (!mInitialized) {
+		result = Initialize();
+		if (result == noErr) {
+			if (CanScheduleParameters())
+				mParamList.reserve(24);
+			mHasBegunInitializing = true;
+			ReallocateBuffers();	// calls CreateElements()
+			mInitialized = true;	// signal that it's okay to render
+			CAMemoryBarrier();
+		}
+	}
+
+	return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::Initialize()
+{
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::PreDestructor()
+{
+	// this is called from the ComponentBase dispatcher, which doesn't know anything about our (optional) lock
+	CAMutex::Locker lock(mAUMutex);
+	DoCleanup();
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::DoCleanup()
+{
+	if (mInitialized)
+		Cleanup();
+	
+	DeallocateIOBuffers();
+	ResetRenderTime ();
+
+	mInitialized = false;
+	mHasBegunInitializing = false;
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::Cleanup()
+{
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::Reset(					AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement)
+{
+	ResetRenderTime ();
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID				inID,
+													AudioUnitScope					inScope,
+													AudioUnitElement				inElement,
+													UInt32 &						outDataSize,
+													Boolean &						outWritable)
+{
+	OSStatus result = noErr;
+	bool validateElement = true;
+	
+	switch (inID) {
+	case kAudioUnitProperty_MakeConnection:
+		ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(AudioUnitConnection);
+		outWritable = true;
+		break;
+		
+		
+	case kAudioUnitProperty_SetRenderCallback:
+		ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
+		ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(AURenderCallbackStruct);
+		outWritable = true;
+		break;
+		
+	case kAudioUnitProperty_StreamFormat:
+		outDataSize = sizeof(CAStreamBasicDescription);
+		outWritable = IsStreamFormatWritable(inScope, inElement);
+		break;
+
+	case kAudioUnitProperty_SampleRate:
+		outDataSize = sizeof(Float64);
+		outWritable = IsStreamFormatWritable(inScope, inElement);
+		break;
+
+	case kAudioUnitProperty_ClassInfo:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(CFPropertyListRef);
+		outWritable = true;
+		break;
+
+	case kAudioUnitProperty_FactoryPresets:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		result = GetPresets(NULL);
+		if (!result) {
+			outDataSize = sizeof(CFArrayRef);
+			outWritable = false;
+		}
+		break;
+		
+	case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+	case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(AUPreset);
+		outWritable = true;
+		break;
+	
+	case kAudioUnitProperty_ElementName:
+		outDataSize = sizeof (CFStringRef);
+		outWritable = true;
+		break;
+	
+	case kAudioUnitProperty_ParameterList:
+		{
+			UInt32 nparams = 0;
+			result = GetParameterList(inScope, NULL, nparams);
+			
+			outDataSize = sizeof(AudioUnitParameterID) * nparams;
+			outWritable = false;
+			validateElement = false;
+		}
+		break;
+		
+	case kAudioUnitProperty_ParameterInfo:
+		outDataSize = sizeof(AudioUnitParameterInfo);
+		outWritable = false;
+		validateElement = false;
+		break;
+
+	case kAudioUnitProperty_ParameterHistoryInfo:
+		outDataSize = sizeof(AudioUnitParameterHistoryInfo);
+		outWritable = false;
+		validateElement = false;
+		break;
+
+	case kAudioUnitProperty_ElementCount:
+		outDataSize = sizeof(UInt32);
+		outWritable = BusCountWritable(inScope);
+		validateElement = false;
+		break;
+	
+	case kAudioUnitProperty_Latency:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(Float64);
+		outWritable = false;
+		break;
+	
+	case kAudioUnitProperty_TailTime:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		if (SupportsTail()) {
+			outDataSize = sizeof(Float64);
+			outWritable = false;
+		} else
+			goto InvalidProperty;
+		break;
+	
+	case kAudioUnitProperty_MaximumFramesPerSlice:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(UInt32);
+		outWritable = true;
+		break;
+	
+	case kAudioUnitProperty_LastRenderError:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(OSStatus);
+		outWritable = false;
+		break;
+		
+	case kAudioUnitProperty_SupportedNumChannels:
+	{
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		UInt32 num = SupportedNumChannels (NULL);
+		if (num) {
+			outDataSize = sizeof (AUChannelInfo) * num;
+			result = noErr;
+		} else
+			goto InvalidProperty;
+		outWritable = false;
+		break;
+	}
+	
+	case kAudioUnitProperty_SupportedChannelLayoutTags:
+	{
+		UInt32 numLayouts = GetChannelLayoutTags(inScope, inElement, NULL);
+		if (numLayouts) {
+			outDataSize = numLayouts * sizeof(AudioChannelLayoutTag);
+			result = noErr;
+		} else
+			goto InvalidProperty;
+		outWritable = false;
+		validateElement = false; //already done it
+		break;
+	}
+	
+	case kAudioUnitProperty_AudioChannelLayout:
+	{
+		outWritable = false;
+		outDataSize = GetAudioChannelLayout(inScope, inElement, NULL, outWritable);
+		if (outDataSize) {
+			result = noErr;
+		} else {
+			if (GetChannelLayoutTags(inScope, inElement, NULL) == 0)
+				goto InvalidProperty;
+			else
+				result = kAudioUnitErr_InvalidPropertyValue;
+		}
+		validateElement = false; //already done it
+		break;
+	}
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+	case kAudioUnitProperty_ShouldAllocateBuffer:
+		ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
+		outWritable = true;
+		outDataSize = sizeof(UInt32);
+		break;
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	case kAudioUnitProperty_FastDispatch:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		if (!IsCMgrObject()) goto InvalidProperty;
+		outDataSize = sizeof(void *);
+		outWritable = false;
+		validateElement = false;
+		break;
+
+	case kAudioUnitProperty_GetUIComponentList:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = GetNumCustomUIComponents();
+		if (outDataSize == 0)
+			goto InvalidProperty;
+		outDataSize *= sizeof (AudioComponentDescription);
+		
+		outWritable = false;
+		break;
+#endif
+	
+	case kAudioUnitProperty_ParameterValueStrings:
+		result = GetParameterValueStrings(inScope, inElement, NULL);
+		if (result == noErr) {
+			outDataSize = sizeof(CFArrayRef);
+			outWritable = false;
+			validateElement = false;
+		}
+		break;
+
+#if !CA_NO_AU_HOST_CALLBACKS
+	case kAudioUnitProperty_HostCallbacks:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(mHostCallbackInfo);
+		outWritable = true;
+		break;
+#endif
+#if !CA_NO_AU_UI_FEATURES
+	case kAudioUnitProperty_ContextName:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outDataSize = sizeof(CFStringRef);
+		outWritable = true;
+		break;
+	
+	case kAudioUnitProperty_IconLocation:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		outWritable = false;
+		if (!HasIcon())
+			goto InvalidProperty;
+		outDataSize = sizeof(CFURLRef);
+		break;
+
+	case kAudioUnitProperty_ParameterClumpName:
+		outDataSize = sizeof(AudioUnitParameterNameInfo );
+		outWritable = false;
+		break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+	case 'lrst' :  // kAudioUnitProperty_LastRenderedSampleTime
+		outDataSize = sizeof(Float64);
+		outWritable = false;
+		break;
+	
+    case kAudioUnitProperty_NickName:
+        ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+        outDataSize = sizeof(CFStringRef);
+        outWritable = true;
+        break;
+
+	default:
+		result = GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+		validateElement = false;
+		break;
+	}
+
+	if (result == noErr && validateElement) {
+		ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);	
+	}
+	
+	return result;
+InvalidProperty:
+	return kAudioUnitErr_InvalidProperty;
+InvalidScope:
+	return kAudioUnitErr_InvalidScope;
+InvalidElement:
+	return kAudioUnitErr_InvalidElement;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::DispatchGetProperty(	AudioUnitPropertyID 			inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement			 	inElement,
+													void *							outData)
+{
+	// NOTE: We're currently only called from AUBase::ComponentEntryDispatch, which
+	// calls DispatchGetPropertyInfo first, which performs validation of the scope/element,
+	// and ensures that the outData buffer is non-null and large enough.
+	OSStatus result = noErr;
+
+	switch (inID) {
+	case kAudioUnitProperty_StreamFormat:
+		*(CAStreamBasicDescription *)outData = GetStreamFormat(inScope, inElement);
+		break;
+	
+	case kAudioUnitProperty_SampleRate:
+		*(Float64 *)outData = GetStreamFormat(inScope, inElement).mSampleRate;
+		break;
+	
+	case kAudioUnitProperty_ParameterList:
+		{
+			UInt32 nparams = 0;
+			result = GetParameterList(inScope, (AudioUnitParameterID *)outData, nparams);
+		}
+		break;
+
+	case kAudioUnitProperty_ParameterInfo:
+		result = GetParameterInfo(inScope, inElement, *(AudioUnitParameterInfo *)outData);
+		break;
+
+	case kAudioUnitProperty_ParameterHistoryInfo:
+		{
+			AudioUnitParameterHistoryInfo* info = (AudioUnitParameterHistoryInfo*)outData;
+			result = GetParameterHistoryInfo(inScope, inElement, info->updatesPerSecond, info->historyDurationInSeconds);
+		}
+		break;
+
+	case kAudioUnitProperty_ClassInfo:
+		{
+			*(CFPropertyListRef *)outData = NULL;
+			result = SaveState((CFPropertyListRef *)outData);
+		}
+		break;
+
+	case kAudioUnitProperty_FactoryPresets:
+		{
+			*(CFArrayRef *)outData = NULL;
+			result = GetPresets ((CFArrayRef *)outData);
+		}
+		break;
+	
+	case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+	case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+		{
+			*(AUPreset *)outData = mCurrentPreset;
+				
+				// retain current string (as client owns a reference to it and will release it)
+			if (inID == kAudioUnitProperty_PresentPreset && mCurrentPreset.presetName) 
+				CFRetain (mCurrentPreset.presetName);
+
+			result = noErr;
+		}
+		break;
+	
+	case kAudioUnitProperty_ElementName:
+		{
+			AUElement * element = GetElement(inScope, inElement);
+			if (element->HasName()) {
+				*(CFStringRef *)outData = element->GetName();
+				CFRetain (element->GetName());
+				result = noErr;
+			} else
+				result = kAudioUnitErr_InvalidPropertyValue;
+		}
+		break;
+
+	case kAudioUnitProperty_ElementCount:
+		*(UInt32 *)outData = GetScope(inScope).GetNumberOfElements();
+		break;
+	
+	case kAudioUnitProperty_Latency:
+		*(Float64 *)outData = GetLatency();
+		break;
+
+	case kAudioUnitProperty_TailTime:
+		if (SupportsTail())
+			*(Float64 *)outData = GetTailTime();
+		else
+			result = kAudioUnitErr_InvalidProperty;
+		break;
+	
+	case kAudioUnitProperty_MaximumFramesPerSlice:
+		*(UInt32 *)outData = mMaxFramesPerSlice;
+		break;
+
+	case kAudioUnitProperty_LastRenderError:
+		*(OSStatus *)outData = mLastRenderError;
+		mLastRenderError = 0;
+		break;
+
+	case kAudioUnitProperty_SupportedNumChannels:
+		{
+			const AUChannelInfo* infoPtr = NULL;
+			UInt32 num = SupportedNumChannels (&infoPtr);
+			if(num != 0 && infoPtr != NULL)
+				memcpy (outData, infoPtr, num * sizeof (AUChannelInfo));
+		}
+		break;
+
+	case kAudioUnitProperty_SupportedChannelLayoutTags:
+		{
+			AudioChannelLayoutTag* ptr = outData ? static_cast<AudioChannelLayoutTag*>(outData) : NULL;
+			UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, ptr);
+			if (numLayouts == 0)
+				result = kAudioUnitErr_InvalidProperty;
+		}
+		break;
+		
+	case kAudioUnitProperty_AudioChannelLayout:
+	{	
+		AudioChannelLayout* ptr = outData ? static_cast<AudioChannelLayout*>(outData) : NULL;
+		Boolean writable;
+		UInt32 dataSize = GetAudioChannelLayout(inScope, inElement, ptr, writable);
+		if (!dataSize) {
+			result = kAudioUnitErr_InvalidProperty;
+		}
+		break;
+	}
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+	case kAudioUnitProperty_ShouldAllocateBuffer:
+	{
+		AUIOElement * element = GetIOElement(inScope, inElement);
+		*(UInt32*)outData = element->WillAllocateBuffer();
+		break;
+	}
+#endif
+
+ 	case kAudioUnitProperty_ParameterValueStrings:
+		result = GetParameterValueStrings(inScope, inElement, (CFArrayRef *)outData);
+		break;
+		
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	case kAudioUnitProperty_FastDispatch:
+		if (!IsCMgrObject()) result = kAudioUnitErr_InvalidProperty;
+		else {
+			switch (inElement) {
+			case kAudioUnitGetParameterSelect:
+				*(AudioUnitGetParameterProc *)outData = (AudioUnitGetParameterProc)CMgr_AudioUnitBaseGetParameter;
+				break;
+			case kAudioUnitSetParameterSelect:
+				*(AudioUnitSetParameterProc *)outData = (AudioUnitSetParameterProc)CMgr_AudioUnitBaseSetParameter;
+				break;
+			case kAudioUnitRenderSelect:
+				if (AudioUnitAPIVersion() > 1)
+					*(AudioUnitRenderProc *)outData = (AudioUnitRenderProc)CMgr_AudioUnitBaseRender;
+				else result = kAudioUnitErr_InvalidElement;
+				break;
+			default:
+				result = GetProperty(inID, inScope, inElement, outData);
+				break;
+			}
+		}
+		break;
+
+	case kAudioUnitProperty_GetUIComponentList:
+		GetUIComponentDescs ((ComponentDescription*)outData);
+		break;
+#endif
+
+#if !CA_NO_AU_HOST_CALLBACKS
+	case kAudioUnitProperty_HostCallbacks:
+		memcpy(outData, &mHostCallbackInfo, sizeof(mHostCallbackInfo));
+		break;
+#endif
+#if !CA_NO_AU_UI_FEATURES
+	case kAudioUnitProperty_IconLocation:
+		{
+			CFURLRef iconLocation = CopyIconLocation();
+			if (iconLocation) {
+				*(CFURLRef*)outData = iconLocation;
+			} else
+				result = kAudioUnitErr_InvalidProperty;
+		}
+		break;
+
+	case kAudioUnitProperty_ContextName:
+		*(CFStringRef *)outData = mContextName;
+		if (mContextName) {
+			CFRetain(mContextName);
+			// retain CFString (if exists) since client will be responsible for its release
+			result = noErr;
+		} else {
+			result = kAudioUnitErr_InvalidPropertyValue;
+		}
+		break;
+		
+	case kAudioUnitProperty_ParameterClumpName:
+		{
+			AudioUnitParameterNameInfo * ioClumpInfo = (AudioUnitParameterNameInfo*) outData;
+			if (ioClumpInfo->inID == kAudioUnitClumpID_System)	// this ID value is reserved
+				result = kAudioUnitErr_InvalidPropertyValue;
+			else 
+			{
+				result = CopyClumpName(inScope, ioClumpInfo->inID, ioClumpInfo->inDesiredLength, &ioClumpInfo->outName);
+					
+					// this is provided for compatbility with existing implementations that don't know
+					// about this new mechanism
+				if (result == kAudioUnitErr_InvalidProperty)
+					result = GetProperty (inID, inScope, inElement, outData);
+			}	
+		}
+		break;
+
+#endif  // !CA_NO_AU_UI_FEATURES
+
+	case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime
+		*(Float64*)outData = mCurrentRenderTime.mSampleTime;
+		break;
+
+    case kAudioUnitProperty_NickName:
+        // Ownership follows Core Foundation's 'Copy Rule'
+        if (mNickName) CFRetain(mNickName);
+        *(CFStringRef*)outData = mNickName;
+        break;
+            
+	default:
+		result = GetProperty(inID, inScope, inElement, outData);
+		break;
+	}
+	return result;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::DispatchSetProperty(	AudioUnitPropertyID 			inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement,
+													const void *					inData,
+													UInt32 							inDataSize)
+{
+	OSStatus result = noErr;
+
+	switch (inID) {
+	case kAudioUnitProperty_MakeConnection:
+		ca_require(inDataSize >= sizeof(AudioUnitConnection), InvalidPropertyValue);
+		{
+			AudioUnitConnection &connection = *(AudioUnitConnection *)inData;
+			result = SetConnection(connection);
+		}
+		break;
+
+		
+	case kAudioUnitProperty_SetRenderCallback:
+		{
+			ca_require(inDataSize >= sizeof(AURenderCallbackStruct), InvalidPropertyValue);
+			ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
+			AURenderCallbackStruct &callback = *(AURenderCallbackStruct*)inData;
+			result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement, callback.inputProc, callback.inputProcRefCon);
+		}
+		break;
+
+	case kAudioUnitProperty_ElementCount:
+		ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+		ca_require(BusCountWritable(inScope), NotWritable);
+		result = SetBusCount(inScope, *(UInt32*)inData);
+		if (result == noErr) {
+			PropertyChanged(inID, inScope, inElement);
+		}
+		break;
+	
+	case kAudioUnitProperty_MaximumFramesPerSlice:
+		ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+		result = CanSetMaxFrames();
+		if (result) return result;
+		SetMaxFramesPerSlice(*(UInt32 *)inData);
+		break;
+
+	case kAudioUnitProperty_StreamFormat:
+		{
+			if (inDataSize < 36) goto InvalidPropertyValue;
+			ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+			CAStreamBasicDescription newDesc;
+				// now we're going to be ultra conservative! because of discrepancies between
+				// sizes of this struct based on aligment padding inconsistencies
+			memset (&newDesc, 0, sizeof(newDesc));
+			memcpy (&newDesc, inData, 36);
+
+			ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+
+			const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+			
+			if ( !curDesc.IsEqual(newDesc, false) ) {
+				ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+				result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+			}
+		}
+		break;
+	
+	case kAudioUnitProperty_SampleRate:
+		{
+			ca_require(inDataSize == sizeof(Float64), InvalidPropertyValue);
+			ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+			const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+			CAStreamBasicDescription newDesc = curDesc;
+			newDesc.mSampleRate = *(Float64 *)inData;
+			
+			ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+			
+			if ( !curDesc.IsEqual(newDesc, false) ) {
+				ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+				result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+			}
+		}
+		break;
+
+	case kAudioUnitProperty_AudioChannelLayout:
+		{
+			const AudioChannelLayout *layout = static_cast<const AudioChannelLayout *>(inData);
+			size_t headerSize = sizeof(AudioChannelLayout) - sizeof(AudioChannelDescription);
+			
+			ca_require(inDataSize >= headerSize + layout->mNumberChannelDescriptions * sizeof(AudioChannelDescription), InvalidPropertyValue);
+			result = SetAudioChannelLayout(inScope, inElement, layout);
+			if (result == noErr)
+				PropertyChanged(inID, inScope, inElement);
+			break;
+		}
+	
+	case kAudioUnitProperty_ClassInfo:
+		ca_require(inDataSize == sizeof(CFPropertyListRef *), InvalidPropertyValue);
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		result = RestoreState(*(CFPropertyListRef *)inData);
+		break;
+
+	case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+	case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+		{
+			ca_require(inDataSize == sizeof(AUPreset), InvalidPropertyValue);
+			ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+			AUPreset & newPreset = *(AUPreset *)inData;
+			
+			if (newPreset.presetNumber >= 0)
+			{
+				result = NewFactoryPresetSet(newPreset);
+				// NewFactoryPresetSet SHOULD call SetAFactoryPreset if the preset is valid
+				// from its own list of preset number->name
+				if (!result)
+					PropertyChanged(inID, inScope, inElement);
+			}
+			else if (newPreset.presetName)
+			{
+				result = NewCustomPresetSet(newPreset);
+                if (!result)
+                    PropertyChanged(inID, inScope, inElement);
+			}
+			else
+				result = kAudioUnitErr_InvalidPropertyValue;
+		}
+		break;
+	
+	case kAudioUnitProperty_ElementName:
+		{
+			ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+			ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+			AUElement * element = GetScope(inScope).GetElement (inElement);
+			element->SetName (*(CFStringRef *)inData);
+			PropertyChanged(inID, inScope, inElement);
+		}
+		break;
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+	case kAudioUnitProperty_ShouldAllocateBuffer:
+		{
+			ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
+			ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+			ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+			ca_require(!IsInitialized(), Initialized);
+
+			AUIOElement * element = GetIOElement(inScope, inElement);
+			element->SetWillAllocateBuffer(*(UInt32 *)inData != 0);
+		}
+		break;
+#endif
+
+#if !CA_NO_AU_HOST_CALLBACKS
+	case kAudioUnitProperty_HostCallbacks:
+	{
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		UInt32 availSize = std::min(inDataSize, (UInt32)sizeof(HostCallbackInfo));
+		bool hasChanged = !memcmp (&mHostCallbackInfo, inData, availSize);
+		memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+		memcpy (&mHostCallbackInfo, inData, availSize);
+		if (hasChanged)
+			PropertyChanged(inID, inScope, inElement);
+		break;
+	}
+#endif
+#if !CA_NO_AU_UI_FEATURES
+	case kAudioUnitProperty_SetExternalBuffer:
+		ca_require(inDataSize >= sizeof(AudioUnitExternalBuffer), InvalidPropertyValue);
+		ca_require(IsInitialized(), Uninitialized);
+		{
+			AudioUnitExternalBuffer &buf = *(AudioUnitExternalBuffer*)inData;
+			if (intptr_t(buf.buffer) & 0x0F) result = kAudio_ParamError;
+			else if (inScope == kAudioUnitScope_Input) {
+				AUInputElement *input = GetInput(inElement);
+				input->UseExternalBuffer(buf);
+			} else {
+				AUOutputElement *output = GetOutput(inElement);
+				output->UseExternalBuffer(buf);
+			}
+		}
+		break;
+
+	case kAudioUnitProperty_ContextName:
+		{
+			ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+			ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+			CFStringRef inStr = *(CFStringRef *)inData;
+			if (mContextName) CFRelease(mContextName);
+			if (inStr) CFRetain(inStr);
+			mContextName = inStr;
+			PropertyChanged(inID, inScope, inElement);
+		}
+		break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+	
+    case kAudioUnitProperty_NickName:
+    {
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+        ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+        CFStringRef inStr = *(CFStringRef *)inData;
+        if (mNickName) CFRelease(mNickName);
+        if (inStr) CFRetain(inStr);
+        mNickName = inStr;
+        PropertyChanged(inID, inScope, inElement);
+        break;
+    }
+            
+	default:
+		result = SetProperty(inID, inScope, inElement, inData, inDataSize);
+		if (result == noErr)
+			PropertyChanged(inID, inScope, inElement);
+		
+		break;
+	}
+	return result;
+NotWritable:
+	return kAudioUnitErr_PropertyNotWritable;
+InvalidFormat:
+	return kAudioUnitErr_FormatNotSupported;
+#if !CA_NO_AU_UI_FEATURES
+Uninitialized:
+	return kAudioUnitErr_Uninitialized;
+#endif
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || CA_USE_AUDIO_PLUGIN_ONLY
+Initialized:
+	return kAudioUnitErr_Initialized;
+#endif
+InvalidScope:
+	return kAudioUnitErr_InvalidScope;
+InvalidProperty:
+	return kAudioUnitErr_InvalidProperty;
+InvalidPropertyValue:
+	return kAudioUnitErr_InvalidPropertyValue;
+InvalidElement:
+	return kAudioUnitErr_InvalidElement;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::DispatchRemovePropertyValue (AudioUnitPropertyID		inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement)
+{
+	OSStatus result = noErr;
+	switch (inID)
+	{
+	case kAudioUnitProperty_AudioChannelLayout:
+	{
+		result = RemoveAudioChannelLayout(inScope, inElement);
+		if (result == noErr)
+			PropertyChanged(inID, inScope, inElement);
+		break;
+	}
+	
+#if !CA_NO_AU_HOST_CALLBACKS
+	case kAudioUnitProperty_HostCallbacks:
+	{
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		bool hasValue = false;
+		void* ptr = &mHostCallbackInfo;
+		for (unsigned int i = 0; i <  sizeof (HostCallbackInfo); ++i) {
+			if (static_cast<char*>(ptr)[i]) {
+				hasValue = true;
+				break;
+			}
+		}
+		if (hasValue) {
+			memset (&mHostCallbackInfo, 0, sizeof (HostCallbackInfo));
+			PropertyChanged(inID, inScope, inElement);
+		}
+		break;
+	}
+#endif
+#if !CA_NO_AU_UI_FEATURES
+	case kAudioUnitProperty_ContextName:
+		if (mContextName) CFRelease(mContextName);
+		mContextName = NULL;
+		result = noErr;
+		break;
+	
+#endif // !CA_NO_AU_UI_FEATURES
+
+    case kAudioUnitProperty_NickName:
+    {
+        if(inScope == kAudioUnitScope_Global) {
+            if (mNickName) CFRelease(mNickName);
+            mNickName = NULL;
+            PropertyChanged(inID, inScope, inElement);
+        } else {
+            result = kAudioUnitErr_InvalidScope;
+        }
+        break;
+    }
+
+	default:
+		result = RemovePropertyValue (inID, inScope, inElement);		
+		break;
+	}
+		
+	return result;
+#if !CA_NO_AU_UI_FEATURES || !CA_NO_AU_HOST_CALLBACKS
+InvalidScope:
+	return kAudioUnitErr_InvalidScope;
+#endif
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::GetPropertyInfo(		AudioUnitPropertyID				inID,
+													AudioUnitScope					inScope,
+													AudioUnitElement				inElement,
+													UInt32 &						outDataSize,
+													Boolean &						outWritable)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::GetProperty(			AudioUnitPropertyID 			inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement			 	inElement,
+													void *							outData)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::SetProperty(			AudioUnitPropertyID 			inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement,
+													const void *					inData,
+													UInt32 							inDataSize)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::RemovePropertyValue (	AudioUnitPropertyID		 		inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement)
+{
+	return kAudioUnitErr_InvalidPropertyValue;
+}
+												
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::AddPropertyListener(	AudioUnitPropertyID				inID,
+													AudioUnitPropertyListenerProc	inProc,
+													void *							inProcRefCon)
+{
+	PropertyListener pl;
+	
+	pl.propertyID = inID;
+	pl.listenerProc = inProc;
+	pl.listenerRefCon = inProcRefCon;
+	
+	if (mPropertyListeners.empty())
+		mPropertyListeners.reserve(32);
+	mPropertyListeners.push_back(pl);
+
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::RemovePropertyListener(		AudioUnitPropertyID				inID,
+														AudioUnitPropertyListenerProc	inProc,
+														void *							inProcRefCon,
+														bool							refConSpecified)
+{
+	// iterate in reverse so that it's safe to erase in the middle of the vector
+	for (int i = (int)mPropertyListeners.size(); --i >=0; ) {
+		PropertyListeners::iterator it = mPropertyListeners.begin() + i;
+		if ((*it).propertyID == inID && (*it).listenerProc == inProc && (!refConSpecified || (*it).listenerRefCon == inProcRefCon))
+			mPropertyListeners.erase(it);
+	}
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::PropertyChanged(			AudioUnitPropertyID				inID,
+														AudioUnitScope					inScope, 
+														AudioUnitElement				inElement)
+{
+	for (PropertyListeners::iterator it = mPropertyListeners.begin(); it != mPropertyListeners.end(); ++it)
+		if ((*it).propertyID == inID)
+			((*it).listenerProc)((*it).listenerRefCon, mComponentInstance, inID, inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::SetRenderNotification(	AURenderCallback		 		inProc,
+													void *							inRefCon)
+{
+	if (inProc == NULL)
+		return kAudio_ParamError;
+
+	mRenderCallbacksTouched = true;
+	mRenderCallbacks.deferred_add(RenderCallback(inProc, inRefCon));
+			// this will do nothing if it's already in the list
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::RemoveRenderNotification(	AURenderCallback			inProc,
+														void *						inRefCon)
+{
+	mRenderCallbacks.deferred_remove(RenderCallback(inProc, inRefCon));
+	return noErr;	// error?
+}
+
+//_____________________________________________________________________________
+//
+OSStatus 	AUBase::GetParameter(			AudioUnitParameterID			inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement,
+													AudioUnitParameterValue &		outValue)
+{
+	AUElement *elem = SafeGetElement(inScope, inElement);
+	outValue = elem->GetParameter(inID);
+	return noErr;
+}
+
+											
+//_____________________________________________________________________________
+//
+OSStatus 	AUBase::SetParameter(			AudioUnitParameterID			inID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement,
+													AudioUnitParameterValue			inValue,
+													UInt32							inBufferOffsetInFrames)
+{
+	AUElement *elem = SafeGetElement(inScope, inElement);
+	elem->SetParameter(inID, inValue);
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus 	AUBase::ScheduleParameter (	const AudioUnitParameterEvent 		*inParameterEvent,
+													UInt32							inNumEvents)
+{
+	bool canScheduleParameters = CanScheduleParameters();
+		
+	for (UInt32 i = 0; i < inNumEvents; ++i) 
+	{
+		if (inParameterEvent[i].eventType == kParameterEvent_Immediate)
+		{
+			SetParameter (inParameterEvent[i].parameter,
+							inParameterEvent[i].scope, 
+							inParameterEvent[i].element,
+							inParameterEvent[i].eventValues.immediate.value, 
+							inParameterEvent[i].eventValues.immediate.bufferOffset);
+		}
+		if (canScheduleParameters) {
+			mParamList.push_back (inParameterEvent[i]);
+		}
+	}
+	
+	return noErr;
+}
+
+// ____________________________________________________________________________
+//
+static bool SortParameterEventList(const AudioUnitParameterEvent &ev1, const AudioUnitParameterEvent &ev2 )
+{
+	int offset1 = ev1.eventType == kParameterEvent_Immediate ?  ev1.eventValues.immediate.bufferOffset : ev1.eventValues.ramp.startBufferOffset;
+	int offset2 = ev2.eventType == kParameterEvent_Immediate ?  ev2.eventValues.immediate.bufferOffset : ev2.eventValues.ramp.startBufferOffset;
+
+	if(offset1 < offset2) return true;
+	return false;
+}
+
+
+// ____________________________________________________________________________
+//
+OSStatus 	AUBase::ProcessForScheduledParams(	ParameterEventList		&inParamList,
+														UInt32					inFramesToProcess,
+														void					*inUserData )
+{
+	OSStatus result = noErr;
+	
+	int totalFramesToProcess = inFramesToProcess;
+	
+	int framesRemaining = totalFramesToProcess;
+
+	unsigned int currentStartFrame = 0;	// start of the whole buffer
+
+
+
+	// sort the ParameterEventList by startBufferOffset
+	std::sort(inParamList.begin(), inParamList.end(), SortParameterEventList);
+
+	ParameterEventList::iterator iter = inParamList.begin();
+	
+	
+	while(framesRemaining > 0 )
+	{
+		// first of all, go through the ramped automation events and find out where the next
+		// division of our whole buffer will be
+		
+		int currentEndFrame = totalFramesToProcess;	// start out assuming we'll process all the way to
+													// the end of the buffer
+		
+		iter = inParamList.begin();
+		
+		// find the next break point
+		while(iter != inParamList.end() )
+		{
+			AudioUnitParameterEvent &event = *iter;
+			
+			int offset = event.eventType == kParameterEvent_Immediate ?  event.eventValues.immediate.bufferOffset : event.eventValues.ramp.startBufferOffset;
+
+			if(offset > (int)currentStartFrame && offset < currentEndFrame )
+			{
+				currentEndFrame = offset;
+				break;
+			}
+
+			// consider ramp end to be a possible choice (there may be gaps in the supplied ramp events)
+			if(event.eventType == kParameterEvent_Ramped )
+			{
+				offset = event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames;
+	
+				if(offset > (int)currentStartFrame && offset < currentEndFrame )
+				{
+					currentEndFrame = offset;
+				}
+			}
+
+			iter++;
+		}
+	
+		int framesThisTime = currentEndFrame - currentStartFrame;
+
+		// next, setup the parameter maps to be current for the ramp parameters active during 
+		// this time segment...
+		
+		for(ParameterEventList::iterator iter2 = inParamList.begin(); iter2 != inParamList.end(); iter2++ )
+		{
+			AudioUnitParameterEvent &event = *iter2;
+			
+			bool eventFallsInSlice;
+			
+			
+			if(event.eventType == kParameterEvent_Ramped)
+				eventFallsInSlice = event.eventValues.ramp.startBufferOffset < currentEndFrame 
+					&& event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames > currentStartFrame;
+			else /* kParameterEvent_Immediate */
+				// actually, for the same parameter, there may be future immediate events which override this one,
+				// but it's OK since the event list is sorted in time order, we're guaranteed to end up with the current one
+				eventFallsInSlice = event.eventValues.immediate.bufferOffset <= currentStartFrame;
+				
+			if(eventFallsInSlice)
+			{
+				AUElement *element = GetElement(event.scope, event.element );
+				
+				if(element) element->SetScheduledEvent(	event.parameter,
+														event,
+														currentStartFrame,
+														currentEndFrame - currentStartFrame );
+			}
+		}
+
+
+
+		// Finally, actually do the processing for this slice.....
+		
+		result = ProcessScheduledSlice(	inUserData,
+										currentStartFrame,
+										framesThisTime,
+										inFramesToProcess );
+								
+		if(result != noErr) break;
+		
+		framesRemaining -= framesThisTime;
+		currentStartFrame = currentEndFrame;	// now start from where we left off last time
+	}
+	
+	return result;
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::SetWantsRenderThreadID (bool inFlag)
+{
+	if (inFlag == mWantsRenderThreadID)	
+		return;
+	
+	mWantsRenderThreadID = inFlag;
+	if (!mWantsRenderThreadID)
+		mRenderThreadID = NULL;
+}
+
+//_____________________________________________________________________________
+//
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::DoRender(		AudioUnitRenderActionFlags &	ioActionFlags,
+											const AudioTimeStamp &			inTimeStamp,
+											UInt32							inBusNumber,
+											UInt32							inFramesToProcess,
+											AudioBufferList &				ioData)
+{
+	OSStatus theError;
+	RenderCallbackList::iterator rcit;
+	
+	AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (uintptr_t)this, inBusNumber, inFramesToProcess, (uintptr_t)ioData.mBuffers[0].mData);
+	DISABLE_DENORMALS
+	
+	try {
+		ca_require(IsInitialized(), Uninitialized);
+		ca_require(mAudioUnitAPIVersion >= 2, ParamErr);
+		if (inFramesToProcess > mMaxFramesPerSlice) {
+			static time_t lastTimeMessagePrinted = 0;
+			time_t now = time(NULL);
+			if (now != lastTimeMessagePrinted) {
+				lastTimeMessagePrinted = now;
+				syslog(LOG_ERR, "kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=%u, mMaxFramesPerSlice=%u", (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice);
+				DebugMessageN4("%s:%d inFramesToProcess=%u, mMaxFramesPerSlice=%u; TooManyFrames", __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice);
+			}
+			goto TooManyFrames;
+		}
+		ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+		AUOutputElement *output = GetOutput(inBusNumber);	// will throw if non-existant
+		if (output->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) {
+			DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+				__FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams());
+			goto ParamErr;
+		}
+
+		unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame;
+		for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
+			AudioBuffer &buf = ioData.mBuffers[ibuf];
+			if (buf.mData != NULL) {
+				// only care about the size if the buffer is non-null
+				if (buf.mDataByteSize < expectedBufferByteSize) {
+					// if the buffer is too small, we cannot render safely. kAudio_ParamError.
+					DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+						__FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize);
+					goto ParamErr;
+				}
+				// Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+				// We will generally set the buffer size at the end of rendering, before we return.
+				// However we should ensure that no one, DURING rendering, READS a
+				// potentially incorrect size. This can lead to doing too much work, or
+				// reading past the end of an input buffer into unmapped memory.
+				buf.mDataByteSize = expectedBufferByteSize;
+			}
+		}
+		
+		if (WantsRenderThreadID())
+		{
+			#if TARGET_OS_MAC
+				mRenderThreadID = pthread_self();
+			#elif TARGET_OS_WIN32
+				mRenderThreadID = GetCurrentThreadId();
+			#endif
+		}
+		
+		AudioUnitRenderActionFlags flags;
+		if (mRenderCallbacksTouched) {
+			mRenderCallbacks.update();
+			flags = ioActionFlags | kAudioUnitRenderAction_PreRender;
+			for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
+				RenderCallback &rc = *rcit;
+				AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0);
+				(*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon, 
+								&flags,
+								&inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+				AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0);
+			}
+		}
+		
+		theError = DoRenderBus(ioActionFlags, inTimeStamp, inBusNumber, output, inFramesToProcess, ioData);
+		
+		if (mRenderCallbacksTouched) {
+			flags = ioActionFlags | kAudioUnitRenderAction_PostRender;
+			
+			if (SetRenderError (theError)) {
+				flags |= kAudioUnitRenderAction_PostRenderError;		
+			}
+			
+			for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
+				RenderCallback &rc = *rcit;
+				AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0);
+				(*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon, 
+								&flags,
+								&inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+				AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0);
+			}
+		}
+
+		// The vector's being emptied
+		// because these events should only apply to this Render cycle, so anything
+		// left over is from a preceding cycle and should be dumped.  New scheduled
+		// parameters must be scheduled from the next pre-render callback.
+		if (!mParamList.empty())
+			mParamList.clear();
+
+	}
+	catch (OSStatus err) {
+		theError = err;
+		goto errexit;
+	}
+	catch (...) {
+		theError = -1;
+		goto errexit;
+	}
+done:	
+	RESTORE_DENORMALS
+	AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData));
+	
+	return theError;
+	
+Uninitialized:	theError = kAudioUnitErr_Uninitialized;				goto errexit;
+ParamErr:		theError = kAudio_ParamError;						goto errexit;
+TooManyFrames:	theError = kAudioUnitErr_TooManyFramesToProcess;	goto errexit;
+errexit:
+	DebugMessageN2 ("  from %s, render err: %d", GetLoggingString(), (int)theError);
+	SetRenderError(theError);
+	goto done;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus	AUBase::DoProcess (	AudioUnitRenderActionFlags  &		ioActionFlags,
+								const AudioTimeStamp &				inTimeStamp,
+								UInt32								inFramesToProcess,
+								AudioBufferList &					ioData)
+{
+	OSStatus theError;
+	AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (intptr_t)this, -1, inFramesToProcess, 0);
+	DISABLE_DENORMALS
+
+	try {		
+	
+		if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) {
+			ca_require(IsInitialized(), Uninitialized);
+			ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
+			ca_require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+			AUInputElement *input = GetInput(0);	// will throw if non-existant
+			if (input->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) {
+				DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+					__FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams());
+				goto ParamErr;
+			}
+
+			unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame;
+			for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
+				AudioBuffer &buf = ioData.mBuffers[ibuf];
+				if (buf.mData != NULL) {
+					// only care about the size if the buffer is non-null
+					if (buf.mDataByteSize < expectedBufferByteSize) {
+						// if the buffer is too small, we cannot render safely. kAudio_ParamError.
+						DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+							__FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize);
+						goto ParamErr;
+					}
+					// Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+					// We will generally set the buffer size at the end of rendering, before we return.
+					// However we should ensure that no one, DURING rendering, READS a
+					// potentially incorrect size. This can lead to doing too much work, or
+					// reading past the end of an input buffer into unmapped memory.
+					buf.mDataByteSize = expectedBufferByteSize;
+				}
+			}
+		}
+		
+		if (WantsRenderThreadID())
+		{
+			#if TARGET_OS_MAC
+				mRenderThreadID = pthread_self();
+			#elif TARGET_OS_WIN32
+				mRenderThreadID = GetCurrentThreadId();
+			#endif
+		}
+		
+		if (NeedsToRender (inTimeStamp)) {
+			theError = ProcessBufferLists (ioActionFlags, ioData, ioData, inFramesToProcess);
+		} else
+			theError = noErr;
+			
+	}
+	catch (OSStatus err) {
+		theError = err;
+		goto errexit;
+	}
+	catch (...) {
+		theError = -1;
+		goto errexit;
+	}
+done:	
+	RESTORE_DENORMALS
+	AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData));
+	
+	return theError;
+	
+Uninitialized:	theError = kAudioUnitErr_Uninitialized;				goto errexit;
+ParamErr:		theError = kAudio_ParamError;						goto errexit;
+TooManyFrames:	theError = kAudioUnitErr_TooManyFramesToProcess;	goto errexit;
+errexit:
+	DebugMessageN2 ("  from %s, process err: %d", GetLoggingString(), (int)theError);
+	SetRenderError(theError);
+	goto done;
+}
+
+OSStatus	AUBase::DoProcessMultiple (	AudioUnitRenderActionFlags  & ioActionFlags,
+							   const AudioTimeStamp &				inTimeStamp,
+							   UInt32								inFramesToProcess,
+							   UInt32								inNumberInputBufferLists,
+							   const AudioBufferList **				inInputBufferLists,
+							   UInt32								inNumberOutputBufferLists,
+							   AudioBufferList **					ioOutputBufferLists)
+{
+	OSStatus theError;
+	DISABLE_DENORMALS
+	
+	try {
+		
+		if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) {
+			ca_require(IsInitialized(), Uninitialized);
+			ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
+			ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+			
+			for (unsigned ibl = 0; ibl < inNumberInputBufferLists; ++ibl) {
+				if (inInputBufferLists[ibl] != NULL) {
+					AUInputElement *input = GetInput(ibl);	// will throw if non-existant
+					unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame;
+					
+					if (input->GetStreamFormat().NumberChannelStreams() != inInputBufferLists[ibl]->mNumberBuffers) {
+						DebugMessageN5("%s:%d inInputBufferLists[%u]->mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+									   __FILE__, __LINE__, ibl, (unsigned)inInputBufferLists[ibl]->mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams());
+						goto ParamErr;
+					}
+					
+					for (unsigned ibuf = 0; ibuf < inInputBufferLists[ibl]->mNumberBuffers; ++ibuf) {
+						const AudioBuffer &buf = inInputBufferLists[ibl]->mBuffers[ibuf];
+						if (buf.mData != NULL) {
+							if (buf.mDataByteSize < expectedBufferByteSize) {
+								// the buffer is too small
+								DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; inInputBufferLists[%u].mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+											   __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibl, ibuf, (unsigned)buf.mDataByteSize);
+								goto ParamErr;
+							}
+						} else {
+							// the buffer must exist
+							goto ParamErr;
+						}
+					}
+				} else {
+					// skip NULL input audio buffer list
+				}
+			}
+			
+			for (unsigned obl = 0; obl < inNumberOutputBufferLists; ++obl) {
+				if (ioOutputBufferLists[obl] != NULL) {
+					AUOutputElement *output = GetOutput(obl);	// will throw if non-existant
+					unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame;
+
+					if (output->GetStreamFormat().NumberChannelStreams() != ioOutputBufferLists[obl]->mNumberBuffers) {
+						DebugMessageN5("%s:%d ioOutputBufferLists[%u]->mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+									   __FILE__, __LINE__, obl, (unsigned)ioOutputBufferLists[obl]->mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams());
+						goto ParamErr;
+					}
+					
+					for (unsigned obuf = 0; obuf < ioOutputBufferLists[obl]->mNumberBuffers; ++obuf) {
+						AudioBuffer &buf = ioOutputBufferLists[obl]->mBuffers[obuf];
+						if (buf.mData != NULL) {
+							// only care about the size if the buffer is non-null
+							if (buf.mDataByteSize < expectedBufferByteSize) {
+								// if the buffer is too small, we cannot render safely. kAudio_ParamError.
+								DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioOutputBufferLists[%u]->mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+											   __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, obl, obuf, (unsigned)buf.mDataByteSize);
+								goto ParamErr;
+							}
+							// Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+							// We will generally set the buffer size at the end of rendering, before we return.
+							// However we should ensure that no one, DURING rendering, READS a
+							// potentially incorrect size. This can lead to doing too much work, or
+							// reading past the end of an input buffer into unmapped memory.
+							buf.mDataByteSize = expectedBufferByteSize;
+						}
+					}
+				} else {
+					// skip NULL output audio buffer list
+				}
+			}
+		}
+		
+		if (WantsRenderThreadID())
+		{
+#if TARGET_OS_MAC
+			mRenderThreadID = pthread_self();
+#elif TARGET_OS_WIN32
+			mRenderThreadID = GetCurrentThreadId();
+#endif
+		}
+		
+		if (NeedsToRender (inTimeStamp)) {
+			theError = ProcessMultipleBufferLists (ioActionFlags, inFramesToProcess, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+		} else
+			theError = noErr;
+	}
+	catch (OSStatus err) {
+		theError = err;
+		goto errexit;
+	}
+	catch (...) {
+		theError = -1;
+		goto errexit;
+	}
+done:	
+	RESTORE_DENORMALS
+	
+	return theError;
+	
+Uninitialized:	theError = kAudioUnitErr_Uninitialized;				goto errexit;
+ParamErr:		theError = kAudio_ParamError;						goto errexit;
+TooManyFrames:	theError = kAudioUnitErr_TooManyFramesToProcess;	goto errexit;
+errexit:
+	DebugMessageN2 ("  from %s, processmultiple err: %d", GetLoggingString(), (int)theError);
+	SetRenderError(theError);
+	goto done;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::SetInputCallback(		UInt32							inPropertyID,
+													AudioUnitElement 				inElement, 
+													AURenderCallback				inProc,
+													void *							inRefCon)
+{
+	AUInputElement *input = GetInput(inElement);	// may throw
+	
+	input->SetInputCallback(inProc, inRefCon);
+	PropertyChanged(inPropertyID, kAudioUnitScope_Input, inElement);
+	
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::SetConnection(			const AudioUnitConnection &		inConnection)
+{
+
+	OSStatus err;
+	AUInputElement *input = GetInput(inConnection.destInputNumber);	// may throw
+		
+	if (inConnection.sourceAudioUnit) {
+		// connecting, not disconnecting
+		CAStreamBasicDescription sourceDesc;
+		UInt32 size = sizeof(CAStreamBasicDescription);
+		ca_require_noerr(err = AudioUnitGetProperty(
+										inConnection.sourceAudioUnit,
+										kAudioUnitProperty_StreamFormat,
+										kAudioUnitScope_Output,
+										inConnection.sourceOutputNumber,
+										&sourceDesc,
+										&size), errexit);
+		ca_require_noerr(err = DispatchSetProperty (kAudioUnitProperty_StreamFormat, 
+								kAudioUnitScope_Input, inConnection.destInputNumber, 
+								&sourceDesc, sizeof(CAStreamBasicDescription)), errexit);
+	}
+	input->SetConnection(inConnection);
+		
+	PropertyChanged(kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inConnection.destInputNumber);
+	return noErr;
+
+errexit:
+	return err;
+}
+ 
+//_____________________________________________________________________________
+//
+UInt32				AUBase::SupportedNumChannels (	const AUChannelInfo** 			outInfo)
+{
+	return 0;
+}
+
+//_____________________________________________________________________________
+//
+bool				AUBase::ValidFormat(			AudioUnitScope					inScope,
+													AudioUnitElement				inElement,
+													const CAStreamBasicDescription &		inNewFormat)
+{
+	return FormatIsCanonical(inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+bool				AUBase::IsStreamFormatWritable(	AudioUnitScope					scope,
+													AudioUnitElement				element)
+{
+	switch (scope) {
+	case kAudioUnitScope_Input:
+		{
+			AUInputElement *input = GetInput(element);
+			if (input->HasConnection()) return false;	// can't write format when input comes from connection
+		}
+		// ... fall ...
+	case kAudioUnitScope_Output:
+		return StreamFormatWritable(scope, element);
+
+//#warning "aliasing of global scope format should be pushed to subclasses"
+	case kAudioUnitScope_Global:
+		return StreamFormatWritable(kAudioUnitScope_Output, 0);
+	}
+	return false;
+}
+
+//_____________________________________________________________________________
+//
+const CAStreamBasicDescription &
+					AUBase::GetStreamFormat(		AudioUnitScope					inScope,
+													AudioUnitElement				inElement)
+{
+//#warning "aliasing of global scope format should be pushed to subclasses"
+	AUIOElement *element;
+	
+	switch (inScope) {
+	case kAudioUnitScope_Input:
+		element = Inputs().GetIOElement(inElement);
+		break;
+	case kAudioUnitScope_Output:
+		element = Outputs().GetIOElement(inElement);
+		break;
+	case kAudioUnitScope_Global:	// global stream description is an alias for that of output 0
+		element = Outputs().GetIOElement(0);
+		break;
+	default:
+		COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+	}
+	return element->GetStreamFormat();
+}
+
+OSStatus			AUBase::SetBusCount(	AudioUnitScope					inScope,
+											UInt32 							inCount)
+{
+	if (IsInitialized()) 
+		return kAudioUnitErr_Initialized;
+		
+	GetScope(inScope).SetNumberOfElements(inCount);
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::ChangeStreamFormat(		AudioUnitScope					inScope,
+													AudioUnitElement				inElement,
+													const CAStreamBasicDescription & inPrevFormat,
+													const CAStreamBasicDescription &	inNewFormat)
+{
+//#warning "aliasing of global scope format should be pushed to subclasses"
+	AUIOElement *element;
+	
+	switch (inScope) {
+	case kAudioUnitScope_Input:
+		element = Inputs().GetIOElement(inElement);
+		break;
+	case kAudioUnitScope_Output:
+		element = Outputs().GetIOElement(inElement);
+		break;
+	case kAudioUnitScope_Global:
+		element = Outputs().GetIOElement(0);
+		break;
+	default:
+		COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+	}
+	element->SetStreamFormat(inNewFormat);
+	PropertyChanged(kAudioUnitProperty_StreamFormat, inScope, inElement);
+	return noErr;
+}
+
+UInt32		AUBase::GetChannelLayoutTags(	AudioUnitScope				inScope,
+											AudioUnitElement 			inElement,
+											AudioChannelLayoutTag *		outLayoutTags)
+{
+	return GetIOElement(inScope, inElement)->GetChannelLayoutTags(outLayoutTags);
+}
+
+UInt32		AUBase::GetAudioChannelLayout(	AudioUnitScope				scope,
+											AudioUnitElement 			element,
+											AudioChannelLayout *		outLayoutPtr,
+											Boolean &					outWritable)
+{
+	AUIOElement * el = GetIOElement(scope, element);
+	return el->GetAudioChannelLayout(outLayoutPtr, outWritable);
+}
+
+OSStatus	AUBase::RemoveAudioChannelLayout(			AudioUnitScope				inScope,
+														AudioUnitElement			inElement)
+{
+	OSStatus result = noErr;
+	AUIOElement * el = GetIOElement(inScope, inElement);
+	Boolean writable;
+	if (el->GetAudioChannelLayout(NULL, writable)) {
+		result = el->RemoveAudioChannelLayout();
+	}
+	return result;
+}
+
+OSStatus 	AUBase::SetAudioChannelLayout(				AudioUnitScope 				inScope, 
+														AudioUnitElement 			inElement,
+														const AudioChannelLayout *	inLayout)
+{
+	AUIOElement* ioEl = GetIOElement (inScope, inElement);
+
+	// the num channels of the layout HAS TO MATCH the current channels of the Element's stream format
+	UInt32 currentChannels = ioEl->GetStreamFormat().NumberChannels();
+	UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+	if (currentChannels != numChannelsInLayout)
+		return kAudioUnitErr_InvalidPropertyValue;
+
+	UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, NULL);
+	if (numLayouts == 0)
+		return kAudioUnitErr_InvalidProperty;
+	AudioChannelLayoutTag *tags = (AudioChannelLayoutTag *)CA_malloc (numLayouts * sizeof (AudioChannelLayoutTag));
+	GetChannelLayoutTags (inScope, inElement, tags);
+	bool foundTag = false;
+	for (unsigned int i = 0; i < numLayouts; ++i) {
+		if (tags[i] == inLayout->mChannelLayoutTag || tags[i] == kAudioChannelLayoutTag_UseChannelDescriptions) {
+			foundTag = true;
+			break;
+		}
+	}
+	free(tags);
+	
+	if (foundTag == false)
+		return kAudioUnitErr_InvalidPropertyValue;
+
+	return ioEl->SetAudioChannelLayout(*inLayout);
+}
+
+static void AddNumToDictionary (CFMutableDictionaryRef dict, CFStringRef key, SInt32 value)
+{
+	CFNumberRef num = CFNumberCreate (NULL, kCFNumberSInt32Type, &value);
+	CFDictionarySetValue (dict, key, num);
+	CFRelease (num);
+}
+
+#define kCurrentSavedStateVersion 0
+
+OSStatus			AUBase::SaveState(		CFPropertyListRef * outData)
+{
+	AudioComponentDescription desc = GetComponentDescription();
+
+	CFMutableDictionaryRef dict = CFDictionaryCreateMutable	(NULL, 0, 
+								&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+// first step -> save the version to the data ref
+	SInt32 value = kCurrentSavedStateVersion;
+	AddNumToDictionary (dict, kVersionString, value);
+
+// second step -> save the component type, subtype, manu to the data ref
+	value = desc.componentType;
+	AddNumToDictionary (dict, kTypeString, value);
+
+	value = desc.componentSubType;
+	AddNumToDictionary (dict, kSubtypeString, value);
+	
+	value = desc.componentManufacturer;
+	AddNumToDictionary (dict, kManufacturerString, value);
+	
+// fourth step -> save the state of all parameters on all scopes and elements
+	CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
+	for (AudioUnitScope iscope = 0; iscope < 3; ++iscope) {
+		AUScope &scope = GetScope(iscope);
+		scope.SaveState (data);
+	}
+    
+    SaveExtendedScopes(data);
+
+// save all this in the data section of the dictionary
+	CFDictionarySetValue(dict, kDataString, data);
+	CFRelease (data);
+	
+//OK - now we're going to do some properties 	
+//save the preset name...
+	CFDictionarySetValue (dict, kNameString, mCurrentPreset.presetName);
+
+// Does the unit support the RenderQuality property - if so, save it...
+	value = 0;
+	OSStatus result = DispatchGetProperty (kAudioUnitProperty_RenderQuality,
+								kAudioUnitScope_Global,
+								0,
+								&value);
+	
+	if (result == noErr) {
+		AddNumToDictionary (dict, kRenderQualityString, value);
+	}
+	
+// Does the unit support the CPULoad Quality property - if so, save it...
+	Float32 cpuLoad;
+	result = DispatchGetProperty (6/*kAudioUnitProperty_CPULoad*/,
+								kAudioUnitScope_Global,
+								0,
+								&cpuLoad);
+	
+	if (result == noErr) {
+		CFNumberRef num = CFNumberCreate (NULL, kCFNumberFloatType, &cpuLoad);
+		CFDictionarySetValue (dict, kCPULoadString, num);
+		CFRelease (num);
+	}
+
+// Do we have any element names for any of our scopes?	
+	// first check to see if we have any names...
+	bool foundName = false;
+	for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+		foundName = GetScope (i).HasElementWithName();
+		if (foundName) 
+			break;
+	}
+		// OK - we found a name away we go...
+	if (foundName) {
+		CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable	(NULL, 0, 
+								&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+		for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+			GetScope (i).AddElementNamesToDict (nameDict);
+		}
+		
+		CFDictionarySetValue (dict, kElementNameString, nameDict);
+		CFRelease (nameDict);
+	}
+	
+// we're done!!!
+	*outData = dict;
+
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::RestoreState(	CFPropertyListRef	plist)
+{
+	if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) return kAudioUnitErr_InvalidPropertyValue;
+	
+	AudioComponentDescription desc = GetComponentDescription();
+	
+	CFDictionaryRef dict = static_cast<CFDictionaryRef>(plist);
+
+// zeroeth step - make sure the Part key is NOT present, as this method is used
+// to restore the GLOBAL state of the dictionary	
+	if (CFDictionaryContainsKey (dict, kPartString))
+		return kAudioUnitErr_InvalidPropertyValue;
+		
+// first step -> check the saved version in the data ref
+// at this point we're only dealing with version==0
+	CFNumberRef cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kVersionString));
+	if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+	SInt32 value;
+	CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+	if (value != kCurrentSavedStateVersion) return kAudioUnitErr_InvalidPropertyValue;
+
+// second step -> check that this data belongs to this kind of audio unit
+// by checking the component subtype and manuID
+// We're not checking the type, since there may be different versions (effect, format-converter, offline)
+// of essentially the same AU
+	cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kSubtypeString));
+	if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+	CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+	if (UInt32(value) != desc.componentSubType) return kAudioUnitErr_InvalidPropertyValue;
+
+	cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kManufacturerString));
+	if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+	CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+	if (UInt32(value) != desc.componentManufacturer) return kAudioUnitErr_InvalidPropertyValue;
+
+// fourth step -> restore the state of all of the parameters for each scope and element	
+	CFDataRef data = reinterpret_cast<CFDataRef>(CFDictionaryGetValue (dict, kDataString));
+	if (data != NULL) 
+	{
+		const UInt8 *p, *pend;
+		
+		p = CFDataGetBytePtr(data);
+		pend = p + CFDataGetLength(data);
+		
+		// we have a zero length data, which may just mean there were no parameters to save!
+		//	if (p >= pend) return noErr; 
+	
+		while (p < pend) {
+            UInt32 scopeIdx = CFSwapInt32BigToHost(*(UInt32 *)p);
+            p += sizeof(UInt32);
+            
+			AUScope &scope = GetScope(scopeIdx);
+            p = scope.RestoreState(p);
+        }
+	}
+
+//OK - now we're going to do some properties
+//restore the preset name...
+	CFStringRef name = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (dict, kNameString));
+	if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+	if (name)
+	{
+		mCurrentPreset.presetName = name;
+		mCurrentPreset.presetNumber = -1;
+	} 
+	else { // no name entry make the default one
+		mCurrentPreset.presetName = kUntitledString;
+		mCurrentPreset.presetNumber = -1;
+	}
+	
+	CFRetain (mCurrentPreset.presetName);
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+	PropertyChanged(kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0);
+#endif
+#endif
+	PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
+
+// Does the dict contain render quality information?		
+	if (CFDictionaryGetValueIfPresent (dict, kRenderQualityString, reinterpret_cast<const void**>(&cfnum))) 
+	{
+		CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+		DispatchSetProperty (kAudioUnitProperty_RenderQuality,
+								kAudioUnitScope_Global,
+								0,
+								&value,
+								sizeof(value));
+	}
+	
+// Does the unit support the CPULoad Quality property - if so, save it...
+	if (CFDictionaryGetValueIfPresent (dict, kCPULoadString, reinterpret_cast<const void**>(&cfnum))) 
+	{
+		Float32 floatValue;
+		CFNumberGetValue (cfnum, kCFNumberFloatType, &floatValue);
+		DispatchSetProperty (6/*kAudioUnitProperty_CPULoad*/,
+								kAudioUnitScope_Global,
+								0,
+								&floatValue,
+								sizeof(floatValue));
+	}
+
+// Do we have any element names for any of our scopes?
+	CFDictionaryRef nameDict;
+	if (CFDictionaryGetValueIfPresent (dict, kElementNameString, reinterpret_cast<const void**>(&nameDict))) 
+	{
+		char string[64];
+		for (int i = 0; i < kNumScopes; ++i) 
+		{
+			snprintf (string, sizeof(string), "%d", i);
+			CFStringRef key = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+			CFDictionaryRef elementDict;
+			if (CFDictionaryGetValueIfPresent (nameDict, key, reinterpret_cast<const void**>(&elementDict))) 
+			{
+				bool didAddElements = GetScope (i).RestoreElementNames (elementDict);
+				if (didAddElements)
+					PropertyChanged (kAudioUnitProperty_ElementCount, i, 0);
+			}
+			CFRelease (key);				
+		}
+	}
+	
+	return noErr;
+}
+
+OSStatus			AUBase::GetPresets (			CFArrayRef * 					outData) const
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+OSStatus			AUBase::NewFactoryPresetSet (const AUPreset & inNewFactoryPreset)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+OSStatus            AUBase::NewCustomPresetSet (const AUPreset & inNewCustomPreset)
+{
+    CFRelease (mCurrentPreset.presetName);
+    mCurrentPreset = inNewCustomPreset;
+    CFRetain (mCurrentPreset.presetName);
+    return noErr;
+}
+
+		// set the default preset for the unit -> the number of the preset MUST be >= 0
+		// and the name should be valid, or the preset WON'T take
+bool				AUBase::SetAFactoryPresetAsCurrent (const AUPreset & inPreset)
+{
+	if (inPreset.presetNumber < 0 || inPreset.presetName == NULL) return false;
+	CFRelease (mCurrentPreset.presetName);
+	mCurrentPreset = inPreset;
+	CFRetain (mCurrentPreset.presetName);
+	return true;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+int			AUBase::GetNumCustomUIComponents () 
+{
+	return 0;
+}
+
+void		AUBase::GetUIComponentDescs (ComponentDescription* inDescArray) {}
+#endif
+	
+bool		AUBase::HasIcon () 
+{
+#if !CA_NO_AU_UI_FEATURES
+	CFURLRef url = CopyIconLocation(); 
+	if (url) {
+		CFRelease (url);
+		return true;
+	}
+#endif
+	return false;
+}
+
+CFURLRef	AUBase::CopyIconLocation () 
+{
+	return NULL;
+}
+	
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::GetParameterList(		AudioUnitScope					inScope,
+													AudioUnitParameterID *			outParameterList,
+													UInt32 &						outNumParameters)
+{
+	AUScope &scope = GetScope(inScope);
+	AUElement *elementWithMostParameters = NULL;
+	UInt32 maxNumParams = 0;
+	
+	int nElems = scope.GetNumberOfElements();
+	for (int ielem = 0; ielem < nElems; ++ielem) {
+		AUElement *element = scope.GetElement(ielem);
+		UInt32 nParams = element->GetNumberOfParameters();
+		if (nParams > maxNumParams) {
+			maxNumParams = nParams;
+			elementWithMostParameters = element;
+		}
+	}
+	
+	if (outParameterList != NULL && elementWithMostParameters != NULL)
+		elementWithMostParameters->GetParameterList(outParameterList);
+	
+	outNumParameters = maxNumParams;
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::GetParameterInfo(		AudioUnitScope			inScope,
+													AudioUnitParameterID	inParameterID,
+													AudioUnitParameterInfo	&outParameterInfo )
+{
+	return kAudioUnitErr_InvalidParameter;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::GetParameterValueStrings(AudioUnitScope			inScope,
+													AudioUnitParameterID	inParameterID,
+													CFArrayRef *			outStrings)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::GetParameterHistoryInfo(	AudioUnitScope					inScope,
+														AudioUnitParameterID			inParameterID,
+														Float32 &						outUpdatesPerSecond,
+														Float32 &						outHistoryDurationInSeconds)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus			AUBase::CopyClumpName(			AudioUnitScope			inScope, 
+													UInt32					inClumpID, 
+													UInt32					inDesiredNameLength,
+													CFStringRef *			outClumpName)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+void				AUBase::SetNumberOfElements(	AudioUnitScope					inScope,
+													UInt32							numElements)
+{
+	if (inScope == kAudioUnitScope_Global && numElements != 1)
+		COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+
+	GetScope(inScope).SetNumberOfElements(numElements);
+}
+
+//_____________________________________________________________________________
+//
+AUElement *			AUBase::CreateElement(			AudioUnitScope					scope,
+													AudioUnitElement				element)
+{
+	switch (scope) {
+	case kAudioUnitScope_Global:
+		return new AUElement(this);
+	case kAudioUnitScope_Input:
+		return new AUInputElement(this);
+	case kAudioUnitScope_Output:
+		return new AUOutputElement(this);
+#if !CA_BASIC_AU_FEATURES
+	case kAudioUnitScope_Group:
+		return new AUElement(this);
+	case kAudioUnitScope_Part:
+		return new AUElement(this);
+#endif
+	}
+	COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+	
+	return NULL;	// get rid of compiler warning
+}
+
+//_____________________________________________________________________________
+//
+bool	AUBase::FormatIsCanonical(		const CAStreamBasicDescription &f)
+{
+	return (f.mFormatID == kAudioFormatLinearPCM
+		&&	f.mFramesPerPacket == 1
+		&&	f.mBytesPerPacket == f.mBytesPerFrame
+//		&&	f.mChannelsPerFrame >= 0	-- this is always true since it's unsigned
+		// so far, it's a valid PCM format
+#if CA_PREFER_FIXED_POINT
+		&&	(f.mFormatFlags & kLinearPCMFormatFlagIsFloat) == 0
+		&&	(((f.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift) == kAudioUnitSampleFractionBits)
+#else
+		&&	(f.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0
+#endif
+		&&	((f.mChannelsPerFrame == 1) || ((f.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0) == (mAudioUnitAPIVersion == 1))
+#if TARGET_RT_BIG_ENDIAN
+		&&	(f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) != 0
+#else
+		&&	(f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) == 0
+#endif
+		&&	f.mBitsPerChannel == 8 * sizeof(AudioUnitSampleType)
+		&&	f.mBytesPerFrame == f.NumberInterleavedChannels() * sizeof(AudioUnitSampleType)
+		);
+}
+
+//_____________________________________________________________________________
+//
+void	AUBase::MakeCanonicalFormat(	CAStreamBasicDescription &		f,
+										int								nChannels)
+{
+	f.SetAUCanonical(nChannels, mAudioUnitAPIVersion < 2);	// interleaved for v1, non for v2
+	f.mSampleRate = 0.0;
+}
+
+const Float64 AUBase::kNoLastRenderedSampleTime = -1.;
+
+#include "AUBaseHelper.h"
+
+char*	AUBase::GetLoggingString () const
+{
+	if (mLogString) return mLogString;
+	
+	AudioComponentDescription desc = GetComponentDescription();
+	
+	const size_t logStringSize = 256;
+	const_cast<AUBase*>(this)->mLogString = new char[logStringSize];
+	char str[24];
+	char str1[24];
+	char str2[24];
+	snprintf (const_cast<AUBase*>(this)->mLogString, logStringSize, "AU (%p): %s %s %s",
+		GetComponentInstance(),
+		CAStringForOSType(desc.componentType, str, sizeof(str)),
+		CAStringForOSType(desc.componentSubType, str1, sizeof(str1)),
+		CAStringForOSType(desc.componentManufacturer, str2, sizeof(str2)));
+
+	return mLogString;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h
new file mode 100644
index 0000000..0c78221
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h
@@ -0,0 +1,1048 @@
+/*
+     File: AUBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUBase_h__
+#define __AUBase_h__
+
+#include <TargetConditionals.h>
+
+#if TARGET_OS_MAC
+	#include <pthread.h>
+#elif TARGET_OS_WIN32
+	#include <windows.h>
+#else
+	#error Unsupported Operating System
+#endif
+
+#include <vector>
+
+#include "AUScopeElement.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include "AUBuffer.h"
+#include "CAMath.h"
+#include "CAThreadSafeList.h"
+#include "CAVectorUnit.h"
+#include "CAMutex.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioUnit.h>
+	#if !CA_BASIC_AU_FEATURES
+		#include <AudioUnit/MusicDevice.h>
+	#endif
+#else
+	#include "AudioUnit.h"
+	#if !CA_BASIC_AU_FEATURES
+		#include "MusicDevice.h"
+	#endif
+#endif
+
+#ifndef AUTRACE
+	#define AUTRACE(code, obj, a, b, c, d)
+#endif	
+
+#include "AUPlugInDispatch.h"
+
+
+
+// ________________________________________________________________________
+// These are to be moved to the public AudioUnit headers
+
+#define kAUDefaultSampleRate		44100.0
+#if !TARGET_OS_WIN32
+#define kAUDefaultMaxFramesPerSlice	1156 
+//this allows enough default frames for a 512 dest 44K and SRC from 96K
+// add a padding of 4 frames for any altivec rounding
+#else
+#define kAUDefaultMaxFramesPerSlice	2048 
+#endif
+
+// ________________________________________________________________________
+
+/*! @class AUBase */
+class AUBase : public ComponentBase {
+public:
+
+	/*! @ctor AUBase */
+								AUBase(					AudioComponentInstance			inInstance, 
+														UInt32							numInputElements,
+														UInt32							numOutputElements,
+														UInt32							numGroupElements = 0);
+	/*! @dtor AUBase */
+	virtual						~AUBase();
+	
+	/*! @method PostConstructor */
+	virtual void				PostConstructor() { CreateElements(); }
+								
+	/*! @method PreDestructor */
+	virtual void				PreDestructor();
+
+	/*! @method CreateElements */
+	void						CreateElements();
+									// Called immediately after construction, when virtual methods work.
+									// Or, a subclass may call this in order to have access to elements
+									// in its constructor.
+
+	/*! @method CreateExtendedElements */
+	virtual void CreateExtendedElements() {}
+
+#pragma mark -
+#pragma mark AU dispatch
+	// ________________________________________________________________________
+	// Virtual methods (mostly) directly corresponding to the entry points.  Many of these
+	// have useful implementations here and will not need overriding.
+	
+	/*! @method DoInitialize */
+			OSStatus			DoInitialize();
+				// this implements the entry point and makes sure that initialization
+				// is only attempted exactly once...
+
+	/*! @method Initialize */
+	virtual OSStatus			Initialize();
+				// ... so that overrides to this method can assume that they will only
+				// be called exactly once.
+	
+	/*! @method IsInitialized */
+			bool				IsInitialized() const { return mInitialized; }
+	/*! @method HasBegunInitializing */
+			bool				HasBegunInitializing() const { return mHasBegunInitializing; }
+			
+	/*! @method DoCleanup */
+			void				DoCleanup();
+				// same pattern as with Initialize
+	
+	/*! @method Cleanup */
+	virtual void				Cleanup();
+
+	/*! @method Reset */
+	virtual OSStatus			Reset(					AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement);
+
+	// Note about GetPropertyInfo, GetProperty, SetProperty:
+	// Certain properties are trapped out in these dispatch functions and handled with different virtual 
+	// methods.  (To discourage hacks and keep vtable size down, these are non-virtual)
+
+	/*! @method DispatchGetPropertyInfo */
+			OSStatus			DispatchGetPropertyInfo(AudioUnitPropertyID				inID,
+														AudioUnitScope					inScope,
+														AudioUnitElement				inElement,
+														UInt32 &						outDataSize,
+														Boolean &						outWritable);
+
+	/*! @method DispatchGetProperty */
+			OSStatus			DispatchGetProperty(	AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement,
+														void *							outData);
+
+	/*! @method DispatchSetProperty */
+			OSStatus			DispatchSetProperty(	AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														const void *					inData,
+														UInt32 							inDataSize);
+													
+			OSStatus			DispatchRemovePropertyValue(	AudioUnitPropertyID 	inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement);
+
+	/*! @method GetPropertyInfo */
+	virtual OSStatus			GetPropertyInfo(		AudioUnitPropertyID				inID,
+														AudioUnitScope					inScope,
+														AudioUnitElement				inElement,
+														UInt32 &						outDataSize,
+														Boolean &						outWritable);
+
+	/*! @method GetProperty */
+	virtual OSStatus			GetProperty(			AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement,
+														void *							outData);
+
+	/*! @method SetProperty */
+	virtual OSStatus			SetProperty(			AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														const void *					inData,
+														UInt32 							inDataSize);
+													
+	/*! @method ClearPropertyUsage */
+	virtual OSStatus			RemovePropertyValue (	AudioUnitPropertyID		 		inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement);
+
+	/*! @method AddPropertyListener */
+	virtual OSStatus			AddPropertyListener(	AudioUnitPropertyID				inID,
+														AudioUnitPropertyListenerProc	inProc,
+														void *							inProcRefCon);
+														
+	/*! @method RemovePropertyListener */
+	virtual OSStatus			RemovePropertyListener(	AudioUnitPropertyID				inID,
+														AudioUnitPropertyListenerProc	inProc,
+														void *							inProcRefCon,
+														bool							refConSpecified);
+	
+	/*! @method SetRenderNotification */
+	virtual OSStatus			SetRenderNotification(	AURenderCallback		 		inProc,
+														void *							inRefCon);
+	
+	/*! @method RemoveRenderNotification */
+	virtual OSStatus			RemoveRenderNotification(
+														AURenderCallback		 		inProc,
+														void *							inRefCon);
+	
+	/*! @method GetParameter */
+	virtual OSStatus 	GetParameter(			AudioUnitParameterID			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														AudioUnitParameterValue &		outValue);
+												
+	/*! @method SetParameter */
+	virtual OSStatus 	SetParameter(			AudioUnitParameterID			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														AudioUnitParameterValue			inValue,
+														UInt32							inBufferOffsetInFrames);
+
+	/*! @method CanScheduleParams */
+	virtual bool CanScheduleParameters() const = 0;
+
+	/*! @method ScheduleParameter */
+	virtual OSStatus 	ScheduleParameter (		const AudioUnitParameterEvent 	*inParameterEvent,
+														UInt32							inNumEvents);
+	
+
+	/*! @method DoRender */
+	OSStatus 	DoRender(								AudioUnitRenderActionFlags &	ioActionFlags,
+														const AudioTimeStamp &			inTimeStamp,
+														UInt32							inBusNumber,
+														UInt32							inNumberFrames,
+														AudioBufferList &				ioData);
+	
+
+	/*! @method Process */
+	OSStatus	DoProcess (							AudioUnitRenderActionFlags  &		ioActionFlags,
+													const AudioTimeStamp &				inTimeStamp,
+													UInt32								inFramesToProcess,
+													AudioBufferList &					ioData);
+	
+	/*! @method ProcessMultiple */
+	OSStatus	DoProcessMultiple (					AudioUnitRenderActionFlags  &		ioActionFlags,
+													const AudioTimeStamp &				inTimeStamp,
+													UInt32								inFramesToProcess,
+													UInt32								inNumberInputBufferLists,
+													const AudioBufferList **			inInputBufferLists,
+													UInt32 								inNumberOutputBufferLists,
+													AudioBufferList **					ioOutputBufferLists);
+		
+	/*! @method ProcessBufferLists */
+	virtual OSStatus	ProcessBufferLists(			AudioUnitRenderActionFlags &		ioActionFlags,
+													const AudioBufferList &				inBuffer,
+													AudioBufferList &					outBuffer,
+													UInt32								inFramesToProcess )
+						{
+							return kAudio_UnimplementedError;
+						}
+
+	/*! @method ProcessMultipleBufferLists */
+	virtual OSStatus	ProcessMultipleBufferLists(	AudioUnitRenderActionFlags &		ioActionFlags,
+													UInt32								inFramesToProcess, 
+												    UInt32								inNumberInputBufferLists,
+												    const AudioBufferList **			inInputBufferLists,
+												    UInt32							 	inNumberOutputBufferLists,
+												    AudioBufferList **					ioOutputBufferLists)	
+						{
+							return kAudio_UnimplementedError;
+						}
+	
+	/*! @method ComplexRender */
+	virtual OSStatus	ComplexRender(				AudioUnitRenderActionFlags &		ioActionFlags, 
+													const AudioTimeStamp &				inTimeStamp, 
+													UInt32								inOutputBusNumber, 
+													UInt32								inNumberOfPackets, 
+													UInt32 *							outNumberOfPackets, 
+													AudioStreamPacketDescription *		outPacketDescriptions, 
+													AudioBufferList &					ioData, 
+													void *								outMetadata, 
+													UInt32 *							outMetadataByteSize) 
+						{	
+							return kAudio_UnimplementedError;
+						}
+
+	// Override this method if your AU processes multiple output busses completely independently --
+	// you'll want to just call Render without the NeedsToRender check.
+	// Otherwise, override Render().
+	//
+	// N.B. Implementations of this method can assume that the output's buffer list has already been
+	// prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of 
+	// GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
+	// copy may occur after rendering.
+	/*! @method RenderBus */
+	virtual OSStatus			RenderBus(				AudioUnitRenderActionFlags &	ioActionFlags,
+														const AudioTimeStamp &			inTimeStamp,
+														UInt32							inBusNumber,
+														UInt32							inNumberFrames)
+								{
+									if (NeedsToRender(inTimeStamp))
+										return Render(ioActionFlags, inTimeStamp, inNumberFrames);
+									return noErr;	// was presumably already rendered via another bus
+								}
+
+	// N.B. For a unit with only one output bus, it can assume in its implementation of this
+	// method that the output's buffer list has already been prepared and access it with 
+	// GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
+	//  -- if PrepareBuffer is called, a copy may occur after rendering.
+	/*! @method Render */
+	virtual OSStatus			Render(					AudioUnitRenderActionFlags &	ioActionFlags,
+														const AudioTimeStamp &			inTimeStamp,
+														UInt32							inNumberFrames)
+								{
+									return noErr;
+								}
+
+								
+#pragma mark -
+#pragma mark Property Dispatch
+
+	static const Float64 kNoLastRenderedSampleTime;
+
+	// ________________________________________________________________________
+	// These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty
+
+	/*! @method BusCountWritable */
+	virtual bool				BusCountWritable(		AudioUnitScope					inScope)
+								{
+									return false;
+								}
+	virtual OSStatus			SetBusCount(		AudioUnitScope					inScope,
+													UInt32							inCount);
+
+	/*! @method SetConnection */
+	virtual OSStatus			SetConnection(			const AudioUnitConnection &		inConnection);
+	
+	/*! @method SetInputCallback */
+	virtual OSStatus			SetInputCallback(		UInt32							inPropertyID,
+														AudioUnitElement 				inElement, 
+														AURenderCallback				inProc,
+														void *							inRefCon);
+
+	/*! @method GetParameterList */
+	virtual OSStatus			GetParameterList(		AudioUnitScope					inScope,
+														AudioUnitParameterID *			outParameterList,
+														UInt32 &						outNumParameters);
+															// outParameterList may be a null pointer
+
+	/*! @method GetParameterInfo */
+	virtual OSStatus			GetParameterInfo(		AudioUnitScope					inScope,
+														AudioUnitParameterID			inParameterID,
+														AudioUnitParameterInfo &		outParameterInfo);
+
+	virtual OSStatus			GetParameterHistoryInfo(AudioUnitScope					inScope,
+														AudioUnitParameterID			inParameterID,
+														Float32 &						outUpdatesPerSecond,
+														Float32 &						outHistoryDurationInSeconds);
+
+	/*! @method SaveState */
+	virtual OSStatus			SaveState(				CFPropertyListRef *				outData);
+    
+    /*! @method SaveExtendedScopes */
+	virtual void                SaveExtendedScopes(		CFMutableDataRef				outData) {};
+
+	/*! @method RestoreState */
+	virtual OSStatus			RestoreState(			CFPropertyListRef				inData);
+
+	/*! @method GetParameterValueStrings */
+	virtual OSStatus			GetParameterValueStrings(AudioUnitScope					inScope,
+														AudioUnitParameterID			inParameterID,
+														CFArrayRef *					outStrings);
+
+	/*! @method CopyClumpName */
+	virtual OSStatus			CopyClumpName(			AudioUnitScope					inScope, 
+														UInt32							inClumpID, 
+														UInt32							inDesiredNameLength,
+														CFStringRef *					outClumpName);
+
+	/*! @method GetPresets */
+	virtual OSStatus			GetPresets (			CFArrayRef * 					outData) const;
+
+		// set the default preset for the unit -> the number of the preset MUST be >= 0
+		// and the name should be valid, or the preset WON'T take
+	/*! @method SetAFactoryPresetAsCurrent */
+	bool						SetAFactoryPresetAsCurrent (const AUPreset & inPreset);
+		
+		// Called when someone sets a new, valid preset
+		// If this is a valid preset, then the subclass sets its state to that preset
+		// and returns noErr.
+		// If not a valid preset, return an error, and the pre-existing preset is restored
+	/*! @method NewFactoryPresetSet */
+	virtual OSStatus			NewFactoryPresetSet (const AUPreset & inNewFactoryPreset);
+	
+	/*! @method NewCustomPresetSet */
+	virtual OSStatus            NewCustomPresetSet (const AUPreset & inNewCustomPreset);
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	/*! @method GetNumCustomUIComponents */
+	virtual int					GetNumCustomUIComponents ();
+
+	/*! @method GetUIComponentDescs */
+	virtual void				GetUIComponentDescs (ComponentDescription* inDescArray);
+#endif
+	
+	/*! @method CopyIconLocation */
+	virtual CFURLRef			CopyIconLocation ();
+	
+	// default is no latency, and unimplemented tail time
+	/*! @method GetLatency */
+    virtual Float64				GetLatency() {return 0.0;}
+	/*! @method GetTailTime */
+    virtual Float64				GetTailTime() {return 0;}
+	/*! @method SupportsRampAndTail */
+	virtual	bool				SupportsTail () { return false; }
+
+	/*! @method IsStreamFormatWritable */
+			bool				IsStreamFormatWritable(	AudioUnitScope					scope,
+														AudioUnitElement				element);
+	
+	/*! @method StreamFormatWritable */
+	virtual bool				StreamFormatWritable(	AudioUnitScope					scope,
+														AudioUnitElement				element) = 0;
+															// scope will always be input or output
+			
+			// pass in a pointer to get the struct, and num channel infos
+			// you can pass in NULL to just get the number
+			// a return value of 0 (the default in AUBase) means the property is not supported...
+	/*! @method SupportedNumChannels */
+	virtual UInt32				SupportedNumChannels (	const AUChannelInfo**			outInfo);
+																												
+	/*! @method ValidFormat */
+	virtual bool				ValidFormat(			AudioUnitScope					inScope,
+														AudioUnitElement				inElement,
+														const CAStreamBasicDescription & inNewFormat);
+															// Will only be called after StreamFormatWritable
+															// has succeeded.
+															// Default implementation requires canonical format:
+															// native-endian 32-bit float, any sample rate,
+															// any number of channels; override when other
+															// formats are supported.  A subclass's override can
+															// choose to always return true and trap invalid 
+															// formats in ChangeStreamFormat.
+
+
+	/*! @method FormatIsCanonical */
+			bool				FormatIsCanonical(		const CAStreamBasicDescription &format);
+
+	/*! @method MakeCanonicalFormat */
+			void				MakeCanonicalFormat(	CAStreamBasicDescription &	outDesc,
+														int							numChannels = 2);
+
+	/*! @method GetStreamFormat */
+	virtual const CAStreamBasicDescription &
+								GetStreamFormat(		AudioUnitScope					inScope,
+														AudioUnitElement				inElement);
+
+	/*! @method ChangeStreamFormat */
+	virtual	OSStatus			ChangeStreamFormat(		AudioUnitScope					inScope,
+														AudioUnitElement				inElement,
+														const CAStreamBasicDescription & inPrevFormat,
+														const CAStreamBasicDescription & inNewFormat);
+															// Will only be called after StreamFormatWritable
+															// and ValidFormat have succeeded.
+															
+	// ________________________________________________________________________
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	/*! @method ComponentEntryDispatch */
+	static OSStatus			ComponentEntryDispatch(	ComponentParameters *			params,
+														AUBase *						This);
+#endif
+
+	// ________________________________________________________________________
+	// Methods useful for subclasses
+	
+	/*! @method GetScope */
+	AUScope &					GetScope(				AudioUnitScope					inScope)
+	{
+		if (inScope >= kNumScopes) {
+			AUScope * scope = GetScopeExtended(inScope);
+			if (!scope) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+			return *scope;
+		}
+		return mScopes[inScope];
+	}
+	
+	/*! @method GetScopeExtended */
+	virtual AUScope *			GetScopeExtended (AudioUnitScope inScope) { return NULL; }
+	
+	/*! @method GlobalScope */
+	AUScope &					GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
+	/*! @method Inputs */
+	AUScope &					Inputs()	{ return mScopes[kAudioUnitScope_Input]; }
+	/*! @method Outputs */
+	AUScope &					Outputs()	{ return mScopes[kAudioUnitScope_Output]; }
+#if !CA_BASIC_AU_FEATURES
+	/*! @method Groups */
+	AUScope &					Groups()	{ return mScopes[kAudioUnitScope_Group]; }
+#endif
+	/*! @method Globals */
+	AUElement *					Globals()	{ return mScopes[kAudioUnitScope_Global].GetElement(0); }
+	
+	/*! @method SetNumberOfElements */
+	void						SetNumberOfElements(	AudioUnitScope					inScope,
+														UInt32							numElements);
+
+	/*! @method GetElement */
+	AUElement *					GetElement(				AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement)
+	{
+		return GetScope(inScope).GetElement(inElement);
+	}
+	
+	/*! @method GetIOElement */
+	AUIOElement *				GetIOElement(			AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement)
+	{
+		return GetScope(inScope).GetIOElement(inElement);
+	}
+	
+	/*! @method SafeGetElement */
+	AUElement *					SafeGetElement(			AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement)
+	{
+		return GetScope(inScope).SafeGetElement(inElement);
+	}
+
+	/*! @method GetInput */
+	AUInputElement *			GetInput(				AudioUnitElement				inElement)
+	{
+		return static_cast<AUInputElement *>(Inputs().SafeGetElement(inElement));
+	}
+	
+	/*! @method GetOutput */
+	AUOutputElement *			GetOutput(				AudioUnitElement				inElement)
+	{
+		return static_cast<AUOutputElement *>(Outputs().SafeGetElement(inElement));
+	}
+	
+#if !CA_BASIC_AU_FEATURES
+	/*! @method GetGroup */
+	AUElement *					GetGroup(				AudioUnitElement				inElement)
+	{
+		return Groups().SafeGetElement(inElement);
+	}
+#endif
+	
+	/*! @method PullInput */
+	OSStatus					PullInput(				UInt32	 					inBusNumber,
+														AudioUnitRenderActionFlags &ioActionFlags,
+														const AudioTimeStamp &		inTimeStamp,
+														UInt32						inNumberFrames)
+	{
+		AUInputElement *input = GetInput(inBusNumber);	// throws if error
+		return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
+	}
+
+	/*! @method GetMaxFramesPerSlice */
+	UInt32						GetMaxFramesPerSlice() const { return mMaxFramesPerSlice; }
+	/*! @method UsesFixedBlockSize */
+	bool						UsesFixedBlockSize() const { return mUsesFixedBlockSize; }
+	/*! @method SetUsesFixedBlockSize */
+	void						SetUsesFixedBlockSize(bool inUsesFixedBlockSize) { mUsesFixedBlockSize = inUsesFixedBlockSize; }
+	
+	/*! @method GetVectorUnitType */
+	static SInt32				GetVectorUnitType() { return sVectorUnitType; }
+	/*! @method HasVectorUnit */
+	static bool					HasVectorUnit() { return sVectorUnitType > 0; }
+	/*! @method HasAltivec */
+	static bool					HasAltivec() { return sVectorUnitType == kVecAltivec; }
+	/*! @method HasSSE2 */
+	static bool					HasSSE2() { return sVectorUnitType >= kVecSSE2; }
+	/*! @method HasSSE3 */
+	static bool					HasSSE3() { return sVectorUnitType >= kVecSSE3; }
+	
+	/*! @method AudioUnitAPIVersion */
+	UInt8						AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; }
+	
+	/*! @method IsRenderThread */
+	bool						InRenderThread () const 
+								{
+#if TARGET_OS_MAC
+									return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
+#elif TARGET_OS_WIN32
+									return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
+#endif
+								}
+
+	/*! @method HasInput */
+	bool						HasInput(				AudioUnitElement				inElement) {
+									AUInputElement *in = static_cast<AUInputElement *>(Inputs().GetElement(inElement));
+									return in != NULL && in->IsActive();
+								}
+									// says whether an input is connected or has a callback
+
+	/*! @method PropertyChanged */
+	virtual void				PropertyChanged(		AudioUnitPropertyID				inID,
+														AudioUnitScope					inScope, 
+														AudioUnitElement				inElement);
+
+#if !CA_NO_AU_UI_FEATURES
+	// These calls can be used to call a Host's Callbacks. The method returns -1 if the host
+	// hasn't supplied the callback. Any other result is returned by the host.
+	// As in the API contract, for a parameter's value, you specify a pointer
+	// to that data type. Specify NULL for a parameter that you are not interested
+	// as this can save work in the host.
+
+	/*! @method CallHostBeatAndTempo */
+	OSStatus	CallHostBeatAndTempo (Float64				*outCurrentBeat,  
+										Float64				*outCurrentTempo)
+	{
+		return (mHostCallbackInfo.beatAndTempoProc 
+						? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData, 
+																	outCurrentBeat, 
+																	outCurrentTempo)
+						: -1);
+	}
+
+	/*! @method CallHostMusicalTimeLocation */
+	OSStatus	CallHostMusicalTimeLocation (UInt32  		*outDeltaSampleOffsetToNextBeat,
+										Float32           	*outTimeSig_Numerator,
+										UInt32            	*outTimeSig_Denominator,
+										Float64           	*outCurrentMeasureDownBeat)
+	{
+		return (mHostCallbackInfo.musicalTimeLocationProc 
+						? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData,
+																			outDeltaSampleOffsetToNextBeat,
+																			outTimeSig_Numerator,
+																			outTimeSig_Denominator,
+																			outCurrentMeasureDownBeat)
+						: -1);
+	}											
+
+	/*! @method CallHostTransportState */
+	OSStatus	CallHostTransportState (Boolean 			*outIsPlaying,
+										Boolean 			*outTransportStateChanged,
+										Float64 			*outCurrentSampleInTimeLine,
+										Boolean 			*outIsCycling,
+										Float64 			*outCycleStartBeat,
+										Float64 			*outCycleEndBeat)
+	{
+		return (mHostCallbackInfo.transportStateProc 
+						? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData,
+																		outIsPlaying,
+																		outTransportStateChanged,
+																		outCurrentSampleInTimeLine,
+																		outIsCycling,
+																		outCycleStartBeat,
+																		outCycleEndBeat)
+						: -1);
+	}
+#endif
+
+	char*						GetLoggingString () const;
+	
+	CAMutex*					GetMutex() { return mAUMutex; }
+
+	// ________________________________________________________________________
+	/*! @method CreateElement */
+	virtual AUElement *			CreateElement(			AudioUnitScope					scope,
+														AudioUnitElement				element);
+
+#pragma mark -
+#pragma mark AU Output Base Dispatch
+	// ________________________________________________________________________
+	// ________________________________________________________________________
+	// ________________________________________________________________________
+	// output unit methods
+	/*! @method Start */
+	virtual OSStatus	Start() { return kAudio_UnimplementedError; }
+	/*! @method Stop */
+	virtual OSStatus	Stop() { return kAudio_UnimplementedError; }
+	
+#if !CA_BASIC_AU_FEATURES
+#pragma mark -
+#pragma mark AU Music Base Dispatch
+
+#if !TARGET_OS_IPHONE
+// these methods are deprecated, so we don't include them except for compatability
+	/*! @method PrepareInstrument */
+	virtual OSStatus			PrepareInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
+
+	/*! @method PrepareInstrument */
+	virtual OSStatus			ReleaseInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
+#endif
+	
+	// ________________________________________________________________________
+	// ________________________________________________________________________
+	// ________________________________________________________________________
+	// music device/music effect methods -- incomplete
+	/*! @method MIDIEvent */
+	virtual OSStatus	MIDIEvent(		UInt32 						inStatus, 
+										UInt32 						inData1, 
+										UInt32 						inData2, 
+										UInt32 						inOffsetSampleFrame) { return kAudio_UnimplementedError; }
+
+	/*! @method SysEx */
+	virtual OSStatus	SysEx(			const UInt8 *				inData, 
+										UInt32 						inLength) { return kAudio_UnimplementedError;}
+										
+	/*! @method StartNote */
+	virtual OSStatus	StartNote(		MusicDeviceInstrumentID 	inInstrument, 
+										MusicDeviceGroupID 			inGroupID, 
+										NoteInstanceID *			outNoteInstanceID, 
+										UInt32 						inOffsetSampleFrame, 
+										const MusicDeviceNoteParams &inParams) { return kAudio_UnimplementedError; }
+
+	/*! @method StopNote */
+	virtual OSStatus	StopNote(		MusicDeviceGroupID 			inGroupID, 
+										NoteInstanceID 				inNoteInstanceID, 
+										UInt32 						inOffsetSampleFrame) { return kAudio_UnimplementedError; }
+#endif
+
+	// ________________________________________________________________________
+	// ________________________________________________________________________
+	// ________________________________________________________________________
+	
+protected:
+#pragma mark -
+#pragma mark Implementation methods
+
+	/*! @method ReallocateBuffers */
+	virtual void				ReallocateBuffers();
+									// needs to be called when mMaxFramesPerSlice changes
+	virtual void				DeallocateIOBuffers();
+		
+	/*! @method FillInParameterName */
+	static void					FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease)
+	{
+		ioInfo.cfNameString = inName;
+		ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
+		if (inShouldRelease)
+			ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
+		CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8);
+	}
+	
+	static void					HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID)				
+	{
+		ioInfo.clumpID = inClumpID;
+		ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
+	}
+	
+	/*! @method SetMaxFramesPerSlice */
+	virtual void				SetMaxFramesPerSlice(UInt32 nFrames);
+
+	/*! @method CanSetMaxFrames */
+	virtual OSStatus			CanSetMaxFrames() const;
+	
+	/*! @method WantsRenderThreadID */
+	bool						WantsRenderThreadID () const { return mWantsRenderThreadID; }
+	
+	/*! @method SetWantsRenderThreadID */
+	void						SetWantsRenderThreadID (bool inFlag);
+	
+	/*! @method SetRenderError */
+	OSStatus					SetRenderError (OSStatus inErr)
+	{
+		if (inErr && mLastRenderError == 0) {
+			mLastRenderError = inErr;
+			PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
+		}
+		return inErr;
+	}
+	
+private:
+	/*! @method DoRenderBus */
+	// shared between Render and RenderSlice, inlined to minimize function call overhead
+	OSStatus					DoRenderBus(			AudioUnitRenderActionFlags &	ioActionFlags,
+														const AudioTimeStamp &			inTimeStamp,
+														UInt32							inBusNumber,
+														AUOutputElement *				theOutput,
+														UInt32							inNumberFrames,
+														AudioBufferList &				ioData)
+	{
+		if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1))
+			// will render into cache buffer
+			theOutput->PrepareBuffer(inNumberFrames);
+		else
+			// will render into caller's buffer
+			theOutput->SetBufferList(ioData);
+		OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
+		if (result == noErr) {
+			if (ioData.mBuffers[0].mData == NULL) {
+				theOutput->CopyBufferListTo(ioData);
+				AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
+			} else {
+				theOutput->CopyBufferContentsTo(ioData);
+				AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, (intptr_t)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
+				theOutput->InvalidateBufferList();
+			}
+		}
+		return result;
+	}
+
+	/*! @method HasIcon */
+	bool						HasIcon ();
+
+	/*! @method ResetRenderTime */
+	void						ResetRenderTime ()
+								{
+									memset (&mCurrentRenderTime, 0, sizeof(mCurrentRenderTime));
+									mCurrentRenderTime.mSampleTime = kNoLastRenderedSampleTime;
+								}
+				
+protected:
+	/*! @method GetAudioChannelLayout */
+	virtual UInt32				GetChannelLayoutTags(	AudioUnitScope				scope,
+														AudioUnitElement 			element,
+														AudioChannelLayoutTag *		outLayoutTags);
+														
+	/*! @method GetAudioChannelLayout */
+	virtual UInt32				GetAudioChannelLayout(	AudioUnitScope				scope,
+														AudioUnitElement 			element,
+														AudioChannelLayout *		outLayoutPtr,
+														Boolean &					outWritable);
+
+	/*! @method SetAudioChannelLayout */
+	virtual OSStatus			SetAudioChannelLayout(	AudioUnitScope 				scope, 
+														AudioUnitElement 			element,
+														const AudioChannelLayout *	inLayout);
+
+	/*! @method RemoveAudioChannelLayout */
+	virtual OSStatus			RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);
+	
+	/*! @method NeedsToRender */
+	bool						NeedsToRender(			const AudioTimeStamp &		inTimeStamp)
+								{
+									bool needsToRender = fnotequal(inTimeStamp.mSampleTime, mCurrentRenderTime.mSampleTime);
+									if (needsToRender)	// only copy this if we need to render
+										mCurrentRenderTime = inTimeStamp;
+									return needsToRender;
+								}
+	
+	// Scheduled parameter implementation:
+
+	typedef std::vector<AudioUnitParameterEvent> ParameterEventList;
+
+	// Usually, you won't override this method.  You only need to call this if your DSP code
+	// is prepared to handle scheduled immediate and ramped parameter changes.
+	// Before calling this method, it is assumed you have already called PullInput() on the input busses
+	// for which the DSP code depends.  ProcessForScheduledParams() will call (potentially repeatedly)
+	// virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
+	// the buffer.  The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
+	// pieces according to the scheduled times found in the ParameterEventList (usually coming 
+	// directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
+	// ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
+	// to do the actual DSP for each of these divisions.
+	virtual OSStatus 	ProcessForScheduledParams(	ParameterEventList		&inParamList,
+															UInt32					inFramesToProcess,
+															void					*inUserData );
+	
+	//	This method is called (potentially repeatedly) by ProcessForScheduledParams()
+	//	in order to perform the actual DSP required for this portion of the entire buffer
+	//	being processed.  The entire buffer can be divided up into smaller "slices"
+	//	according to the timestamps on the scheduled parameters...
+	//
+	//	sub-classes wishing to handle scheduled parameter changes should override this method
+	//  in order to do the appropriate DSP.  AUEffectBase already overrides this for standard
+	//	effect AudioUnits.
+	virtual OSStatus			ProcessScheduledSlice(	void				*inUserData,
+														UInt32				inStartFrameInBuffer,
+														UInt32				inSliceFramesToProcess,
+														UInt32				inTotalBufferFrames ) {return noErr;};	// default impl does nothing...
+	
+	
+	/*! @method CurrentRenderTime */
+	const AudioTimeStamp &		CurrentRenderTime () const { return mCurrentRenderTime; }
+	
+	// ________________________________________________________________________
+	//	Private data members to discourage hacking in subclasses
+private:
+	struct RenderCallback {
+		RenderCallback(AURenderCallback proc, void *ref) :
+			mRenderNotify(proc),
+			mRenderNotifyRefCon(ref)
+		{ }
+		
+		AURenderCallback			mRenderNotify;
+		void *						mRenderNotifyRefCon;
+		
+		bool operator == (const RenderCallback &other) {
+			return this->mRenderNotify == other.mRenderNotify &&
+					this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
+		}
+	};
+	typedef TThreadSafeList<RenderCallback>	RenderCallbackList;
+	
+#if !CA_BASIC_AU_FEATURES
+	enum { kNumScopes = 4 };
+#else
+	enum { kNumScopes = 3 };
+#endif
+	
+	/*! @var mElementsCreated */
+	bool						mElementsCreated;
+protected:
+	/*! @var mInitialized */
+	bool						mInitialized;
+	/*! @var mHasBegunInitializing */
+	bool						mHasBegunInitializing;
+private:
+	/*! @var mAudioUnitAPIVersion */
+	UInt8						mAudioUnitAPIVersion;
+	
+	/*! @var mInitNumInputEls */
+	const UInt32				mInitNumInputEls;
+	/*! @var mInitNumOutputEls */
+	const UInt32				mInitNumOutputEls;
+#if !CA_BASIC_AU_FEATURES
+	/*! @var mInitNumGroupEls */
+	const UInt32				mInitNumGroupEls;
+#endif
+	/*! @var mScopes */
+	AUScope						mScopes[kNumScopes];
+	
+	/*! @var mRenderCallbacks */
+	RenderCallbackList			mRenderCallbacks;
+	bool						mRenderCallbacksTouched;
+	
+	/*! @var mRenderThreadID */
+#if TARGET_OS_MAC
+	pthread_t					mRenderThreadID;
+#elif TARGET_OS_WIN32
+	UInt32						mRenderThreadID;
+#endif
+	
+	/*! @var mWantsRenderThreadID */
+	bool						mWantsRenderThreadID;
+		
+	/*! @var mCurrentRenderTime */
+	AudioTimeStamp				mCurrentRenderTime;
+	
+	/*! @var mMaxFramesPerSlice */
+	UInt32						mMaxFramesPerSlice;
+	
+	/*! @var mLastRenderError */
+	OSStatus					mLastRenderError;
+	/*! @var mCurrentPreset */
+	AUPreset					mCurrentPreset;
+	
+protected:
+	/*! @var mUsesFixedBlockSize */
+	bool						mUsesFixedBlockSize;
+	
+	struct PropertyListener {
+		AudioUnitPropertyID				propertyID;
+		AudioUnitPropertyListenerProc	listenerProc;
+		void *							listenerRefCon;
+	};
+	typedef std::vector<PropertyListener>	PropertyListeners;
+
+	/*! @var mParamList */
+	ParameterEventList			mParamList;
+	/*! @var mPropertyListeners */
+	PropertyListeners			mPropertyListeners;
+	
+	/*! @var mBuffersAllocated */
+	bool						mBuffersAllocated;
+	
+	/*! @var mLogString */
+	// if this is NOT null, it will contain identifying info about this AU.
+	char*						mLogString;
+
+	/*! @var mNickName */
+	CFStringRef					mNickName;
+
+	/*! @var mAUMutex */
+	CAMutex *					mAUMutex;
+
+private:
+	/*! @var sVectorUnitType */
+	static SInt32	sVectorUnitType;
+
+#if !CA_NO_AU_HOST_CALLBACKS
+protected:
+	/*! @var mHostCallbackInfo */
+	HostCallbackInfo 			mHostCallbackInfo;
+
+#endif
+#if !CA_NO_AU_UI_FEATURES
+protected:
+	/*! @var mContextInfo */
+	CFStringRef					mContextName;
+#endif
+};
+
+inline 	OSStatus	AUInputElement::PullInputWithBufferList(	
+												AudioUnitRenderActionFlags &  	ioActionFlags,
+												const AudioTimeStamp &			inTimeStamp,
+												AudioUnitElement				inElement,
+												UInt32							nFrames,
+												AudioBufferList *				inBufferList)
+{
+	OSStatus theResult;
+	
+	if (HasConnection()) {
+			// only support connections for V2 audio units
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+		if (mConnRenderProc != NULL)
+			theResult = reinterpret_cast<AudioUnitRenderProc>(mConnRenderProc)(
+							mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+		else
+#endif
+			theResult = AudioUnitRender(
+							mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+	} else {
+		// kFromCallback:
+			theResult = (mInputProc)(
+							mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
+	}
+	
+	if (mInputType == kNoInput)	// defense: the guy upstream could have disconnected
+								// it's a horrible thing to do, but may happen!
+		return kAudioUnitErr_NoConnection;
+
+
+	return theResult;
+}
+
+#endif // __AUBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
new file mode 100644
index 0000000..1f0f01c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
@@ -0,0 +1,438 @@
+/*
+     File: AUDispatch.cpp
+ Abstract: AUDispatch.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUBase.h"
+#include "CAXException.h"
+#include "AUDispatch.h"
+
+
+
+#if TARGET_OS_MAC
+	#if __LP64__
+		// comp instance, parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index + 1];
+	#else
+		// parameters in reverse order, then comp instance
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+	#endif
+#elif TARGET_OS_WIN32
+		// (no comp instance), parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index];
+#endif
+
+
+OSStatus		AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
+{
+	if (This == NULL) return kAudio_ParamError;
+
+	OSStatus result = noErr;
+
+	switch (params->what) {
+	case kComponentCanDoSelect:
+		switch (GetSelectorForCanDo(params)) {
+	// any selectors
+			case kAudioUnitInitializeSelect:
+			case kAudioUnitUninitializeSelect:
+			case kAudioUnitGetPropertyInfoSelect:
+			case kAudioUnitGetPropertySelect:
+			case kAudioUnitSetPropertySelect:
+			case kAudioUnitAddPropertyListenerSelect:
+#if (!__LP64__)
+			case kAudioUnitRemovePropertyListenerSelect:
+#endif
+			case kAudioUnitGetParameterSelect:
+			case kAudioUnitSetParameterSelect:
+			case kAudioUnitResetSelect:
+				result = 1;
+				break;
+	// v1 selectors
+
+	// v2 selectors
+			case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+			case kAudioUnitAddRenderNotifySelect:
+			case kAudioUnitRemoveRenderNotifySelect:
+			case kAudioUnitScheduleParametersSelect:
+			case kAudioUnitRenderSelect:
+				result = (This->AudioUnitAPIVersion() > 1);
+				break;
+				
+			default:
+				return ComponentBase::ComponentEntryDispatch(params, This);
+		}
+		break;
+		
+	case kAudioUnitInitializeSelect:
+	{
+		CAMutex::Locker lock2(This->GetMutex());
+		result = This->DoInitialize();
+	}
+		break;
+		
+	case kAudioUnitUninitializeSelect:
+	{
+		CAMutex::Locker lock2(This->GetMutex());
+		This->DoCleanup();
+		result = noErr;
+	}
+		break;
+
+	case kAudioUnitGetPropertyInfoSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitPropertyID, pinID, 0, 5);
+			PARAM(AudioUnitScope, pinScope, 1, 5);
+			PARAM(AudioUnitElement, pinElement, 2, 5);
+			PARAM(UInt32 *, poutDataSize, 3, 5);
+			PARAM(Boolean *, poutWritable, 4, 5);
+
+			// pass our own copies so that we assume responsibility for testing
+			// the caller's pointers against null and our C++ classes can
+			// always assume they're non-null
+			UInt32 dataSize;
+			Boolean writable;
+			
+			result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
+			if (poutDataSize != NULL)
+				*poutDataSize = dataSize;
+			if (poutWritable != NULL)
+				*poutWritable = writable;
+		}
+		break;
+
+	case kAudioUnitGetPropertySelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitPropertyID, pinID, 0, 5);
+			PARAM(AudioUnitScope, pinScope, 1, 5);
+			PARAM(AudioUnitElement, pinElement, 2, 5);
+			PARAM(void *, poutData, 3, 5);
+			PARAM(UInt32 *, pioDataSize, 4, 5);
+
+			UInt32 actualPropertySize, clientBufferSize;
+			Boolean writable;
+			char *tempBuffer;
+			void *destBuffer;
+			
+			if (pioDataSize == NULL) {
+				ca_debug_string("AudioUnitGetProperty: null size pointer");
+				result = kAudio_ParamError;
+				goto finishGetProperty;
+			}
+			if (poutData == NULL) {
+				UInt32 dataSize;
+				
+				result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
+				*pioDataSize = dataSize;
+				goto finishGetProperty;
+			}
+			
+			clientBufferSize = *pioDataSize;
+			if (clientBufferSize == 0)
+			{
+				ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
+				// $$$ or should we allow this as a shortcut for finding the size?
+				result = kAudio_ParamError;
+				goto finishGetProperty;
+			}
+			
+			result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, 
+													actualPropertySize, writable);
+			if (result) 
+				goto finishGetProperty;
+			
+			if (clientBufferSize < actualPropertySize) 
+			{
+				tempBuffer = new char[actualPropertySize];
+				destBuffer = tempBuffer;
+			} else {
+				tempBuffer = NULL;
+				destBuffer = poutData;
+			}
+			
+			result = This->DispatchGetProperty(pinID, pinScope, pinElement, destBuffer);
+			
+			if (result == noErr) {
+				if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
+				{
+					memcpy(poutData, tempBuffer, clientBufferSize);
+					delete[] tempBuffer;
+					// pioDataSize remains correct, the number of bytes we wrote
+				} else
+					*pioDataSize = actualPropertySize;
+			} else
+				*pioDataSize = 0;
+
+			finishGetProperty:
+				;
+
+		}
+		break;
+		
+	case kAudioUnitSetPropertySelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitPropertyID, pinID, 0, 5);
+			PARAM(AudioUnitScope, pinScope, 1, 5);
+			PARAM(AudioUnitElement, pinElement, 2, 5);
+			PARAM(const void *, pinData, 3, 5);
+			PARAM(UInt32, pinDataSize, 4, 5);
+			
+			if (pinData && pinDataSize)
+				result = This->DispatchSetProperty(pinID, pinScope, pinElement, pinData, pinDataSize);
+			else {
+				if (pinData == NULL && pinDataSize == 0) {
+					result = This->DispatchRemovePropertyValue (pinID, pinScope, pinElement);
+				} else {
+					if (pinData == NULL) {
+						ca_debug_string("AudioUnitSetProperty: inData == NULL");
+						result = kAudio_ParamError;
+						goto finishSetProperty;
+					}
+
+					if (pinDataSize == 0) {
+						ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
+						result = kAudio_ParamError;
+						goto finishSetProperty;
+					}
+				}
+			}
+			finishSetProperty:
+					;
+
+		}
+		break;
+		
+	case kAudioUnitAddPropertyListenerSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitPropertyID, pinID, 0, 3);
+			PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
+			PARAM(void *, pinProcRefCon, 2, 3);
+			result = This->AddPropertyListener(pinID, pinProc, pinProcRefCon);
+		}
+		break;
+
+#if (!__LP64__)
+	case kAudioUnitRemovePropertyListenerSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitPropertyID, pinID, 0, 2);
+			PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
+			result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
+		}
+		break;
+#endif
+
+	case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitPropertyID, pinID, 0, 3);
+			PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
+			PARAM(void *, pinProcRefCon, 2, 3);
+			result = This->RemovePropertyListener(pinID, pinProc, pinProcRefCon, true);
+		}
+		break;
+		
+	case kAudioUnitAddRenderNotifySelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AURenderCallback, pinProc, 0, 2);
+			PARAM(void *, pinProcRefCon, 1, 2);
+			result = This->SetRenderNotification (pinProc, pinProcRefCon);
+		}
+		break;
+
+	case kAudioUnitRemoveRenderNotifySelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AURenderCallback, pinProc, 0, 2);
+			PARAM(void *, pinProcRefCon, 1, 2);
+			result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
+		}
+		break;
+
+	case kAudioUnitGetParameterSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitParameterID, pinID, 0, 4);
+			PARAM(AudioUnitScope, pinScope, 1, 4);
+			PARAM(AudioUnitElement, pinElement, 2, 4);
+			PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
+			result = (poutValue == NULL ? kAudio_ParamError : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
+		}
+		break;
+
+	case kAudioUnitSetParameterSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
+			PARAM(AudioUnitParameterID, pinID, 0, 5);
+			PARAM(AudioUnitScope, pinScope, 1, 5);
+			PARAM(AudioUnitElement, pinElement, 2, 5);
+			PARAM(AudioUnitParameterValue, pinValue, 3, 5);
+			PARAM(UInt32, pinBufferOffsetInFrames, 4, 5);
+			result = This->SetParameter(pinID, pinScope, pinElement, pinValue, pinBufferOffsetInFrames);
+		}
+		break;
+
+	case kAudioUnitScheduleParametersSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
+			if (This->AudioUnitAPIVersion() > 1)
+			{
+				PARAM(AudioUnitParameterEvent *, pinParameterEvent, 0, 2);
+				PARAM(UInt32, pinNumParamEvents, 1, 2);
+				result = This->ScheduleParameter (pinParameterEvent, pinNumParamEvents);
+			} else
+				result = badComponentSelector;
+		}
+		break;
+
+
+	case kAudioUnitRenderSelect:
+		{
+			// realtime; no lock
+			{
+				PARAM(AudioUnitRenderActionFlags *, pinActionFlags, 0, 5);
+				PARAM(const AudioTimeStamp *, pinTimeStamp, 1, 5);
+				PARAM(UInt32, pinOutputBusNumber, 2, 5);
+				PARAM(UInt32, pinNumberFrames, 3, 5);
+				PARAM(AudioBufferList *, pioData, 4, 5);
+				AudioUnitRenderActionFlags tempFlags;
+				
+				if (pinTimeStamp == NULL || pioData == NULL)
+					result = kAudio_ParamError;
+				else {
+					if (pinActionFlags == NULL) {
+						tempFlags = 0;
+						pinActionFlags = &tempFlags;
+					}
+					result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
+				}
+			}			
+		}
+		break;
+
+	case kAudioUnitResetSelect:
+		{
+			CAMutex::Locker lock(This->GetMutex());
+			PARAM(AudioUnitScope, pinScope, 0, 2);
+			PARAM(AudioUnitElement, pinElement, 1, 2);
+			This->ResetRenderTime();
+			result = This->Reset(pinScope, pinElement);
+		}
+		break;
+
+	default:
+		result = ComponentBase::ComponentEntryDispatch(params, This);
+		break;
+	}
+
+	return result;
+}
+
+// Fast dispatch entry points -- these need to replicate all error-checking logic from above
+
+OSStatus CMgr_AudioUnitBaseGetParameter(	AUBase *				This,
+											AudioUnitParameterID	inID,
+											AudioUnitScope			inScope,
+											AudioUnitElement		inElement,
+											float					*outValue)
+{
+	OSStatus result = AUBase::noErr;
+	
+	try {
+		if (This == NULL || outValue == NULL) return kAudio_ParamError;
+		result = This->GetParameter(inID, inScope, inElement, *outValue);
+	}
+	COMPONENT_CATCH
+	
+	return result;
+}
+
+OSStatus CMgr_AudioUnitBaseSetParameter(	AUBase * 				This,
+											AudioUnitParameterID	inID,
+											AudioUnitScope			inScope,
+											AudioUnitElement		inElement,
+											float					inValue,
+											UInt32					inBufferOffset)
+{
+	OSStatus result = AUBase::noErr;
+	
+	try {
+		if (This == NULL) return kAudio_ParamError;
+		result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
+	}
+	COMPONENT_CATCH
+	
+	return result;
+}
+
+OSStatus CMgr_AudioUnitBaseRender(			AUBase *				This,
+											AudioUnitRenderActionFlags *ioActionFlags,
+											const AudioTimeStamp *	inTimeStamp,
+											UInt32					inBusNumber,
+											UInt32					inNumberFrames,
+											AudioBufferList *		ioData)
+{
+	if (inTimeStamp == NULL || ioData == NULL) return kAudio_ParamError;
+	
+	OSStatus result = AUBase::noErr;
+	AudioUnitRenderActionFlags tempFlags;
+	
+	try {
+		if (ioActionFlags == NULL) {
+			tempFlags = 0;
+			ioActionFlags = &tempFlags;
+		}
+		result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
+	}
+	COMPONENT_CATCH
+	
+	return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h
new file mode 100644
index 0000000..5acd962
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h
@@ -0,0 +1,82 @@
+/*
+     File: AUDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUDispatch_h__
+#define __AUDispatch_h__
+
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioUnit.h>
+#else
+	#include "AudioUnit.h"
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+/*! @function AudioUnitBaseGetParameter */
+OSStatus CMgr_AudioUnitBaseGetParameter(	AUBase *				This,
+											AudioUnitParameterID	inID,
+											AudioUnitScope			inScope,
+											AudioUnitElement		inElement,
+											float *					outValue);
+
+/*! @function AudioUnitBaseSetParameter */
+OSStatus CMgr_AudioUnitBaseSetParameter(	AUBase *		 		This,
+											AudioUnitParameterID	inID,
+											AudioUnitScope			inScope,
+											AudioUnitElement		inElement,
+											float					inValue,
+											UInt32					inBufferOffset);
+
+/*! @function AudioUnitBaseRender */
+OSStatus CMgr_AudioUnitBaseRender(			AUBase *				This,
+											AudioUnitRenderActionFlags *ioActionFlags,
+											const AudioTimeStamp *	inTimeStamp,
+											UInt32					inBusNumber,
+											UInt32					inNumberFrames,
+											AudioBufferList *		ioData);
+#endif
+
+#endif // __AUDispatch_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
new file mode 100644
index 0000000..2e148e8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
@@ -0,0 +1,151 @@
+/*
+     File: AUInputElement.cpp
+ Abstract: AUInputElement.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUBase.h"
+
+inline bool	HasGoodBufferPointers(const AudioBufferList &abl, UInt32 nBytes)
+{
+	const AudioBuffer *buf = abl.mBuffers;
+	for (UInt32 i = abl.mNumberBuffers; i--;++buf) {
+		if (buf->mData == NULL || buf->mDataByteSize < nBytes)
+			return false;
+	}
+	return true;
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//	AUInputElement::AUInputElement
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+AUInputElement::AUInputElement(AUBase *audioUnit) :
+	AUIOElement(audioUnit),
+	mInputType(kNoInput)
+{
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//	AUInputElement::SetConnection
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void	AUInputElement::SetConnection(const AudioUnitConnection &conn)
+{
+	if (conn.sourceAudioUnit == 0) {
+		Disconnect();
+		return;
+	}	
+	
+	mInputType = kFromConnection;
+	mConnection = conn;
+	AllocateBuffer();
+
+	mConnInstanceStorage = NULL;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	mConnRenderProc = NULL;
+	UInt32 size = sizeof(AudioUnitRenderProc);
+	OSStatus result = AudioUnitGetProperty(	conn.sourceAudioUnit,
+							kAudioUnitProperty_FastDispatch,
+							kAudioUnitScope_Global,
+							kAudioUnitRenderSelect,
+							&mConnRenderProc,
+							&size);
+	if (result == noErr)
+		mConnInstanceStorage = CMgr_GetComponentInstanceStorage (conn.sourceAudioUnit);
+	else
+		mConnRenderProc = NULL;
+#endif
+}
+
+void	AUInputElement::Disconnect()
+{
+	mInputType = kNoInput;
+	mIOBuffer.Deallocate();
+}
+
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//	AUInputElement::SetInputCallback
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void	AUInputElement::SetInputCallback(AURenderCallback proc, void *refCon)
+{
+	if (proc == NULL)
+		Disconnect();
+	else {
+		mInputType = kFromCallback;
+		mInputProc = proc;
+		mInputProcRefCon = refCon;
+		AllocateBuffer();
+	}
+}
+
+OSStatus	AUInputElement::SetStreamFormat(const CAStreamBasicDescription &fmt)
+{
+	OSStatus err = AUIOElement::SetStreamFormat(fmt);
+	if (err == AUBase::noErr)
+		AllocateBuffer();
+	return err;
+}
+
+OSStatus		AUInputElement::PullInput(	AudioUnitRenderActionFlags &  	ioActionFlags,
+											const AudioTimeStamp &			inTimeStamp,
+											AudioUnitElement				inElement,
+											UInt32							nFrames)
+{	
+	if (!IsActive())
+		return kAudioUnitErr_NoConnection;
+		
+	AudioBufferList *pullBuffer;
+	
+	if (HasConnection() || !WillAllocateBuffer())
+		pullBuffer = &mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
+	else
+		pullBuffer = &mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
+	
+	return PullInputWithBufferList (ioActionFlags, inTimeStamp, inElement, nFrames, pullBuffer);
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h
new file mode 100644
index 0000000..891e4c6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h
@@ -0,0 +1,119 @@
+/*
+     File: AUInputElement.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUInput_h__
+#define __AUInput_h__
+
+#include "AUScopeElement.h"
+#include "AUBuffer.h"
+
+/*! @class AUInputElement */
+class AUInputElement : public AUIOElement {
+public:
+	
+	/*! @ctor AUInputElement */
+						AUInputElement(AUBase *audioUnit);
+	/*! @dtor ~AUInputElement */
+	virtual				~AUInputElement() { }
+
+	// AUElement override
+	/*! @method SetStreamFormat */
+	virtual OSStatus	SetStreamFormat(const CAStreamBasicDescription &desc);
+	/*! @method NeedsBufferSpace */
+	virtual bool		NeedsBufferSpace() const { return IsCallback(); }
+
+	/*! @method SetConnection */
+	void				SetConnection(const AudioUnitConnection &conn);
+	/*! @method SetInputCallback */
+	void				SetInputCallback(AURenderCallback proc, void *refCon);
+
+	/*! @method IsActive */
+	bool				IsActive() const { return mInputType != kNoInput; }
+	/*! @method IsCallback */
+	bool				IsCallback() const { return mInputType == kFromCallback; }
+	/*! @method HasConnection */
+	bool				HasConnection() const { return mInputType == kFromConnection; }
+
+	/*! @method PullInput */
+	OSStatus			PullInput(	AudioUnitRenderActionFlags &  	ioActionFlags,
+									const AudioTimeStamp &			inTimeStamp,
+									AudioUnitElement				inElement,
+									UInt32							inNumberFrames);
+
+	/*! @method PullInputWithBufferList */
+	OSStatus			PullInputWithBufferList(	AudioUnitRenderActionFlags &  	ioActionFlags,
+													const AudioTimeStamp &			inTimeStamp,
+													AudioUnitElement				inElement,
+													UInt32							nFrames,
+													AudioBufferList *				inBufferList);
+protected:
+	/*! @method Disconnect */
+	void				Disconnect();
+
+	enum EInputType { kNoInput, kFromConnection, kFromCallback };
+
+	/*! @var mInputType */
+	EInputType					mInputType;
+
+	// if from callback:
+	/*! @var mInputProc */
+	AURenderCallback			mInputProc;
+	/*! @var mInputProcRefCon */
+	void *						mInputProcRefCon;
+	
+	// if from connection:
+	/*! @var mConnection */
+	AudioUnitConnection			mConnection;
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	/*! @var mConnRenderProc */
+	AudioUnitRenderProc			mConnRenderProc;
+#endif
+	/*! @var mConnInstanceStorage */
+	void *						mConnInstanceStorage;		// for the input component
+};
+
+
+#endif // __AUInput_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
new file mode 100644
index 0000000..5eb34a1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
@@ -0,0 +1,62 @@
+/*
+     File: AUOutputElement.cpp
+ Abstract: AUOutputElement.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUOutputElement.h"
+#include "AUBase.h"
+
+AUOutputElement::AUOutputElement(AUBase *audioUnit) : 
+	AUIOElement(audioUnit)
+{
+	AllocateBuffer();
+}
+
+OSStatus	AUOutputElement::SetStreamFormat(const CAStreamBasicDescription &desc)
+{
+	OSStatus result = AUIOElement::SetStreamFormat(desc);	// inherited
+	if (result == AUBase::noErr)
+		AllocateBuffer();
+	return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h
new file mode 100644
index 0000000..3e6a938
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h
@@ -0,0 +1,66 @@
+/*
+     File: AUOutputElement.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUOutput_h__
+#define __AUOutput_h__
+
+#include "AUScopeElement.h"
+#include "AUBuffer.h"
+
+	/*! @class AUOutputElement */
+class AUOutputElement : public AUIOElement {
+public:
+	/*! @ctor AUOutputElement */
+						AUOutputElement(AUBase *audioUnit);
+
+	// AUElement override
+	/*! @method SetStreamFormat */
+	virtual OSStatus	SetStreamFormat(const CAStreamBasicDescription &desc);
+	/*! @method NeedsBufferSpace */
+	virtual bool		NeedsBufferSpace() const { return true; }
+};
+
+#endif // __AUOutput_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp
new file mode 100644
index 0000000..3bab198
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp
@@ -0,0 +1,669 @@
+/*
+     File: AUPlugInDispatch.cpp
+ Abstract: AUPlugInDispatch.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUPlugInDispatch.h"
+#include "CAXException.h"
+#include "ComponentBase.h"
+#include "AUBase.h"
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define AUI	((AUBase *)&ACPI->mInstanceStorage)
+
+#define AUI_LOCK CAMutex::Locker auLock(AUI->GetMutex());
+
+// ------------------------------------------------------------------------------------------------
+static OSStatus AUMethodInitialize(void *self)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->DoInitialize();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodUninitialize(void *self)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		AUI->DoCleanup();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodGetPropertyInfo(void *self, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *outDataSize, Boolean *outWritable)
+{
+	OSStatus result = noErr;
+	try {
+		UInt32 dataSize = 0;        // 13517289 GetPropetyInfo was returning an uninitialized value when there is an error. This is a problem for auval.
+		Boolean writable = false;
+		
+		AUI_LOCK
+		result = AUI->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
+		if (outDataSize != NULL)
+			*outDataSize = dataSize;
+		if (outWritable != NULL)
+			*outWritable = writable;
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodGetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize)
+{
+	OSStatus result = noErr;
+	try {
+		UInt32 actualPropertySize, clientBufferSize;
+		Boolean writable;
+		char *tempBuffer;
+		void *destBuffer;
+		
+		AUI_LOCK
+		if (ioDataSize == NULL) {
+			ca_debug_string("AudioUnitGetProperty: null size pointer");
+			result = kAudio_ParamError;
+			goto finishGetProperty;
+		}
+		if (outData == NULL) {
+			UInt32 dataSize;
+			
+			result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, dataSize, writable);
+			*ioDataSize = dataSize;
+			goto finishGetProperty;
+		}
+		
+		clientBufferSize = *ioDataSize;
+		if (clientBufferSize == 0)
+		{
+			ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
+			// $$$ or should we allow this as a shortcut for finding the size?
+			result = kAudio_ParamError;
+			goto finishGetProperty;
+		}
+		
+		result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, actualPropertySize, writable);
+		if (result != noErr) 
+			goto finishGetProperty;
+		
+		if (clientBufferSize < actualPropertySize) 
+		{
+			tempBuffer = new char[actualPropertySize];
+			destBuffer = tempBuffer;
+		} else {
+			tempBuffer = NULL;
+			destBuffer = outData;
+		}
+		
+		result = AUI->DispatchGetProperty(inID, inScope, inElement, destBuffer);
+		
+		if (result == noErr) {
+			if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
+			{
+				memcpy(outData, tempBuffer, clientBufferSize);
+				delete[] tempBuffer;
+				// ioDataSize remains correct, the number of bytes we wrote
+			} else
+				*ioDataSize = actualPropertySize;
+		} else
+			*ioDataSize = 0;
+	}
+	COMPONENT_CATCH
+finishGetProperty:
+	return result;
+}
+
+static OSStatus AUMethodSetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		if (inData && inDataSize)
+			result = AUI->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
+		else {
+			if (inData == NULL && inDataSize == 0) {
+				result = AUI->DispatchRemovePropertyValue(inID, inScope, inElement);
+			} else {
+				if (inData == NULL) {
+					ca_debug_string("AudioUnitSetProperty: inData == NULL");
+					result = kAudio_ParamError;
+					goto finishSetProperty;
+				}
+
+				if (inDataSize == 0) {
+					ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
+					result = kAudio_ParamError;
+					goto finishSetProperty;
+				}
+			}
+		}
+	}
+	COMPONENT_CATCH
+finishSetProperty:
+	return result;
+}
+
+static OSStatus AUMethodAddPropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->AddPropertyListener(prop, proc, userData);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodRemovePropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->RemovePropertyListener(prop, proc, NULL, false);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodRemovePropertyListenerWithUserData(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->RemovePropertyListener(prop, proc, userData, true);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodAddRenderNotify(void *self, AURenderCallback proc, void *userData)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->SetRenderNotification(proc, userData);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodRemoveRenderNotify(void *self, AURenderCallback proc, void *userData)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->RemoveRenderNotification(proc, userData);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodGetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = (value == NULL ? kAudio_ParamError : AUI->GetParameter(param, scope, elem, *value));
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodSetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a (potentially) realtime method; no lock
+		result = AUI->SetParameter(param, scope, elem, value, bufferOffset);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodScheduleParameters(void *self, const AudioUnitParameterEvent *events, UInt32 numEvents)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a (potentially) realtime method; no lock
+		result = AUI->ScheduleParameter(events, numEvents);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+	OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+	try {
+#endif
+		// this is a processing method; no lock
+		AudioUnitRenderActionFlags tempFlags;
+		
+		if (inTimeStamp == NULL || ioData == NULL)
+			result = kAudio_ParamError;
+		else {
+			if (ioActionFlags == NULL) {
+				tempFlags = 0;
+				ioActionFlags = &tempFlags;
+			}
+			result = AUI->DoRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
+		}
+
+#if !TARGET_OS_IPHONE
+	}
+	COMPONENT_CATCH
+#endif
+
+	return result;
+}
+
+static OSStatus AUMethodComplexRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets, UInt32 *outNumberOfPackets, AudioStreamPacketDescription *outPacketDescriptions, AudioBufferList *ioData, void *outMetadata, UInt32 *outMetadataByteSize)
+{
+	OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+	try {
+#endif
+		// this is a processing method; no lock
+		AudioUnitRenderActionFlags tempFlags;
+		
+		if (inTimeStamp == NULL || ioData == NULL)
+			result = kAudio_ParamError;
+		else {
+			if (ioActionFlags == NULL) {
+				tempFlags = 0;
+				ioActionFlags = &tempFlags;
+			}
+			result = AUI->ComplexRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, *ioData, outMetadata, outMetadataByteSize);
+		}
+
+#if !TARGET_OS_IPHONE
+	}
+	COMPONENT_CATCH
+#endif
+
+	return result;
+}
+
+static OSStatus AUMethodReset(void *self, AudioUnitScope scope, AudioUnitElement elem)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->Reset(scope, elem);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodProcess (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+	OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+	try {
+#endif
+		// this is a processing method; no lock
+		bool doParamCheck = true;
+
+		AudioUnitRenderActionFlags tempFlags;
+
+		if (ioActionFlags == NULL) {
+			tempFlags = 0;
+			ioActionFlags = &tempFlags;
+		} else {
+			if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
+				doParamCheck = false;
+		}
+		
+		if (doParamCheck && (inTimeStamp == NULL || ioData == NULL))
+			result = kAudio_ParamError;
+		else {
+			result = AUI->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
+		}
+
+#if !TARGET_OS_IPHONE
+	}
+	COMPONENT_CATCH
+#endif
+
+	return result;
+}
+
+static OSStatus AUMethodProcessMultiple (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists, const AudioBufferList **inInputBufferLists, UInt32 inNumberOutputBufferLists, AudioBufferList **ioOutputBufferLists)
+{
+	OSStatus result = noErr;
+	
+#if !TARGET_OS_IPHONE
+	try {
+#endif
+		// this is a processing method; no lock
+		bool doParamCheck = true;
+		
+		AudioUnitRenderActionFlags tempFlags;
+		
+		if (ioActionFlags == NULL) {
+			tempFlags = 0;
+			ioActionFlags = &tempFlags;
+		} else {
+			if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
+				doParamCheck = false;
+		}
+
+		if (doParamCheck && (inTimeStamp == NULL || inInputBufferLists == NULL || ioOutputBufferLists == NULL))
+			result = kAudio_ParamError;
+		else {
+			result = AUI->DoProcessMultiple(*ioActionFlags, *inTimeStamp, inNumberFrames, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+		}
+		
+#if !TARGET_OS_IPHONE
+	}
+	COMPONENT_CATCH
+#endif
+
+	return result;
+}
+// ------------------------------------------------------------------------------------------------
+
+static OSStatus AUMethodStart(void *self)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->Start();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodStop(void *self)
+{
+	OSStatus result = noErr;
+	try {
+		AUI_LOCK
+		result = AUI->Stop();
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+#if !CA_BASIC_AU_FEATURES
+// I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
+static OSStatus AUMethodMIDIEvent(void *self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a potential render-time method; no lock
+		result = AUI->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodSysEx(void *self, const UInt8 *inData, UInt32 inLength)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a potential render-time method; no lock
+		result = AUI->SysEx(inData, inLength);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodStartNote(void *self, MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a potential render-time method; no lock
+		if (inParams == NULL || outNoteInstanceID == NULL) 
+			result = kAudio_ParamError;
+		else
+			result = AUI->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodStopNote(void *self, MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a potential render-time method; no lock
+		result = AUI->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+#if !TARGET_OS_IPHONE
+static OSStatus AUMethodPrepareInstrument (void *self, MusicDeviceInstrumentID inInstrument)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a potential render-time method; no lock
+		result = AUI->PrepareInstrument(inInstrument);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+static OSStatus AUMethodReleaseInstrument (void *self, MusicDeviceInstrumentID inInstrument)
+{
+	OSStatus result = noErr;
+	try {
+		// this is a potential render-time method; no lock
+		result = AUI->ReleaseInstrument(inInstrument);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+#endif // TARGET_OS_IPHONE
+#endif // CA_BASIC_AU_FEATURES
+
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#pragma mark -
+#pragma mark Lookup Methods
+
+AudioComponentMethod AUBaseLookup::Lookup (SInt16 selector)
+{
+	switch (selector) {
+		case kAudioUnitInitializeSelect:		return (AudioComponentMethod)AUMethodInitialize;
+		case kAudioUnitUninitializeSelect:		return (AudioComponentMethod)AUMethodUninitialize;
+		case kAudioUnitGetPropertyInfoSelect:	return (AudioComponentMethod)AUMethodGetPropertyInfo;
+		case kAudioUnitGetPropertySelect:		return (AudioComponentMethod)AUMethodGetProperty;
+		case kAudioUnitSetPropertySelect:		return (AudioComponentMethod)AUMethodSetProperty;
+		case kAudioUnitAddPropertyListenerSelect:return (AudioComponentMethod)AUMethodAddPropertyListener;
+		case kAudioUnitRemovePropertyListenerSelect:
+												return (AudioComponentMethod)AUMethodRemovePropertyListener;
+		case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+												return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData;
+		case kAudioUnitAddRenderNotifySelect:	return (AudioComponentMethod)AUMethodAddRenderNotify;
+		case kAudioUnitRemoveRenderNotifySelect:return (AudioComponentMethod)AUMethodRemoveRenderNotify;
+		case kAudioUnitGetParameterSelect:		return (AudioComponentMethod)AUMethodGetParameter;
+		case kAudioUnitSetParameterSelect:		return (AudioComponentMethod)AUMethodSetParameter;
+		case kAudioUnitScheduleParametersSelect:return (AudioComponentMethod)AUMethodScheduleParameters;
+		case kAudioUnitRenderSelect:			return (AudioComponentMethod)AUMethodRender;
+		case kAudioUnitResetSelect:				return (AudioComponentMethod)AUMethodReset;
+		default:
+			break;
+	}
+	return NULL;
+}
+
+AudioComponentMethod AUOutputLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+	if (method) return method;
+
+	switch (selector) {
+		case kAudioOutputUnitStartSelect:	return (AudioComponentMethod)AUMethodStart;
+		case kAudioOutputUnitStopSelect:	return (AudioComponentMethod)AUMethodStop;
+		default:
+			break;
+	}
+	return NULL;
+}
+
+AudioComponentMethod AUComplexOutputLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+	if (method) return method;
+	
+	method = AUOutputLookup::Lookup(selector);
+	if (method) return method;
+	
+	if (selector == kAudioUnitComplexRenderSelect)
+		return (AudioComponentMethod)AUMethodComplexRender;
+	return NULL;
+}
+
+AudioComponentMethod AUBaseProcessLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+	if (method) return method;
+	
+	if (selector == kAudioUnitProcessSelect)
+		return (AudioComponentMethod)AUMethodProcess;
+	
+	return NULL;
+}
+
+AudioComponentMethod AUBaseProcessMultipleLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+	if (method) return method;
+    
+	if (selector == kAudioUnitProcessMultipleSelect)
+		return (AudioComponentMethod)AUMethodProcessMultiple;
+	
+	return NULL;
+}
+
+AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+	if (method) return method;
+
+	method = AUBaseProcessMultipleLookup::Lookup(selector);
+	if (method) return method;
+    
+	method = AUBaseProcessLookup::Lookup(selector);
+	if (method) return method;
+
+	return NULL;
+}
+
+#if !CA_BASIC_AU_FEATURES
+inline AudioComponentMethod MIDI_Lookup (SInt16 selector)
+{
+	switch (selector) {
+		case kMusicDeviceMIDIEventSelect:	return (AudioComponentMethod)AUMethodMIDIEvent;
+		case kMusicDeviceSysExSelect:		return (AudioComponentMethod)AUMethodSysEx;
+		default:
+			break;
+	}
+	return NULL;
+}
+
+AudioComponentMethod AUMIDILookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+	if (method) return method;
+	
+	return MIDI_Lookup(selector);
+}
+
+AudioComponentMethod AUMIDIProcessLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
+	if (method) return method;
+	
+	return MIDI_Lookup(selector);
+}
+
+AudioComponentMethod AUMusicLookup::Lookup (SInt16 selector)
+{
+	AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+	if (method) return method;
+
+	switch (selector) {
+		case kMusicDeviceStartNoteSelect:	return (AudioComponentMethod)AUMethodStartNote;
+		case kMusicDeviceStopNoteSelect:	return (AudioComponentMethod)AUMethodStopNote;
+#if !TARGET_OS_IPHONE
+		case kMusicDevicePrepareInstrumentSelect:	return (AudioComponentMethod)AUMethodPrepareInstrument;
+		case kMusicDeviceReleaseInstrumentSelect:	return (AudioComponentMethod)AUMethodReleaseInstrument;
+#endif
+		default:		
+			break;
+	}
+	return MIDI_Lookup (selector);
+}
+
+AudioComponentMethod AUAuxBaseLookup::Lookup (SInt16 selector)
+{
+	switch (selector) {
+		case kAudioUnitGetPropertyInfoSelect:	return (AudioComponentMethod)AUMethodGetPropertyInfo;
+		case kAudioUnitGetPropertySelect:		return (AudioComponentMethod)AUMethodGetProperty;
+		case kAudioUnitSetPropertySelect:		return (AudioComponentMethod)AUMethodSetProperty;
+            
+		case kAudioUnitGetParameterSelect:		return (AudioComponentMethod)AUMethodGetParameter;
+		case kAudioUnitSetParameterSelect:		return (AudioComponentMethod)AUMethodSetParameter;
+            
+		default:
+			break;
+	}
+	return NULL;
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h
new file mode 100644
index 0000000..6ebea75
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h
@@ -0,0 +1,144 @@
+/*
+     File: AUPlugInDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUPlugInBase_h__
+#define __AUPlugInBase_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioComponent.h>
+	#if !CA_BASIC_AU_FEATURES
+		#include <AudioUnit/MusicDevice.h>
+	#endif
+#else
+	#include "AudioComponent.h"
+	#include "MusicDevice.h"
+#endif
+
+#include "ComponentBase.h"
+
+struct AUBaseLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseFactory : public APFactory<AUBaseLookup, Implementor>
+{
+};
+
+struct AUOutputLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUOutputBaseFactory : public APFactory<AUOutputLookup, Implementor>
+{
+};
+
+struct AUComplexOutputLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUOutputComplexBaseFactory : public APFactory<AUComplexOutputLookup, Implementor>
+{
+};
+
+struct AUBaseProcessLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessFactory : public APFactory<AUBaseProcessLookup, Implementor>
+{
+};
+
+struct AUBaseProcessMultipleLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessMultipleFactory : public APFactory<AUBaseProcessMultipleLookup, Implementor>
+{
+};
+
+struct AUBaseProcessAndMultipleLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessAndMultipleFactory : public APFactory<AUBaseProcessAndMultipleLookup, Implementor>
+{
+};
+
+#if !CA_BASIC_AU_FEATURES
+struct AUMIDILookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMIDIEffectFactory : public APFactory<AUMIDILookup, Implementor>
+{
+};
+
+struct AUMIDIProcessLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMIDIProcessFactory : public APFactory<AUMIDIProcessLookup, Implementor>
+{
+};
+
+struct AUMusicLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMusicDeviceFactory : public APFactory<AUMusicLookup, Implementor>
+{
+};
+
+struct AUAuxBaseLookup {
+	static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUAuxBaseFactory : public APFactory<AUAuxBaseLookup, Implementor>
+{
+};
+#endif // CA_BASIC_AU_FEATURES
+
+#endif // __AUPlugInBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r
new file mode 100644
index 0000000..55040fc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r
@@ -0,0 +1,140 @@
+/*
+     File: AUResources.r
+ Abstract: AUResources.r
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//	AUResources.r
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* sample macro definitions -- all of these symbols must be defined
+#define RES_ID			kHALOutputResID
+#define COMP_TYPE		kAudioUnitComponentType
+#define COMP_SUBTYPE	kAudioUnitOutputSubType
+#define COMP_MANUF		kAudioUnitAudioHardwareOutputSubSubType
+#define VERSION			0x00010000
+#define NAME			"AudioHALOutput"
+#define DESCRIPTION		"Audio hardware output AudioUnit"
+#define ENTRY_POINT		"AUHALEntry"
+*/
+#define UseExtendedThingResource 1
+
+#include <CoreServices/CoreServices.r>
+
+// this is a define used to indicate that a component has no static data that would mean 
+// that no more than one instance could be open at a time - never been true for AUs
+#ifndef cmpThreadSafeOnMac
+#define cmpThreadSafeOnMac	0x10000000
+#endif
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'STR ' (RES_ID, purgeable) {
+	NAME
+};
+
+resource 'STR ' (RES_ID + 1, purgeable) {
+	DESCRIPTION
+};
+
+resource 'dlle' (RES_ID) {
+	ENTRY_POINT
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'thng' (RES_ID, NAME) {
+	COMP_TYPE,
+	COMP_SUBTYPE,
+	COMP_MANUF,
+	0, 0, 0, 0,								//	no 68K
+	'STR ',	RES_ID,
+	'STR ',	RES_ID + 1,
+	0,	0,			/* icon */
+	VERSION,
+	componentHasMultiplePlatforms | componentDoAutoVersion,
+	0,
+	{
+	#if defined(ppc_YES)
+			cmpThreadSafeOnMac,
+			'dlle', RES_ID, platformPowerPCNativeEntryPoint
+			#define NeedLeadingComma 1
+	#endif
+	#if defined(ppc64_YES)
+		#if defined(NeedLeadingComma)
+			,
+		#endif
+			cmpThreadSafeOnMac,
+			'dlle', RES_ID, platformPowerPC64NativeEntryPoint
+			#define NeedLeadingComma 1
+	#endif
+	#if defined(i386_YES)
+		#if defined(NeedLeadingComma)
+			,
+		#endif
+			cmpThreadSafeOnMac,
+			'dlle', RES_ID, platformIA32NativeEntryPoint
+			#define NeedLeadingComma 1
+	#endif
+	#if defined(x86_64_YES)
+		#if defined(NeedLeadingComma)
+			,
+		#endif
+			cmpThreadSafeOnMac,
+			'dlle', RES_ID, 8
+			#define NeedLeadingComma 1
+	#endif
+	}
+};
+
+#undef RES_ID
+#undef COMP_TYPE
+#undef COMP_SUBTYPE
+#undef COMP_MANUF
+#undef VERSION
+#undef NAME
+#undef DESCRIPTION
+#undef ENTRY_POINT
+#undef NeedLeadingComma
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
new file mode 100644
index 0000000..24bd18e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
@@ -0,0 +1,565 @@
+/*
+     File: AUScopeElement.cpp
+ Abstract: AUScopeElement.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUScopeElement.h"
+#include "AUBase.h"
+
+//_____________________________________________________________________________
+//
+//	By default, parameterIDs may be arbitrarily spaced, and an STL map
+//  will be used for access.  Calling UseIndexedParameters() will
+//	instead use an STL vector for faster indexed access.
+//	This assumes the paramIDs are numbered 0.....inNumberOfParameters-1
+//	Call this before defining/adding any parameters with SetParameter()
+//
+void	AUElement::UseIndexedParameters(int inNumberOfParameters)
+{
+	mIndexedParameters.resize (inNumberOfParameters);	
+	mUseIndexedParameters = true;
+}
+
+//_____________________________________________________________________________
+//
+//	Helper method.
+//	returns the ParameterMapEvent object associated with the paramID
+//
+inline ParameterMapEvent&	AUElement::GetParamEvent(AudioUnitParameterID paramID)
+{
+	ParameterMapEvent *event;
+	
+	if(mUseIndexedParameters)
+	{
+		if(paramID >= mIndexedParameters.size() )
+			COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+		
+		event = &mIndexedParameters[paramID];
+	}
+	else
+	{
+		ParameterMap::iterator i = mParameters.find(paramID);
+		if (i == mParameters.end())
+			COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+			
+		event = &(*i).second;
+	}
+	
+	return *event;
+}
+
+//_____________________________________________________________________________
+//
+//	Helper method.
+//	returns whether the specified paramID is known to the element
+//
+bool		AUElement::HasParameterID (AudioUnitParameterID paramID) const
+{	
+	if(mUseIndexedParameters)
+	{
+		if(paramID >= mIndexedParameters.size() )
+			return false;
+		
+		return true;
+	}
+	
+	ParameterMap::const_iterator i = mParameters.find(paramID);
+	if (i == mParameters.end())
+		return false;
+		
+	return true;
+}
+
+//_____________________________________________________________________________
+//
+//	caller assumes that this is actually an immediate parameter
+//
+AudioUnitParameterValue		AUElement::GetParameter(AudioUnitParameterID paramID)
+{
+	ParameterMapEvent &event = GetParamEvent(paramID);
+	
+	return event.GetValue();
+}
+
+
+//_____________________________________________________________________________
+//
+void			AUElement::GetRampSliceStartEnd(	AudioUnitParameterID		paramID,
+													AudioUnitParameterValue &	outStartValue,
+													AudioUnitParameterValue &	outEndValue,
+													AudioUnitParameterValue &	outValuePerFrameDelta )
+
+{
+	ParameterMapEvent &event = GetParamEvent(paramID);
+		
+	// works even if the value is constant (immediate parameter value)
+	event.GetRampSliceStartEnd(outStartValue, outEndValue, outValuePerFrameDelta );
+}
+
+//_____________________________________________________________________________
+//
+AudioUnitParameterValue			AUElement::GetEndValue(	AudioUnitParameterID		paramID)
+
+{
+	ParameterMapEvent &event = GetParamEvent(paramID);
+		
+	// works even if the value is constant (immediate parameter value)
+	return event.GetEndValue();
+}
+
+//_____________________________________________________________________________
+//
+void			AUElement::SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized)
+{
+	if(mUseIndexedParameters)
+	{
+		ParameterMapEvent &event = GetParamEvent(paramID);
+		event.SetValue(inValue);
+	}
+	else
+	{
+		ParameterMap::iterator i = mParameters.find(paramID);
+	
+		if (i == mParameters.end())
+		{
+			if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
+				// The AU should not be creating new parameters once initialized.
+				// If a client tries to set an undefined parameter, we could throw as follows, 
+				// but this might cause a regression. So it is better to just fail silently.
+				// COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+#if DEBUG
+				fprintf(stderr, "WARNING: %s SetParameter for undefined param ID %d while initialized. Ignoring..\n", 
+								mAudioUnit->GetLoggingString(), (int)paramID);
+#endif
+			} else {
+				// create new entry in map for the paramID (only happens first time)
+				ParameterMapEvent event(inValue);		
+				mParameters[paramID] = event;
+			}
+		}
+		else
+		{
+			// paramID already exists in map so simply change its value
+			ParameterMapEvent &event = (*i).second;
+			event.SetValue(inValue);
+		}
+	}
+}
+
+//_____________________________________________________________________________
+//
+void			AUElement::SetScheduledEvent(	AudioUnitParameterID 			paramID,
+												const AudioUnitParameterEvent 	&inEvent,
+												UInt32 							inSliceOffsetInBuffer,
+												UInt32							inSliceDurationFrames,
+												bool							okWhenInitialized )
+{
+	if(mUseIndexedParameters)
+	{
+		ParameterMapEvent &event = GetParamEvent(paramID);
+		event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+	}
+	else
+	{
+		ParameterMap::iterator i = mParameters.find(paramID);
+	
+		if (i == mParameters.end())
+		{
+			if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
+				// The AU should not be creating new parameters once initialized.
+				// If a client tries to set an undefined parameter, we could throw as follows, 
+				// but this might cause a regression. So it is better to just fail silently.
+				// COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+#if DEBUG
+				fprintf(stderr, "WARNING: %s SetScheduledEvent for undefined param ID %d while initialized. Ignoring..\n", 
+								mAudioUnit->GetLoggingString(), (int)paramID);
+#endif
+			} else {
+				// create new entry in map for the paramID (only happens first time)
+				ParameterMapEvent event(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames);		
+				mParameters[paramID] = event;
+			}
+		}
+		else
+		{
+			// paramID already exists in map so simply change its value
+			ParameterMapEvent &event = (*i).second;
+			
+			event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+		}
+	}
+}
+
+
+
+//_____________________________________________________________________________
+//
+void			AUElement::GetParameterList(AudioUnitParameterID *outList)
+{
+	if(mUseIndexedParameters)
+	{
+		UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
+		for (UInt32 i = 0; i < nparams; i++ )
+			*outList++ = (AudioUnitParameterID)i;
+	}
+	else
+	{
+		for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i)
+			*outList++ = (*i).first;
+	}
+}
+
+//_____________________________________________________________________________
+//
+void			AUElement::SaveState(CFMutableDataRef data)
+{
+	if(mUseIndexedParameters)
+	{
+		UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
+		UInt32 theData = CFSwapInt32HostToBig(nparams);
+		CFDataAppendBytes(data, (UInt8 *)&theData, sizeof(nparams));
+	
+		for (UInt32 i = 0; i < nparams; i++)
+		{
+			struct {
+				UInt32				paramID;
+				//CFSwappedFloat32	value; crashes gcc3 PFE
+				UInt32				value;	// really a big-endian float
+			} entry;
+			
+			entry.paramID = CFSwapInt32HostToBig(i);
+	
+			AudioUnitParameterValue v = mIndexedParameters[i].GetValue();
+			entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
+	
+			CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
+		}
+	}
+	else
+	{
+		UInt32 nparams = CFSwapInt32HostToBig(static_cast<uint32_t>(mParameters.size()));
+		CFDataAppendBytes(data, (UInt8 *)&nparams, sizeof(nparams));
+	
+		for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i) {
+			struct {
+				UInt32				paramID;
+				//CFSwappedFloat32	value; crashes gcc3 PFE
+				UInt32				value;	// really a big-endian float
+			} entry;
+			
+			entry.paramID = CFSwapInt32HostToBig((*i).first);
+	
+			AudioUnitParameterValue v = (*i).second.GetValue();
+			entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
+	
+			CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
+		}
+	}
+}
+
+//_____________________________________________________________________________
+//
+const UInt8 *	AUElement::RestoreState(const UInt8 *state)
+{
+	union FloatInt32 { UInt32 i; AudioUnitParameterValue f; };
+	const UInt8 *p = state;
+	UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
+	p += sizeof(UInt32);
+	
+	for (UInt32 i = 0; i < nparams; ++i) {
+		struct {
+			AudioUnitParameterID		paramID;
+			AudioUnitParameterValue		value;
+		} entry;
+		
+		entry.paramID = CFSwapInt32BigToHost(*(UInt32 *)p);
+		p += sizeof(UInt32);
+		FloatInt32 temp;
+		temp.i = CFSwapInt32BigToHost(*(UInt32 *)p);
+		entry.value = temp.f;
+		p += sizeof(AudioUnitParameterValue);
+		
+		SetParameter(entry.paramID, entry.value);
+	}
+	return p;
+}
+
+//_____________________________________________________________________________
+//
+void	AUElement::SetName (CFStringRef inName) 
+{ 
+	if (mElementName) CFRelease (mElementName);
+	mElementName = inName; 
+	if (mElementName) CFRetain (mElementName);
+}
+
+
+//_____________________________________________________________________________
+//
+AUIOElement::AUIOElement(AUBase *audioUnit) :
+	AUElement(audioUnit),
+	mWillAllocate (true)
+{
+	mStreamFormat.SetAUCanonical(2,	// stereo
+		audioUnit->AudioUnitAPIVersion() == 1);
+		// interleaved if API version 1, deinterleaved if version 2
+	mStreamFormat.mSampleRate = kAUDefaultSampleRate;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus		AUIOElement::SetStreamFormat(const CAStreamBasicDescription &desc)
+{
+	mStreamFormat = desc;
+	return AUBase::noErr;
+}
+
+//_____________________________________________________________________________
+// inFramesToAllocate == 0 implies the AudioUnit's max-frames-per-slice will be used
+void			AUIOElement::AllocateBuffer(UInt32 inFramesToAllocate)
+{
+	if (GetAudioUnit()->HasBegunInitializing())
+	{
+		UInt32 framesToAllocate = inFramesToAllocate > 0 ? inFramesToAllocate : GetAudioUnit()->GetMaxFramesPerSlice();
+		
+//		printf ("will allocate: %d\n", (int)((mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0));
+		
+		mIOBuffer.Allocate(mStreamFormat, (mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0);
+	}
+}
+
+//_____________________________________________________________________________
+//
+void			AUIOElement::DeallocateBuffer()
+{
+	mIOBuffer.Deallocate();
+}
+
+//_____________________________________________________________________________
+//
+//		AudioChannelLayout support
+
+// outLayoutTagsPtr WILL be NULL if called to find out how many
+// layouts that Audio Unit will report 
+// return 0 (ie. NO channel layouts) if the AU doesn't require channel layout knowledge
+UInt32		AUIOElement::GetChannelLayoutTags (AudioChannelLayoutTag		*outLayoutTagsPtr)
+{
+	return 0;
+}
+		
+// As the AudioChannelLayout can be a variable length structure 
+// (though in most cases it won't be!!!)
+// The size of the ACL is always returned by the method
+// if outMapPtr is NOT-NULL, then AU should copy into this pointer (outMapPtr) the current ACL that it has in use. 
+// the AU should also return whether the property is writable (that is the client can provide any arbitrary ACL that the audio unit will then honour)
+// or if the property is read only - which is the generally preferred mode.
+// If the AU doesn't require an AudioChannelLayout, then just return 0.
+UInt32		AUIOElement::GetAudioChannelLayout (AudioChannelLayout		*outMapPtr, 
+											Boolean				&outWritable)
+{
+	return 0;
+}
+
+// the incoming channel map will be at least as big as a basic AudioChannelLayout
+// but its contents will determine its actual size
+// Subclass should overide if channel map is writable
+OSStatus	AUIOElement::SetAudioChannelLayout (const AudioChannelLayout &inData)
+{
+	return kAudioUnitErr_InvalidProperty;
+}
+
+// Some units support optional usage of channel maps - typically converter units
+// that can do channel remapping between different maps. In that optional case
+// the user should be able to remove a channel map if that is possible.
+// Typically this is NOT the case (e.g., the 3DMixer even in the stereo case
+// needs to know if it is rendering to speakers or headphones)
+OSStatus	AUIOElement::RemoveAudioChannelLayout ()
+{
+	return kAudioUnitErr_InvalidPropertyValue;
+}
+
+
+//_____________________________________________________________________________
+//
+AUScope::~AUScope()
+{
+	for (ElementVector::iterator it = mElements.begin(); it != mElements.end(); ++it)
+		delete *it;
+}
+
+//_____________________________________________________________________________
+//
+void	AUScope::SetNumberOfElements(UInt32 numElements)
+{
+	if (mDelegate)
+		return mDelegate->SetNumberOfElements(numElements);
+
+	if (numElements > mElements.size()) {
+		mElements.reserve(numElements);
+		while (numElements > mElements.size()) {
+			AUElement *elem = mCreator->CreateElement(GetScope(), static_cast<UInt32>(mElements.size()));
+			mElements.push_back(elem);
+		}
+	} else
+		while (numElements < mElements.size()) {
+			AUElement *elem = mElements.back();
+			mElements.pop_back();
+			delete elem;
+		}
+}
+
+//_____________________________________________________________________________
+//
+bool	AUScope::HasElementWithName () const
+{
+	for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+		AUElement *	el = const_cast<AUScope*>(this)->GetElement (i);
+		if (el && el->HasName()) {
+			return true;
+		}
+	}
+	return false;
+}
+
+//_____________________________________________________________________________
+//
+
+void	AUScope::AddElementNamesToDict (CFMutableDictionaryRef & inNameDict)
+{
+	if (HasElementWithName())
+	{
+		static char string[32];
+		CFMutableDictionaryRef elementDict = CFDictionaryCreateMutable	(NULL, 0,
+								&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+		CFStringRef str;
+		for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+			AUElement *	el = GetElement (i);
+			if (el && el->HasName()) {
+				snprintf (string, sizeof(string), "%d", int(i));
+				str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+				CFDictionarySetValue (elementDict, str, el->GetName());
+				CFRelease (str);
+			}
+		}
+
+		snprintf (string, sizeof(string), "%d", int(mScope));
+		str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+		CFDictionarySetValue (inNameDict, str, elementDict);
+		CFRelease (str);
+		CFRelease (elementDict);
+	}
+}
+
+//_____________________________________________________________________________
+//
+bool	AUScope::RestoreElementNames (CFDictionaryRef& inNameDict)
+{
+	static char string[32];
+
+	//first we have to see if we have enough elements
+	bool didAddElements = false;
+	unsigned int maxElNum = GetNumberOfElements();
+	
+	int dictSize = static_cast<int>(CFDictionaryGetCount(inNameDict));
+	CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef));
+	CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast<const void**>(keys), NULL);
+	for (int i = 0; i < dictSize; i++)
+	{
+		unsigned int intKey = 0;
+		CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
+		int result = sscanf (string, "%u", &intKey);
+        // check if sscanf succeeded and element index is less than max elements.
+		if (result && UInt32(intKey) < maxElNum)
+        {
+            CFStringRef elName = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (inNameDict,  keys[i]));
+            AUElement* element = GetElement (intKey);
+            if (element)
+                element->SetName (elName);
+        }
+	}
+	free (keys);
+	
+	return didAddElements;
+}
+
+void    AUScope::SaveState(CFMutableDataRef data)
+{
+    AudioUnitElement nElems = GetNumberOfElements();
+    for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
+        AUElement *element = GetElement(ielem);
+        UInt32 nparams = element->GetNumberOfParameters();
+        if (nparams > 0) {
+            struct {
+                UInt32	scope;
+                UInt32	element;
+            } hdr;
+            
+            hdr.scope = CFSwapInt32HostToBig(GetScope());
+            hdr.element = CFSwapInt32HostToBig(ielem);
+            CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
+            
+            element->SaveState(data);
+        }
+    }
+}
+
+const UInt8 *	AUScope::RestoreState(const UInt8 *state)
+{
+    const UInt8 *p = state;
+    UInt32 elementIdx = CFSwapInt32BigToHost(*(UInt32 *)p);	p += sizeof(UInt32);
+    AUElement *element = GetElement(elementIdx);
+    if (!element) {
+        struct {
+            AudioUnitParameterID		paramID;
+            AudioUnitParameterValue		value;
+        } entry;
+        UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
+        p += sizeof(UInt32);
+        
+        p += nparams * sizeof(entry);
+    } else
+        p = element->RestoreState(p);
+    
+    return p;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h
new file mode 100644
index 0000000..47ebe2f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h
@@ -0,0 +1,553 @@
+/*
+     File: AUScopeElement.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUScopeElement_h__
+#define __AUScopeElement_h__
+
+#include <map>
+#include <vector>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioUnit.h>
+#else
+	#include <AudioUnit.h>
+#endif
+#include "ComponentBase.h"
+#include "AUBuffer.h"
+
+
+class AUBase;
+
+// ____________________________________________________________________________
+//
+// represents a parameter's value (either constant or ramped)
+/*! @class ParameterMapEvent */
+class ParameterMapEvent
+{
+public:
+/*! @ctor ParameterMapEvent */
+	ParameterMapEvent() 
+		: mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0f), mValue2(0.0f), mSliceDurationFrames(0) 
+		{}
+
+/*! @ctor ParameterMapEvent */
+	ParameterMapEvent(AudioUnitParameterValue inValue)
+		: mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(inValue), mValue2(inValue), mSliceDurationFrames(0) 
+		{}
+		
+	// constructor for scheduled event
+/*! @ctor ParameterMapEvent */
+	ParameterMapEvent(	const AudioUnitParameterEvent 	&inEvent,
+						UInt32 							inSliceOffsetInBuffer,
+						UInt32							inSliceDurationFrames )
+	{
+		SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+	};
+	
+/*! @method SetScheduledEvent */
+	void SetScheduledEvent(	const AudioUnitParameterEvent 	&inEvent,
+							UInt32 							inSliceOffsetInBuffer,
+							UInt32							inSliceDurationFrames )
+	{
+		mEventType = inEvent.eventType;
+		mSliceDurationFrames = inSliceDurationFrames;
+		
+		if(mEventType == kParameterEvent_Immediate )
+		{
+			// constant immediate value for the whole slice
+			mValue1 = inEvent.eventValues.immediate.value;
+			mValue2 = mValue1;
+			mDurationInFrames = inSliceDurationFrames;
+			mBufferOffset = 0;
+		}
+		else
+		{
+			mDurationInFrames 	= 	inEvent.eventValues.ramp.durationInFrames;
+			mBufferOffset 		= 	inEvent.eventValues.ramp.startBufferOffset - inSliceOffsetInBuffer;	// shift over for this slice
+			mValue1 			= 	inEvent.eventValues.ramp.startValue;
+			mValue2 			= 	inEvent.eventValues.ramp.endValue;
+		}
+	};
+	
+	
+	
+/*! @method GetEventType */
+	AUParameterEventType		GetEventType() const {return mEventType;};
+
+/*! @method GetValue */
+	AudioUnitParameterValue		GetValue() const {return mValue1;};	// only valid if immediate event type
+/*! @method GetEndValue */
+	AudioUnitParameterValue		GetEndValue() const {return mValue2;};	// only valid if immediate event type
+/*! @method SetValue */
+	void						SetValue(AudioUnitParameterValue inValue) 
+								{
+									mEventType = kParameterEvent_Immediate; 
+									mValue1 = inValue; 
+									mValue2 = inValue;
+								}
+	
+	// interpolates the start and end values corresponding to the current processing slice
+	// most ramp parameter implementations will want to use this method
+	// the start value will correspond to the start of the slice
+	// the end value will correspond to the end of the slice
+/*! @method GetRampSliceStartEnd */
+	void					GetRampSliceStartEnd(	AudioUnitParameterValue &	outStartValue,
+													AudioUnitParameterValue &	outEndValue,
+													AudioUnitParameterValue &	outValuePerFrameDelta )
+	{
+		if (mEventType == kParameterEvent_Ramped) {
+			outValuePerFrameDelta = (mValue2 - mValue1) / mDurationInFrames;
+		
+			outStartValue = mValue1 + outValuePerFrameDelta * (-mBufferOffset);	// corresponds to frame 0 of this slice
+			outEndValue = outStartValue +  outValuePerFrameDelta * mSliceDurationFrames;
+		} else {
+			outValuePerFrameDelta = 0;
+			outStartValue = outEndValue = mValue1;
+		}
+	};
+
+	// Some ramp parameter implementations will want to interpret the ramp using their
+	// own interpolation method (perhaps non-linear)
+	// This method gives the raw ramp information, relative to this processing slice
+	// for the client to interpret as desired
+/*! @method GetRampInfo */
+	void					GetRampInfo(	SInt32 	&					outBufferOffset,
+											UInt32 	&					outDurationInFrames,
+											AudioUnitParameterValue &	outStartValue,
+											AudioUnitParameterValue &	outEndValue )
+	{
+		outBufferOffset = mBufferOffset;
+		outDurationInFrames = mDurationInFrames;
+		outStartValue = mValue1;
+		outEndValue = mValue2;
+	};
+
+#if DEBUG
+	void					Print()
+	{
+		printf("ParameterEvent @ %p\n", this);
+		printf("	mEventType = %d\n", (int)mEventType);
+		printf("	mBufferOffset = %d\n", (int)mBufferOffset);
+		printf("	mDurationInFrames = %d\n", (int)mDurationInFrames);
+		printf("	mSliceDurationFrames = %d\n", (int)mSliceDurationFrames);
+		printf("	mValue1 = %.5f\n", mValue1);
+		printf("	mValue2 = %.5f\n", mValue2);
+	}
+#endif
+
+private:	
+	AUParameterEventType		mEventType;
+	
+	SInt32						mBufferOffset;		// ramp start offset relative to start of this slice (may be negative)
+	UInt32						mDurationInFrames;	// total duration of ramp parameter
+	AudioUnitParameterValue     mValue1;				// value if immediate : startValue if ramp
+	AudioUnitParameterValue		mValue2;				// endValue (only used for ramp)
+	
+	UInt32					mSliceDurationFrames;	// duration of this processing slice 
+};
+
+
+
+// ____________________________________________________________________________
+//
+class AUIOElement;
+
+/*! @class AUElement */
+class AUElement {
+public:
+/*! @ctor AUElement */
+								AUElement(AUBase *audioUnit) : mAudioUnit(audioUnit),
+									mUseIndexedParameters(false), mElementName(0) { }
+	
+/*! @dtor ~AUElement */
+	virtual						~AUElement() { if (mElementName) CFRelease (mElementName); }
+	
+/*! @method GetNumberOfParameters */
+	virtual UInt32				GetNumberOfParameters()
+	{
+		if(mUseIndexedParameters) return static_cast<UInt32>(mIndexedParameters.size()); else return static_cast<UInt32>(mParameters.size());
+	}
+/*! @method GetParameterList */
+	virtual void				GetParameterList(AudioUnitParameterID *outList);
+/*! @method HasParameterID */
+	bool						HasParameterID (AudioUnitParameterID paramID) const;
+	
+/*! @method GetParameter */
+	AudioUnitParameterValue		GetParameter(AudioUnitParameterID paramID);
+/*! @method SetParameter */
+	void						SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value, bool okWhenInitialized = false);
+	// Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted. 
+
+	// interpolates the start and end values corresponding to the current processing slice
+	// most ramp parameter implementations will want to use this method
+/*! @method GetRampSliceStartEnd */
+	void						GetRampSliceStartEnd(	AudioUnitParameterID	paramID,
+													AudioUnitParameterValue &	outStartValue,
+													AudioUnitParameterValue &	outEndValue,
+													AudioUnitParameterValue &	outValuePerFrameDelta );
+													
+/*! @method GetEndValue */
+	AudioUnitParameterValue		GetEndValue(	AudioUnitParameterID		paramID);
+
+/*! @method SetRampParameter */
+	void						SetScheduledEvent(	AudioUnitParameterID 			paramID,
+													const AudioUnitParameterEvent 	&inEvent,
+													UInt32 							inSliceOffsetInBuffer,
+													UInt32							inSliceDurationFrames,
+													bool							okWhenInitialized = false );
+	// Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted. 
+
+
+/*! @method GetAudioUnit */
+	AUBase *					GetAudioUnit() const { return mAudioUnit; };
+
+/*! @method SaveState */
+	void						SaveState(CFMutableDataRef data);
+/*! @method RestoreState */
+	const UInt8 *				RestoreState(const UInt8 *state);
+/*! @method GetName */
+	CFStringRef					GetName () const { return mElementName; }
+/*! @method SetName */
+	void						SetName (CFStringRef inName);
+/*! @method HasName */
+	bool						HasName () const { return mElementName != 0; }
+/*! @method UseIndexedParameters */
+	virtual void				UseIndexedParameters(int inNumberOfParameters);
+
+/*! @method AsIOElement*/
+	virtual AUIOElement*		AsIOElement () { return NULL; }
+	
+protected:
+	inline ParameterMapEvent&	GetParamEvent(AudioUnitParameterID paramID);
+	
+private:
+	typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID> > ParameterMap;
+	
+/*! @var mAudioUnit */
+	AUBase *						mAudioUnit;
+/*! @var mParameters */
+	ParameterMap					mParameters;
+
+/*! @var mUseIndexedParameters */
+	bool							mUseIndexedParameters;
+/*! @var mIndexedParameters */
+	std::vector<ParameterMapEvent>	mIndexedParameters;
+	
+/*! @var mElementName */
+	CFStringRef						mElementName;
+};
+
+
+
+// ____________________________________________________________________________
+//
+/*! @class AUIOElement */
+class AUIOElement : public AUElement {
+public:
+/*! @ctor AUIOElement */
+								AUIOElement(AUBase *audioUnit);
+
+/*! @method GetStreamFormat */
+	const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; }
+	
+/*! @method SetStreamFormat */
+	virtual OSStatus			SetStreamFormat(const CAStreamBasicDescription &desc);
+
+/*! @method AllocateBuffer */
+	virtual void				AllocateBuffer(UInt32 inFramesToAllocate = 0);
+/*! @method DeallocateBuffer */
+	void						DeallocateBuffer();
+/*! @method NeedsBufferSpace */
+	virtual bool				NeedsBufferSpace() const = 0;
+
+/*! @method SetWillAllocateBuffer */
+	void						SetWillAllocateBuffer(bool inFlag) { 
+									mWillAllocate = inFlag; 
+								}
+/*! @method WillAllocateBuffer */
+	bool						WillAllocateBuffer() const { 
+									return mWillAllocate; 
+								}
+	
+/*! @method UseExternalBuffer */
+	void						UseExternalBuffer(const AudioUnitExternalBuffer &buf) {
+									mIOBuffer.UseExternalBuffer(mStreamFormat, buf);
+								}
+/*! @method PrepareBuffer */
+	AudioBufferList &			PrepareBuffer(UInt32 nFrames) {
+									if (mWillAllocate)
+										return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
+									throw OSStatus(kAudioUnitErr_InvalidPropertyValue);
+								}
+/*! @method PrepareNullBuffer */
+	AudioBufferList &			PrepareNullBuffer(UInt32 nFrames) {
+									return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
+								}
+/*! @method SetBufferList */
+	AudioBufferList &			SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); }
+/*! @method SetBuffer */
+	void						SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); }
+/*! @method InvalidateBufferList */
+	void						InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }
+
+/*! @method GetBufferList */
+	AudioBufferList &			GetBufferList() const { return mIOBuffer.GetBufferList(); }
+
+/*! @method GetChannelData */
+	AudioUnitSampleType *		GetChannelData(int ch) const {
+									if (mStreamFormat.IsInterleaved())
+										return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+									else
+										return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+								}
+	Float32 *					GetFloat32ChannelData(int ch) const {
+									if (mStreamFormat.IsInterleaved())
+										return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+									else
+										return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+								}
+	SInt32 *					GetSInt32ChannelData(int ch) const {
+									if (mStreamFormat.IsInterleaved())
+										return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+									else
+										return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+								}
+	SInt16 *					GetInt16ChannelData(int ch) const {
+									if (mStreamFormat.IsInterleaved())
+										return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+									else
+										return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+								}
+
+/*! @method CopyBufferListTo */
+	void						CopyBufferListTo(AudioBufferList &abl) const {
+									mIOBuffer.CopyBufferListTo(abl);
+								}
+/*! @method CopyBufferContentsTo */
+	void						CopyBufferContentsTo(AudioBufferList &abl) const {
+									mIOBuffer.CopyBufferContentsTo(abl);
+								}
+
+/*	UInt32						BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; }
+	UInt32						BytesToFrames(AudioBufferList &abl) {
+									return BytesToFrames(abl.mBuffers[0].mDataByteSize);
+								}
+	UInt32						FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/
+
+/*! @method IsInterleaved */
+	bool						IsInterleaved() const { return mStreamFormat.IsInterleaved(); }
+/*! @method NumberChannels */
+	UInt32						NumberChannels() const { return mStreamFormat.NumberChannels(); }
+/*! @method NumberInterleavedChannels */
+	UInt32						NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); }
+
+/*! @method GetChannelMapTags */
+	virtual UInt32				GetChannelLayoutTags (AudioChannelLayoutTag	*outLayoutTagsPtr);
+
+/*! @method GetAudioChannelLayout */
+	virtual UInt32				GetAudioChannelLayout (AudioChannelLayout	*outMapPtr, Boolean	&outWritable);
+
+/*! @method SetAudioChannelLayout */
+	virtual OSStatus			SetAudioChannelLayout (const AudioChannelLayout &inData);
+		
+/*! @method RemoveAudioChannelLayout */
+	virtual OSStatus			RemoveAudioChannelLayout ();
+
+/*! @method AsIOElement*/
+	virtual AUIOElement*		AsIOElement () { return this; }
+
+protected:
+/*! @var mStreamFormat */
+	CAStreamBasicDescription	mStreamFormat;
+/*! @var mIOBuffer */
+	AUBufferList				mIOBuffer;	// for input: input proc buffer, only allocated when needed
+											// for output: output cache, usually allocated early on
+/*! @var mWillAllocate */
+	bool						mWillAllocate;
+};
+
+// ____________________________________________________________________________
+//
+// AUScopeDelegates are a way to get virtual scopes.
+/*! @class AUScopeDelegate */
+class AUScopeDelegate {
+public:
+/*! @ctor AUScopeDelegate */
+					AUScopeDelegate() : mCreator(NULL), mScope(0) { }	
+/*! @dtor ~AUScopeDelegate */
+					virtual ~AUScopeDelegate() {}
+	
+/*! @method Initialize */
+	void					Initialize(	AUBase *creator, 
+										AudioUnitScope scope, 
+										UInt32 numElements)
+	{
+		mCreator = creator;
+		mScope = scope;
+		SetNumberOfElements(numElements);
+	}
+	
+/*! @method SetNumberOfElements */
+	virtual void			SetNumberOfElements(UInt32 numElements) = 0;
+	
+/*! @method GetNumberOfElements */
+	virtual UInt32			GetNumberOfElements()	 = 0;
+	
+/*! @method GetElement */
+	virtual AUElement *		GetElement(UInt32 elementIndex) = 0;
+	
+	AUBase *			GetCreator() const { return mCreator; }
+	AudioUnitScope		GetScope() const { return mScope; }
+	
+
+private:
+/*! @var mCreator */
+	AUBase *					mCreator;
+/*! @var mScope */
+	AudioUnitScope				mScope;
+};
+
+
+
+// ____________________________________________________________________________
+//
+/*! @class AUScope */
+class AUScope {
+public:
+/*! @ctor AUScope */
+					AUScope() : mCreator(NULL), mScope(0), mDelegate(0) { }	
+/*! @dtor ~AUScope */
+					~AUScope();
+	
+/*! @method Initialize */
+	void			Initialize(AUBase *creator, 
+								AudioUnitScope scope, 
+								UInt32 numElements)
+	{
+		mCreator = creator;
+		mScope = scope;
+
+		if (mDelegate)
+			return mDelegate->Initialize(creator, scope, numElements);
+			
+		SetNumberOfElements(numElements);
+	}
+	
+/*! @method SetNumberOfElements */
+	void			SetNumberOfElements(UInt32 numElements);
+	
+/*! @method GetNumberOfElements */
+	UInt32			GetNumberOfElements()	const	
+	{
+		if (mDelegate)
+			return mDelegate->GetNumberOfElements();
+			
+		return static_cast<UInt32>(mElements.size());
+	}
+	
+/*! @method GetElement */
+	AUElement *		GetElement(UInt32 elementIndex) const
+	{
+		if (mDelegate)
+			return mDelegate->GetElement(elementIndex);
+
+		ElementVector::const_iterator i = mElements.begin() + elementIndex;
+			// catch passing -1 in as the elementIndex - causes a wrap around
+		return (i >= mElements.end() || i < mElements.begin()) ? NULL : *i;
+	}
+	
+/*! @method SafeGetElement */
+	AUElement *		SafeGetElement(UInt32 elementIndex)
+	{
+		AUElement *element = GetElement(elementIndex);
+		if (element == NULL)
+			COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+		return element;
+	}
+	
+/*! @method GetIOElement */
+	AUIOElement *	GetIOElement(UInt32 elementIndex) const
+	{
+		AUElement *element = GetElement(elementIndex);
+		AUIOElement *ioel = element ? element->AsIOElement () : NULL;
+		if (!ioel)
+			COMPONENT_THROW (kAudioUnitErr_InvalidElement);
+		return ioel;
+	}
+	
+/*! @method HasElementWithName */
+	bool			HasElementWithName () const;
+	
+/*! @method AddElementNamesToDict */
+	void			AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
+	
+	bool			RestoreElementNames (CFDictionaryRef& inNameDict);
+	
+	AudioUnitScope		GetScope() const { return mScope; }
+
+	void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
+
+/*! @method SaveState */
+    void            SaveState(CFMutableDataRef data);
+
+/*! @method RestoreState */
+    const UInt8 *	RestoreState(const UInt8 *state);
+	
+private:
+	typedef std::vector<AUElement *> ElementVector;
+/*! @var mCreator */
+	AUBase *					mCreator;
+/*! @var mScope */
+	AudioUnitScope				mScope;
+/*! @var mElements */
+	ElementVector				mElements;
+/*! @var mDelegate */
+	AUScopeDelegate *			mDelegate;
+};
+
+
+
+#endif // __AUScopeElement_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
new file mode 100644
index 0000000..fc98733
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
@@ -0,0 +1,370 @@
+/*
+     File: ComponentBase.cpp
+ Abstract: ComponentBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "ComponentBase.h"
+#include "CAXException.h"
+
+#if TARGET_OS_MAC
+pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_once_t ComponentInitLocker::sOnce = PTHREAD_ONCE_INIT;
+
+void ComponentInitLocker::InitComponentInitLocker()
+{
+	// have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
+	pthread_mutexattr_t attr;
+	pthread_mutexattr_init(&attr);
+	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+	pthread_mutex_init(&sComponentOpenMutex, &attr);
+	pthread_mutexattr_destroy(&attr);
+}
+
+#elif TARGET_OS_WIN32
+CAGuard	ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
+#endif
+
+ComponentBase::EInstanceType ComponentBase::sNewInstanceType;
+
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
+#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_WIN32
+	static OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
+#endif
+
+ComponentBase::ComponentBase(AudioComponentInstance inInstance) 
+	: mComponentInstance(inInstance), 
+	  mInstanceType(sNewInstanceType) 
+{ 
+	GetComponentDescription(); 
+}
+
+ComponentBase::~ComponentBase()
+{
+}
+
+void			ComponentBase::PostConstructor()
+{
+}
+
+void			ComponentBase::PreDestructor()
+{
+}
+
+#define ACPI	((AudioComponentPlugInInstance *)self)
+#define ACImp	((ComponentBase *)&ACPI->mInstanceStorage)
+
+OSStatus ComponentBase::AP_Open(void *self, AudioUnit compInstance)
+{
+	OSStatus result = noErr;
+	try {
+		ComponentInitLocker lock;
+		
+		ComponentBase::sNewInstanceType = ComponentBase::kAudioComponentInstance;
+		ComponentBase *cb = (ComponentBase *)(*ACPI->mConstruct)(&ACPI->mInstanceStorage, compInstance);
+		cb->PostConstructor();	// allows base class to do additional initialization
+		// once the derived class is fully constructed
+		result = noErr;
+	}
+	COMPONENT_CATCH
+	if (result)
+		delete ACPI;
+	return result;
+}
+
+OSStatus ComponentBase::AP_Close(void *self)
+{
+	OSStatus result = noErr;
+	try {
+		if (ACImp) {
+			ACImp->PreDestructor();
+			(*ACPI->mDestruct)(&ACPI->mInstanceStorage);
+			free(self);
+		}
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus		ComponentBase::Version()
+{
+	return 0x00000001;
+}
+
+OSStatus		ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
+{
+	if (This == NULL) return kAudio_ParamError;
+
+	OSStatus result = noErr;
+	
+	switch (p->what) {
+	case kComponentCloseSelect:
+		This->PreDestructor();
+		delete This;
+		break;
+	
+	case kComponentVersionSelect:
+		result = This->Version();
+		break;
+
+	case kComponentCanDoSelect:
+		switch (GetSelectorForCanDo(p)) {
+		case kComponentOpenSelect:
+		case kComponentCloseSelect:
+		case kComponentVersionSelect:
+		case kComponentCanDoSelect:
+			return 1;
+		default:
+			return 0;
+		}
+		
+	default:
+		result = badComponentSelector;
+		break;
+	}
+	return result;
+}
+
+SInt16		ComponentBase::GetSelectorForCanDo(ComponentParameters *params)
+{
+	if (params->what != kComponentCanDoSelect) return 0;
+	
+	#if TARGET_CPU_X86
+		SInt16 sel = params->params[0];
+	#elif TARGET_CPU_X86_64
+		SInt16 sel = params->params[1];
+	#elif TARGET_CPU_PPC
+		SInt16 sel = (params->params[0] >> 16);
+	#else
+		SInt16 sel = params->params[0];
+	#endif
+	
+	return sel;
+/*		
+		printf ("flags:%d, paramSize: %d, what: %d\n\t", params->flags, params->paramSize, params->what);
+		for (int i = 0; i < params->paramSize; ++i) {
+			printf ("[%d]:%d(0x%x), ", i, params->params[i], params->params[i]);
+		}
+		printf("\n\tsel:%d\n", sel);
+*/
+}
+
+#endif
+
+#if CA_DO_NOT_USE_AUDIO_COMPONENT 
+static OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription &outDesc);
+#endif
+
+AudioComponentDescription ComponentBase::GetComponentDescription() const
+{
+	AudioComponentDescription desc;
+	OSStatus result = 1;
+	
+	if (IsPluginObject()) {
+		ca_require_noerr(result = CB_GetComponentDescription (mComponentInstance, &desc), home);
+	}
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	else {
+		ca_require_noerr(result = CMgr_GetComponentDescription (mComponentInstance, &desc), home);	
+	}
+#endif
+
+home:
+	if (result)
+		memset (&desc, 0, sizeof(AudioComponentDescription));
+	
+	return desc;
+}
+
+#if CA_USE_AUDIO_PLUGIN_ONLY
+// everything we need is there and we should be linking against it
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+	AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
+	if (comp)
+		return AudioComponentGetDescription(comp, outDesc);
+
+	return kAudio_ParamError;
+}
+
+#elif !TARGET_OS_WIN32
+// these are the direct dependencies on ComponentMgr calls that an AU
+// that is a component mgr is dependent on
+
+// these are dynamically loaded so that these calls will work on Leopard
+#include <dlfcn.h>
+
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+	typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
+	static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
+	
+	typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
+	static AudioComponentGetDescriptionProc acGDProc = NULL;
+	
+	static int doneInit = 0;
+	if (doneInit == 0) {
+		doneInit = 1;	
+		void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
+		if (theImage != NULL)
+		{
+			aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
+			if (aciGCProc) {
+				acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
+			}
+		}
+	}
+	
+	OSStatus result = kAudio_UnimplementedError;
+	if (acGDProc && aciGCProc) {
+		AudioComponent comp = (*aciGCProc)(inInstance);
+		if (comp)
+			result = (*acGDProc)(comp, outDesc);
+	} 
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	else {
+		result = CMgr_GetComponentDescription (inInstance, outDesc);
+	}
+#endif
+
+	return result;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+// these are the direct dependencies on ComponentMgr calls that an AU
+// that is a component mgr is dependent on
+
+// these are dynamically loaded
+
+#include <CoreServices/CoreServices.h>
+#include <AudioUnit/AudioUnit.h>
+#include "CAXException.h"
+#include "ComponentBase.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Component Manager
+// Used for fast dispatch with audio units
+typedef Handle (*GetComponentInstanceStorageProc)(ComponentInstance aComponentInstance);
+static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
+
+typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
+static GetComponentInfoProc sGetComponentInfoProc = NULL;
+
+typedef void (*SetComponentInstanceStorageProc)(ComponentInstance, Handle);
+static SetComponentInstanceStorageProc sSetComponentInstanceStorageProc = NULL;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+static void CSInitOnce(void* /*unused*/)
+{
+	void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
+	if (!theImage) return;
+
+	sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
+	sGetComponentInfoProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
+	sSetComponentInstanceStorageProc = (SetComponentInstanceStorageProc) dlsym(theImage, "SetComponentInstanceStorage");
+}
+
+#if TARGET_OS_MAC
+
+#include <dispatch/dispatch.h>
+
+static dispatch_once_t sCSInitOnce = 0;
+
+static void CSInit ()
+{
+	dispatch_once_f(&sCSInitOnce, NULL, CSInitOnce);
+}
+
+#else 
+
+static void CSInit ()
+{
+	static int sDoCSLoad = 1;
+	if (sDoCSLoad) {
+		sDoCSLoad = 0;
+		CSInitOnce(NULL);
+	}
+}
+
+#endif
+
+OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+	CSInit();
+	if (sGetComponentInfoProc)
+		return (*sGetComponentInfoProc)((Component)inInstance, (ComponentDescription*)outDesc, NULL, NULL, NULL);
+	return kAudio_UnimplementedError;
+}
+
+Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance)
+{
+	CSInit();
+	if (sGetComponentInstanceStorageProc)
+		return (*sGetComponentInstanceStorageProc)(aComponentInstance);
+	return NULL;
+}
+
+void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage)
+{
+	CSInit();
+	if (sSetComponentInstanceStorageProc)
+		(*sSetComponentInstanceStorageProc)(aComponentInstance, theStorage);
+}
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY
+
+#else
+//#include "ComponentManagerDependenciesWin.h"
+// everything we need is there and we should be linking against it
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+	AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
+	if (comp)
+		return AudioComponentGetDescription(comp, outDesc);
+
+	return kAudio_ParamError;
+}
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h
new file mode 100644
index 0000000..67417aa
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h
@@ -0,0 +1,353 @@
+/*
+     File: ComponentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __ComponentBase_h__
+#define __ComponentBase_h__
+
+#include <new>
+#include "CADebugMacros.h"
+#include "CAXException.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <AudioUnit/AudioUnit.h>
+
+	#if !CA_USE_AUDIO_PLUGIN_ONLY
+		#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
+	
+		#if	(MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
+			#define AudioComponentInstance			ComponentInstance
+			#define AudioComponentDescription		ComponentDescription
+			#define	AudioComponent					Component
+		#endif
+		Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance);
+		void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage);
+	#endif
+
+	#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+		typedef Float32 AudioUnitParameterValue;
+	#endif
+	#if COREAUDIOTYPES_VERSION < 1051
+		typedef Float32 AudioUnitSampleType;
+	#endif
+
+	#if !TARGET_OS_WIN32
+		#include <pthread.h>
+	#endif
+
+	#if TARGET_OS_WIN32
+		#include "CAGuard.h"
+	#endif
+#else
+	#include "CoreAudioTypes.h"
+	#if !CA_USE_AUDIO_PLUGIN_ONLY
+		#include "ComponentManagerDependenciesWin.h"
+	#endif
+	#include "AudioUnit.h"
+	#include "CAGuard.h"
+#endif
+
+#ifndef COMPONENT_THROW
+	#if VERBOSE_COMPONENT_THROW
+		#define COMPONENT_THROW(throw_err) \
+			do { DebugMessage(#throw_err); throw static_cast<OSStatus>(throw_err); } while (0)
+	#else
+		#define COMPONENT_THROW(throw_err) \
+			throw static_cast<OSStatus>(throw_err)
+	#endif
+#endif
+
+#define COMPONENT_CATCH \
+	catch (const CAXException &ex) { result = ex.mError; } \
+	catch (std::bad_alloc &) { result = kAudio_MemFullError; } \
+	catch (OSStatus catch_err) { result = catch_err; } \
+	catch (OSErr catch_err) { result = catch_err; } \
+	catch (...) { result = -1; }
+
+/*! @class ComponentBase */
+class ComponentBase {
+public:
+	// classic MacErrors
+	enum { noErr = 0};
+
+	/*! @ctor ComponentBase */
+				ComponentBase(AudioComponentInstance inInstance);
+				
+	/*! @dtor ~ComponentBase */
+	virtual 	~ComponentBase();
+	
+	/*! @method PostConstructor */
+	virtual void			PostConstructor();
+	
+	/*! @method PreDestructor */
+	virtual void			PreDestructor();
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	/*! @method Version */
+	virtual OSStatus		Version();
+
+	/*! @method ComponentEntryDispatch */
+	static OSStatus		ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This);
+
+	/*! GetSelectorForCanDo */
+	static SInt16		GetSelectorForCanDo(ComponentParameters *params);
+#endif
+	
+	/*! @method GetComponentInstance */
+	AudioComponentInstance		GetComponentInstance() const { return mComponentInstance; }
+
+	/*! @method GetComponentDescription */
+	AudioComponentDescription	GetComponentDescription() const;
+
+	// This global variable is so that new instances know how they were instantiated: via the Component Manager, 
+	// or as AudioComponents. It's ugly, but preferable to altering the constructor of every class in the hierarchy.
+	// It's safe because construction is protected by ComponentInitLocker.
+	enum EInstanceType { kComponentMgrInstance, kAudioComponentInstance };
+	static EInstanceType sNewInstanceType;
+
+	/*! @method IsPluginObject */
+	bool			IsPluginObject () const { return mInstanceType == kAudioComponentInstance; }
+	/*! @method IsCMgrObject */
+	bool			IsCMgrObject () const { return mInstanceType == kComponentMgrInstance; }
+
+	/*! @method AP_Open */
+	static OSStatus AP_Open(void *self, AudioUnit compInstance);
+
+	/*! @method AP_Close */
+	static OSStatus AP_Close(void *self);
+	
+protected:
+	/*! @var mComponentInstance */
+	AudioComponentInstance		mComponentInstance;
+	EInstanceType				mInstanceType;
+};
+
+class ComponentInitLocker 
+{
+#if TARGET_OS_MAC
+public:
+	ComponentInitLocker() 
+	{ 
+		pthread_once(&sOnce, InitComponentInitLocker);
+		pthread_mutex_lock(&sComponentOpenMutex); 
+		mPreviousNewInstanceType = ComponentBase::sNewInstanceType;
+	}
+	~ComponentInitLocker() 
+	{ 
+		ComponentBase::sNewInstanceType = mPreviousNewInstanceType;
+		pthread_mutex_unlock(&sComponentOpenMutex); 
+	}
+
+	// There are situations (11844772) where we need to be able to release the lock early.
+	class Unlocker {
+	public:
+		Unlocker()
+		{
+			pthread_mutex_unlock(&sComponentOpenMutex);
+		}
+		~Unlocker()
+		{
+			pthread_mutex_lock(&sComponentOpenMutex); 
+		}
+	};
+
+private:
+	static pthread_mutex_t sComponentOpenMutex;
+	static pthread_once_t sOnce;
+	static void InitComponentInitLocker();
+	
+#elif TARGET_OS_WIN32
+public:
+	bool sNeedsUnlocking;
+	ComponentInitLocker() { sNeedsUnlocking = sComponentOpenGuard.Lock(); }
+	~ComponentInitLocker() { if(sNeedsUnlocking) { sComponentOpenGuard.Unlock(); } }
+private:
+	static CAGuard	sComponentOpenGuard;
+#endif
+	
+private:
+	ComponentBase::EInstanceType	mPreviousNewInstanceType;
+};
+
+/*! @class AudioComponentPlugInInstance */ 
+struct AudioComponentPlugInInstance {
+	AudioComponentPlugInInterface		mPlugInInterface;
+	void *								(*mConstruct)(void *memory, AudioComponentInstance ci);
+	void								(*mDestruct)(void *memory);
+	void *								mPad[2];				// pad to a 16-byte boundary (in either 32 or 64 bit mode)
+	UInt32								mInstanceStorage;		// the ACI implementation object is constructed into this memory
+																// this member is just a placeholder. it is aligned to a 16byte boundary
+};
+
+/*! @class APFactory */ 
+template <class APMethodLookup, class Implementor>
+class APFactory {
+public:
+	static void *Construct(void *memory, AudioComponentInstance compInstance)
+	{
+		return new(memory) Implementor(compInstance);
+	}
+	
+	static void Destruct(void *memory)
+	{
+		((Implementor *)memory)->~Implementor();
+	}
+
+	// This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
+	// The actual implementation object is not created until Open().
+	static AudioComponentPlugInInterface *Factory(const AudioComponentDescription * /* inDesc */)
+	{
+		AudioComponentPlugInInstance *acpi = 
+				(AudioComponentPlugInInstance *)malloc( offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor) );
+		acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
+		acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
+		acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
+		acpi->mPlugInInterface.reserved = NULL;
+		acpi->mConstruct = Construct;
+		acpi->mDestruct = Destruct;
+		acpi->mPad[0] = NULL;
+		acpi->mPad[1] = NULL;
+		return (AudioComponentPlugInInterface*)acpi;
+	}
+	
+	// This is for runtime registration (not for plug-ins loaded from bundles).
+	static AudioComponent Register(UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags=0)
+	{
+		AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
+		return AudioComponentRegister(&desc, name, vers, Factory); 
+	}
+};
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+/*! @class ComponentEntryPoint 
+ *	@discussion This is only used for a component manager version
+*/
+template <class Class>
+class ComponentEntryPoint {
+public:
+	/*! @method Dispatch */
+	static OSStatus Dispatch(ComponentParameters *params, Class *obj)
+	{
+		OSStatus result = noErr;
+		
+		try {
+			if (params->what == kComponentOpenSelect) {
+				// solve a host of initialization thread safety issues.
+				ComponentInitLocker lock;
+
+				ComponentBase::sNewInstanceType = ComponentBase::kComponentMgrInstance;
+				ComponentInstance ci = (ComponentInstance)(params->params[0]);
+				Class *This = new Class((AudioComponentInstance)ci);
+				This->PostConstructor();	// allows base class to do additional initialization
+											// once the derived class is fully constructed
+				
+				CMgr_SetComponentInstanceStorage(ci, (Handle)This);
+			} else
+				result = Class::ComponentEntryDispatch(params, obj);
+		}
+		COMPONENT_CATCH
+		
+		return result;
+	}
+	
+	/*! @method Register */
+	static Component Register(OSType compType, OSType subType, OSType manufacturer)
+	{
+		ComponentDescription	description = {compType, subType, manufacturer, 0, 0};
+		Component	component = RegisterComponent(&description, (ComponentRoutineUPP) Dispatch, registerComponentGlobal, NULL, NULL, NULL);
+		if (component != NULL) {
+			SetDefaultComponent(component, defaultComponentAnyFlagsAnyManufacturerAnySubType);
+		}
+		return component;
+	}
+};
+
+// NOTE: Component Mgr is deprecated in ML.
+// this macro should not be used with new audio components
+// it is only for backwards compatibility with Lion and SL.
+// this macro registers both a plugin and a component mgr version.
+#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
+    extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+    extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+        return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+    } \
+    extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
+    extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
+        return FactoryType<Class>::Factory(inDesc); \
+    }
+    // the only component we still support are the carbon based view components
+    // you should be using this macro now to exclusively register those types
+#define VIEW_COMPONENT_ENTRY(Class) \
+    extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+    extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+        return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+    }
+
+	/*! @class ComponentRegistrar */
+template <class Class, OSType Type, OSType Subtype, OSType Manufacturer>
+class ComponentRegistrar {
+public:
+	/*! @ctor ComponentRegistrar */
+	ComponentRegistrar() { ComponentEntryPoint<Class>::Register(Type, Subtype, Manufacturer); }
+};
+
+#define	COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \
+	static ComponentRegistrar<Class, Type, Subtype, Manufacturer>	gRegistrar##Class
+#else
+#define COMPONENT_ENTRY(Class)
+#define COMPONENT_REGISTER(Class)
+// this macro is used to generate the Entry Point for a given Audio Plugin
+// you should be using this macro now with audio components
+#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
+    extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
+    extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
+        return FactoryType<Class>::Factory(inDesc); \
+    }
+
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY
+
+
+#endif // __ComponentBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
new file mode 100644
index 0000000..3324753
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
@@ -0,0 +1,403 @@
+/*
+     File: AUCarbonViewBase.cpp
+ Abstract: AUCarbonViewBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include <algorithm>
+
+AUCarbonViewBase::AUCarbonViewBase(AudioUnitCarbonView inInstance, Float32 inNotificationInterval /* in seconds */) :
+	ComponentBase(inInstance),
+	mEditAudioUnit(0),
+	mParameterListener(NULL),
+#if !__LP64__
+	mEventListener(NULL),
+#endif
+	mTimerRef (NULL),
+	mTimerUPP (NULL),
+	mCarbonWindow(NULL),
+	mCarbonPane(NULL),
+	mXOffset(0), 
+	mYOffset(0)
+{
+	AUEventListenerCreate (ParameterListener, this,
+			CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 
+			inNotificationInterval, inNotificationInterval,
+			&mParameterListener);
+}
+
+AUCarbonViewBase::~AUCarbonViewBase()
+{
+#if !__LP64__
+	if (mCarbonPane)
+		DisposeControl(mCarbonPane);
+
+	for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
+		AUCarbonViewControl *ctl = *it;
+		delete ctl;
+	}
+	AUListenerDispose(mParameterListener);
+
+	if (mTimerRef)
+		::RemoveEventLoopTimer (mTimerRef);
+		
+	if (mTimerUPP)
+		DisposeEventLoopTimerUPP (mTimerUPP);
+#endif
+}
+	
+void	AUCarbonViewBase::AddControl(AUCarbonViewControl *control)
+{
+	ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
+	if (it == mControlList.end())
+		mControlList.push_back(control);
+}
+
+void	AUCarbonViewBase::RemoveControl(AUCarbonViewControl *control)
+{
+	ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
+	if (it != mControlList.end()) {
+		AUCarbonViewControl *ctl = *it;
+		mControlList.erase(it);
+		delete ctl;
+	}
+}
+
+void	AUCarbonViewBase::ClearControls ()
+{
+	for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
+		AUCarbonViewControl *ctl = *it;
+		delete ctl;
+	}
+	mControlList.clear();
+}
+
+void	AUCarbonViewBase::ParameterListener(void *				inCallbackRefCon,
+									void *						inObject,
+									const AudioUnitEvent *		inEvent,
+									UInt64						inEventHostTime,
+									Float32						inParameterValue)
+{
+	if (inEvent->mEventType == kAudioUnitEvent_ParameterValueChange) {
+		AUCarbonViewControl *ctl = (AUCarbonViewControl *)inObject;
+		ctl->ParameterToControl(inParameterValue);
+	}
+}
+
+									
+OSStatus			AUCarbonViewBase::CreateCarbonView(AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl)
+{
+#if !__LP64__
+	mEditAudioUnit = inAudioUnit;
+	mCarbonWindow = inWindow;
+
+	WindowAttributes attributes;
+	verify_noerr(GetWindowAttributes(mCarbonWindow, &attributes));
+	mCompositWindow = (attributes & kWindowCompositingAttribute) != 0;
+
+	Rect area;
+	area.left = short(inLocation.x); area.top = short(inLocation.y);
+	area.right = short(area.left + inSize.x); area.bottom = short(area.top + inSize.y);
+	OSStatus err = ::CreateUserPaneControl(inWindow, &area, 
+						kControlSupportsEmbedding,
+						&mCarbonPane);	// subclass can resize mCarbonPane to taste
+	verify_noerr(err);
+	if (err) return err;
+	outParentControl = mCarbonPane;
+	
+	// register for mouse-down in our pane -- we want to clear focus
+	EventTypeSpec paneEvents[] = {
+		{ kEventClassControl, kEventControlClick }
+	};
+	WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(paneEvents), paneEvents);
+	
+	if (IsCompositWindow()) {
+		verify_noerr(::HIViewAddSubview(inParentControl, mCarbonPane));
+		mXOffset = 0;
+		mYOffset = 0;
+	}
+	else {
+		verify_noerr(::EmbedControl(mCarbonPane, inParentControl));
+		mXOffset = inLocation.x;
+		mYOffset = inLocation.y;
+	}
+	mBottomRight.h = mBottomRight.v = 0;
+	
+	SizeControl(mCarbonPane, 0, 0);
+	if (err = CreateUI(mXOffset, mYOffset))
+		return err;
+
+	// we should only resize the control if a subclass has embedded
+	// controls in this AND this is done with the EmbedControl call below
+	// if mBottomRight is STILL equal to zero, then that wasn't done
+	// so don't size the control
+	Rect paneBounds;
+	GetControlBounds(mCarbonPane, &paneBounds);
+	// only resize mCarbonPane if it has not already been resized during CreateUI
+	if ((paneBounds.top == paneBounds.bottom) && (paneBounds.left == paneBounds.right)) {
+		if (mBottomRight.h != 0 && mBottomRight.v != 0)
+			SizeControl(mCarbonPane, (short) (mBottomRight.h - mXOffset), (short) (mBottomRight.v - mYOffset));
+	}
+
+	if (IsCompositWindow()) {
+		// prepare for handling scroll-events
+		EventTypeSpec scrollEvents[] = {
+			{ kEventClassScrollable, kEventScrollableGetInfo },
+			{ kEventClassScrollable, kEventScrollableScrollTo }
+		};
+		
+		WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(scrollEvents), scrollEvents);
+	
+		mCurrentScrollPoint.x = mCurrentScrollPoint.y = 0.0f;
+	}
+	
+	return err;
+#else
+	return noErr;
+#endif
+}
+
+OSStatus	AUCarbonViewBase::CreateUI(Float32	inXOffset, Float32 	inYOffset)
+{
+	return noErr;
+}
+
+OSStatus	AUCarbonViewBase::EmbedControl(ControlRef ctl)
+{
+#if !__LP64__
+	Rect r;
+	::GetControlBounds(ctl, &r);
+	if (r.right > mBottomRight.h) mBottomRight.h = r.right;
+	if (r.bottom > mBottomRight.v) mBottomRight.v = r.bottom;
+
+	if (IsCompositWindow()) 
+		return ::HIViewAddSubview(mCarbonPane, ctl);
+	else 
+		return ::EmbedControl(ctl, mCarbonPane);	
+#else
+	return noErr;
+#endif
+}
+
+void	AUCarbonViewBase::AddCarbonControl(AUCarbonViewControl::ControlType type, const CAAUParameter &param, ControlRef control)
+{
+	verify_noerr(EmbedControl(control));
+    
+	AUCarbonViewControl *auvc = new AUCarbonViewControl(this, mParameterListener, type, param, control);
+	auvc->Bind();
+	AddControl(auvc);
+}
+
+bool	AUCarbonViewBase::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{	
+#if !__LP64__
+	UInt32 eclass = GetEventClass(event);
+	UInt32 ekind = GetEventKind(event);
+	ControlRef control;
+	
+	switch (eclass) {
+		case kEventClassControl:
+		{
+			switch (ekind) {
+			case kEventControlClick:
+				GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+				if (control == mCarbonPane) {
+					ClearKeyboardFocus(mCarbonWindow);
+					return true;
+				}
+			}
+		}
+		break;
+		
+		case kEventClassScrollable:
+		{
+			switch (ekind) {
+			case kEventScrollableGetInfo:
+				{
+					// [1/4]
+					/*	<--	kEventParamImageSize (out, typeHISize)
+					 *		On exit, contains the size of the entire scrollable view.
+					 */
+					HISize originalSize = { mBottomRight.h, mBottomRight.v };
+					verify_noerr(SetEventParameter(event, kEventParamImageSize, typeHISize, sizeof(HISize), &originalSize));
+					
+					// [2/4]
+					/*	<--	kEventParamViewSize (out, typeHISize)
+					 *		On exit, contains the amount of the scrollable view that is
+					 *		visible.
+					 */
+					HIViewRef parentView = HIViewGetSuperview(mCarbonPane);
+					HIRect parentBounds;
+					verify_noerr(HIViewGetBounds(parentView, &parentBounds));
+					//HISize windowSize = {	float(windowBounds.right - windowBounds.left),
+					//						float(windowBounds.bottom - windowBounds.top) };
+					verify_noerr(SetEventParameter(event, kEventParamViewSize, typeHISize, sizeof(HISize), &(parentBounds.size)));
+					
+					// [3/4]
+					/*	<--	kEventParamLineSize (out, typeHISize)
+					 *		On exit, contains the amount that should be scrolled in
+					 *		response to a single click on a scrollbar arrow.
+					 */
+					 HISize scrollIncrementSize = { 16.0f, float(20) };
+					 verify_noerr(SetEventParameter(event, kEventParamLineSize, typeHISize, sizeof(HISize), &scrollIncrementSize));
+					 
+					// [4/4]
+					/*	<-- kEventParamOrigin (out, typeHIPoint)
+					 *		On exit, contains the scrollable viewÕs current origin (the
+					 *		view-relative coordinate that is drawn at the top left
+					 *		corner of its frame). These coordinates should always be
+					 *		greater than or equal to zero. They should be less than or
+					 *		equal to the viewÕs image size minus its view size.
+					 */
+					 verify_noerr(SetEventParameter(event, kEventParamOrigin, typeHIPoint, sizeof(HIPoint), &mCurrentScrollPoint));
+				}
+				return true;
+				
+			case kEventScrollableScrollTo:
+				{
+					/*
+					 *  kEventClassScrollable / kEventScrollableScrollTo
+					 *  
+					 *  Summary:
+					 *    Requests that an HIScrollViewÕs scrollable view should scroll to
+					 *    a particular origin.
+					 */
+					
+					/*	-->	kEventParamOrigin (in, typeHIPoint)
+					 *		The new origin for the scrollable view. The origin
+					 *		coordinates will vary from (0,0) to scrollable viewÕs image
+					 *		size minus its view size.
+					 */
+					HIPoint pointToScrollTo;
+					verify_noerr(GetEventParameter(event, kEventParamOrigin, typeHIPoint, NULL, sizeof(HIPoint), NULL, &pointToScrollTo));
+					
+					float xDelta = mCurrentScrollPoint.x - pointToScrollTo.x;
+					float yDelta = mCurrentScrollPoint.y - pointToScrollTo.y;
+					// move visible portion the appropriate amount
+					verify_noerr(HIViewScrollRect(mCarbonPane, NULL, xDelta, yDelta));
+					// set new content to be drawn
+					verify_noerr(HIViewSetBoundsOrigin(mCarbonPane, pointToScrollTo.x, pointToScrollTo.y));
+					
+					mCurrentScrollPoint = pointToScrollTo;
+				}
+				return true;
+				
+			default:
+				break;
+			}
+		}
+		break;
+		
+		default:
+			break;
+	}
+#endif
+	return false;
+}
+
+/*! @method TellListener */
+void	AUCarbonViewBase::TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar)
+{
+#if !__LP64__
+	if (mEventListener)
+		(*mEventListener)(mEventListenerUserData, mComponentInstance, &auvp, event, evpar);
+#endif
+
+	AudioUnitEvent	auEvent;
+	auEvent.mArgument.mParameter = auvp;
+	if (event == kAudioUnitCarbonViewEvent_MouseDownInControl) {
+		auEvent.mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
+	} else {
+		auEvent.mEventType = kAudioUnitEvent_EndParameterChangeGesture;
+	}
+	AUEventListenerNotify(mParameterListener, this, &auEvent);									
+}
+
+
+void			AUCarbonViewBase::Update (bool inUIThread)
+{
+	for (ControlList::iterator iter = mControlList.begin(); iter != mControlList.end(); ++iter)
+	{
+		(*iter)->Update(inUIThread);
+	}
+}
+
+pascal void		AUCarbonViewBase::TheTimerProc (EventLoopTimerRef inTimer, void *inUserData)
+{
+	AUCarbonViewBase* This = reinterpret_cast<AUCarbonViewBase*>(inUserData);
+	This->RespondToEventTimer (inTimer);
+}
+
+void			AUCarbonViewBase::RespondToEventTimer (EventLoopTimerRef inTimer) 
+{}
+
+/* 
+	THESE are reasonable values for these two times
+	0.005 // delay 
+	0.050 // interval
+*/
+
+OSStatus	AUCarbonViewBase::CreateEventLoopTimer (Float32 inDelay, Float32 inInterval) 
+{
+	if (mTimerUPP)
+		return noErr;
+	
+	mTimerUPP = NewEventLoopTimerUPP(TheTimerProc);
+	
+	EventLoopRef mainEventLoop = GetMainEventLoop();
+	
+		//doesn't seem to like too small a value
+	if (inDelay < 0.005)
+		inDelay = 0.005;
+			
+	OSStatus timerResult =  ::InstallEventLoopTimer(
+									mainEventLoop,
+									inDelay,
+									inInterval,
+									mTimerUPP,
+									this,
+									&mTimerRef);                       
+	return timerResult;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
new file mode 100644
index 0000000..910e53f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
@@ -0,0 +1,188 @@
+/*
+     File: AUCarbonViewBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUCarbonViewBase_h__
+#define __AUCarbonViewBase_h__
+
+#include <vector>
+#include "AUCarbonViewControl.h"
+#include "ComponentBase.h"
+
+static const Float32 kDefaultNotificationInterval = 0.100;
+
+	/*! @class AUCarbonViewBase */
+class AUCarbonViewBase : public ComponentBase, public CarbonEventHandler
+{
+public:
+    /*! @ctor AUCarbonViewBase */
+    AUCarbonViewBase (	AudioUnitCarbonView inInstance,
+						Float32 inNotificationInterval = kDefaultNotificationInterval /* in seconds */);
+	/*! @dtor ~AUCarbonViewBase */
+	virtual ~AUCarbonViewBase();
+	
+	// AUViewBase overrides
+	/*! @method CreateCarbonView */
+	virtual OSStatus			CreateCarbonView (AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl);
+
+	// our own virtual methods
+	/*! @method CreateUI */
+	virtual OSStatus			CreateUI (Float32	inXOffset, Float32 	inYOffset);
+
+	/*! @method HandleEvent */
+	virtual bool				HandleEvent (EventHandlerCallRef inHandlerRef, EventRef event);
+	
+	/*! @method GetEditAudioUnit */
+	const AudioUnit				GetEditAudioUnit () const { return mEditAudioUnit; }
+	//
+	/*! @method ComponentEntryDispatch */
+	static OSStatus			ComponentEntryDispatch (
+									ComponentParameters *			params,
+									AUCarbonViewBase *				This);
+
+	/*! @method AddCarbonControl */
+	void						AddCarbonControl (
+									AUCarbonViewControl::ControlType	type, 
+									const CAAUParameter &				param, 
+									ControlRef							control);
+
+	/*! @method GetCarbonWindow */
+	WindowRef					GetCarbonWindow () { return mCarbonWindow; }
+	/*! @method GetCarbonPane */
+	ControlRef					GetCarbonPane () { return mCarbonPane; }
+	/*! @method EmbedControl */
+	OSStatus					EmbedControl (ControlRef ctl);
+	
+	/*! @method TellListener */
+	void						TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar);
+	
+	// pass in true if wanting an update to the view and you're calling this from a thread
+	// that is safe to do UI in.
+	// If you don't know, pass in false!
+	/*! @method Update */
+	void						Update (bool inUIThread);
+	
+	/*! @method GetXOffset */
+	Float32						GetXOffset () { return mXOffset; }
+	/*! @method GetYOffset */
+	Float32						GetYOffset () { return mYOffset; }
+	
+	/*! @method ClearControls */
+	void						ClearControls ();
+	
+	/*! @method IsCompositWindow */
+	bool						IsCompositWindow () const { return mCompositWindow; }
+	
+protected:
+#if !__LP64__
+	/*! @method SetEventListener */
+	void						SetEventListener (AudioUnitCarbonViewEventListener listener, void *userData)
+								{
+									mEventListener = listener;
+									mEventListenerUserData = userData;
+								}
+#endif
+
+	/*! @method AddControl */
+	void						AddControl (AUCarbonViewControl *control);
+	/*! @method RemoveControl */
+	void						RemoveControl (AUCarbonViewControl *control);
+
+	OSStatus					CreateEventLoopTimer (Float32 inDelay, Float32 inInterval);
+	
+	/*! @method ParameterListener */
+	static void ParameterListener (void *						inCallbackRefCon,
+									void *						inObject,
+									const AudioUnitEvent *		inEvent,
+									UInt64						inEventHostTime,
+									Float32						inParameterValue);
+									
+	static pascal void TheTimerProc (	EventLoopTimerRef 		inTimer, 
+										void *					inUserData);
+
+	virtual void 				RespondToEventTimer (EventLoopTimerRef inTimer);
+
+	/*! @var mEditAudioUnit */
+	AudioUnit					mEditAudioUnit;	// the AU we're controlling
+	/*! @var mParameterListener */
+	AUEventListenerRef			mParameterListener;
+
+#if !__LP64__
+	/*! @var mEventListener */
+	AudioUnitCarbonViewEventListener
+								mEventListener;
+#endif
+
+	/*! @var mEventListenerUserData */
+	void *						mEventListenerUserData;
+
+private:
+	typedef std::vector<AUCarbonViewControl *> ControlList;
+	/*! @var mControlList */
+	ControlList					mControlList;
+
+	EventLoopTimerRef 			mTimerRef;
+
+	EventLoopTimerUPP			mTimerUPP;
+
+protected:
+	/*! @var mCarbonWindow */
+	WindowRef			mCarbonWindow;
+	/*! @var mCarbonPane */
+	ControlRef			mCarbonPane;	// user pane, contains all other controls
+	/*! @var mBottomRight */
+	Point				mBottomRight;	// largest width and height of child controls
+	/*! @var mXOffset */
+	Float32				mXOffset;
+	/*! @var mYOffset */
+	Float32				mYOffset;
+	/*! @var mCompositWindow */
+	bool				mCompositWindow;
+	/*! @var mCurrentScrollPoint */
+	HIPoint				mCurrentScrollPoint;		// needed for scrolling
+};
+
+
+#endif // __AUCarbonViewBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
new file mode 100644
index 0000000..981347b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
@@ -0,0 +1,710 @@
+/*
+     File: AUCarbonViewControl.cpp
+ Abstract: AUCarbonViewControl.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUCarbonViewControl.h"
+#include "AUCarbonViewBase.h"
+#include "AUViewLocalizedStringKeys.h"
+
+AUCarbonViewControl::AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control) :
+	mOwnerView(ownerView),
+	mListener(listener),
+	mType(type),
+	mParam(param),
+	mControl(control),
+	mInControlInitialization(0)
+{
+#if !__LP64__
+	SetControlReference(control, SRefCon(this));
+#endif
+}
+
+AUCarbonViewControl::~AUCarbonViewControl()
+{
+	AUListenerRemoveParameter(mListener, this, &mParam);
+}
+
+AUCarbonViewControl* AUCarbonViewControl::mLastControl = NULL;
+
+void	AUCarbonViewControl::Bind()
+{
+#if !__LP64__
+	mInControlInitialization = 1;   // true
+	AUListenerAddParameter(mListener, this, &mParam);
+		// will cause an almost-immediate callback
+	
+	EventTypeSpec events[] = {
+		{ kEventClassControl, kEventControlValueFieldChanged }	// N.B. OS X only
+	};
+	
+	WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+
+	if (mType == kTypeContinuous || mType == kTypeText || mType == kTypeDiscrete) {
+		EventTypeSpec events[] = {
+			{ kEventClassControl, kEventControlHit },
+			{ kEventClassControl, kEventControlClick },
+		    { kEventClassControl, kEventControlTrack }
+		};
+		WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+	} 
+
+	if (mType == kTypeText) {
+		EventTypeSpec events[] = {
+			{ kEventClassControl, kEventControlSetFocusPart }
+		};
+		WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events); 
+		ControlKeyFilterUPP proc = mParam.ValuesHaveStrings() ? StdKeyFilterCallback : NumericKeyFilterCallback;
+			// this will fail for a static text field
+		SetControlData(mControl, 0, kControlEditTextKeyFilterTag, sizeof(proc), &proc);
+	}
+	
+	Update(true);
+	mInControlInitialization = 0;   // false
+#endif
+}
+
+void	AUCarbonViewControl::ParameterToControl(Float32 paramValue)
+{
+#if !__LP64__
+	++mInControlInitialization;
+	switch (mType) {
+	case kTypeContinuous:
+		SetValueFract(AUParameterValueToLinear(paramValue, &mParam));
+		break;
+	case kTypeDiscrete:
+		{
+			long value = long(paramValue);
+			
+			// special case [1] -- menu parameters
+			if (mParam.HasNamedParams()) {
+				// if we're dealing with menus they behave differently!
+				// becaue setting min and max doesn't work correctly for the control value
+				// first menu item always reports a control value of 1
+				ControlKind ctrlKind;
+				if (GetControlKind(mControl, &ctrlKind) == noErr) {
+					if ((ctrlKind.kind == kControlKindPopupArrow) 
+						|| (ctrlKind.kind == kControlKindPopupButton))				
+					{
+						value = value - long(mParam.ParamInfo().minValue) + 1;
+					}
+				}
+			}
+			
+			// special case [2] -- Write-only boolean parameters
+			AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+			
+			bool isWriteOnlyBoolParameter = (	(AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+												(AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+												!(AUPI.flags & kAudioUnitParameterFlag_IsReadable)	);
+			if (!isWriteOnlyBoolParameter) {
+				SetValue (value);
+			}
+		}
+		break;
+	case kTypeText:
+		{
+			CFStringRef cfstr = mParam.GetStringFromValueCopy(&paramValue);
+
+			if ( !(mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsWritable)			//READ ONLY PARAMS
+					&& (mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsReadable)) 
+			{
+				if (mParam.GetParamTag()) {
+					CFMutableStringRef str = CFStringCreateMutableCopy(NULL, 256, cfstr);
+					CFRelease (cfstr);
+					CFStringAppend (str, CFSTR(" "));
+					CFStringAppend (str, mParam.GetParamTag());
+					cfstr = str;
+				}
+			}
+			SetTextValue(cfstr);
+			CFRelease (cfstr);
+		}
+		break;
+	}
+	--mInControlInitialization;
+#endif
+}
+
+void	AUCarbonViewControl::ControlToParameter()
+{
+#if !__LP64__
+	if (mInControlInitialization)
+		return;
+
+	switch (mType) {
+	case kTypeContinuous:
+		{
+			double controlValue = GetValueFract();
+			Float32 paramValue = AUParameterValueFromLinear(controlValue, &mParam);
+			mParam.SetValue(mListener, this, paramValue);
+		}
+		break;
+	case kTypeDiscrete:
+		{
+			long value = GetValue();
+			
+			// special case [1] -- Menus
+			if (mParam.HasNamedParams()) {
+				// if we're dealing with menus they behave differently!
+				// becaue setting min and max doesn't work correctly for the control value
+				// first menu item always reports a control value of 1
+				ControlKind ctrlKind;
+				if (GetControlKind(mControl, &ctrlKind) == noErr) {
+					if ((ctrlKind.kind == kControlKindPopupArrow) 
+						|| (ctrlKind.kind == kControlKindPopupButton))				
+					{
+						value = value + long(mParam.ParamInfo().minValue) - 1;
+					}
+				}
+			}
+			
+			// special case [2] -- Write-only boolean parameters
+			AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+			
+			bool isWriteOnlyBoolParameter = (	(AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+												(AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+												!(AUPI.flags & kAudioUnitParameterFlag_IsReadable)	);
+			if (isWriteOnlyBoolParameter) {
+				value = 1;
+			}
+			
+			mParam.SetValue (mListener, this, value);
+		}
+		break;
+	case kTypeText:
+		{
+			Float32 val = mParam.GetValueFromString (GetTextValue());
+			mParam.SetValue(mListener, this, (mParam.IsIndexedParam() ? (int)val : val));
+			if (mParam.ValuesHaveStrings())
+				ParameterToControl(val); //make sure we display the correct text (from the AU)
+		}
+		break;
+	}
+#endif
+}
+
+void	AUCarbonViewControl::SetValueFract(double value)
+{
+#if !__LP64__
+	SInt32 minimum = GetControl32BitMinimum(mControl);
+	SInt32 maximum = GetControl32BitMaximum(mControl);
+	SInt32 cval = SInt32(value * (maximum - minimum) + minimum + 0.5);
+	SetControl32BitValue(mControl, cval);
+//	printf("set: value=%lf, min=%ld, max=%ld, ctl value=%ld\n", value, minimum, maximum, cval);
+#endif
+}
+
+double	AUCarbonViewControl::GetValueFract()
+{
+#if !__LP64__
+	SInt32 minimum = GetControl32BitMinimum(mControl);
+	SInt32 maximum = GetControl32BitMaximum(mControl);
+	SInt32 cval = GetControl32BitValue(mControl);
+	double result = double(cval - minimum) / double(maximum - minimum);
+//	printf("get: min=%ld, max=%ld, value=%ld, result=%f\n", minimum, maximum, cval, result);
+	return result;
+#else
+	return 0;
+#endif
+}
+
+void	AUCarbonViewControl::SetTextValue(CFStringRef cfstr)
+{
+#if !__LP64__
+	verify_noerr(SetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr));
+#endif
+}
+
+CFStringRef	AUCarbonViewControl::GetTextValue()
+{
+#if !__LP64__
+	CFStringRef cfstr;
+	verify_noerr(GetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr, NULL));
+	return cfstr;
+#else
+	return CFSTR("");
+#endif
+}
+
+void	AUCarbonViewControl::SetValue(long value)
+{
+#if !__LP64__
+	SetControl32BitValue(mControl, value);
+#endif
+}
+
+long	AUCarbonViewControl::GetValue()
+{
+#if !__LP64__
+	return GetControl32BitValue(mControl);
+#else
+	return 0;
+#endif
+}
+
+/* Notes on event handling 
+	
+	Button (Click and release on button)
+		kEventControlClick received
+		kEventControlTrack received
+		kEventControlValueFieldChanged received
+		kEventControlHit received
+	
+	Button (Click and release outside of button bounds)
+		kEventControlClick received
+		kEventControlTrack received
+	
+	Slider (Click, drag, and release)
+		kEventControlClick received
+		kEventControlTrack received
+		kEventControlValueFieldChanged received
+		kEventControlValueFieldChanged received
+		kEventControlHit received
+		
+	Slider (Click, release without changing value)
+		kEventControlClick received
+		kEventControlTrack received
+*/
+bool	AUCarbonViewControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+	UInt32 eclass = GetEventClass(event);
+	UInt32 ekind = GetEventKind(event);
+	ControlRef control;
+	bool		handled = true;
+	
+	switch (eclass) {
+		case kEventClassControl:
+		{
+			AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+			
+			bool isWriteOnlyBoolParameter = (	(AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+												(AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+												!(AUPI.flags & kAudioUnitParameterFlag_IsReadable)	);
+			
+			switch (ekind) {
+				case kEventControlSetFocusPart:	// tab
+					handled = !handled;		// fall through to next case
+					mLastControl = this;
+				case kEventControlValueFieldChanged:
+					GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+					verify(control == mControl);
+					ControlToParameter();
+					return handled;			
+				case kEventControlClick:
+					if (isWriteOnlyBoolParameter) {
+						GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+						verify(control == mControl);
+						ControlToParameter();
+					} else if (mLastControl != this) {
+						if (mLastControl != NULL) {
+							mLastControl->Update(false);
+						}
+						mLastControl = this;	
+					}
+					mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseDownInControl, NULL);
+					break;	// don't return true, continue normal processing
+				case kEventControlHit:
+					if (mLastControl != this) {
+						if (mLastControl != NULL)
+							mLastControl->Update(false);
+						mLastControl = this;	
+					} 
+					mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
+					break;	// don't return true, continue normal processing
+				case kEventControlTrack:		
+					if (mLastControl != this) {
+						if (mLastControl != NULL)
+							mLastControl->Update(false);
+						mLastControl = this;	
+					}
+					
+					CallNextEventHandler(inHandlerRef, event);
+					ControlToParameter();						// new code
+					mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
+					// old code:
+					//		break;	// don't return true, continue normal processing
+
+					return handled;	// don't return true, continue normal processing
+			}
+		}
+	}
+	return !handled;
+}
+
+pascal void	AUCarbonViewControl::SliderTrackProc(ControlRef theControl, ControlPartCode partCode)
+{
+	// this doesn't need to actually do anything
+//	AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+}
+
+pascal ControlKeyFilterResult	AUCarbonViewControl::StdKeyFilterCallback(ControlRef theControl, 
+												SInt16 *keyCode, SInt16 *charCode, 
+												EventModifiers *modifiers)
+{
+#if !__LP64__
+	SInt16 c = *charCode;
+	if (c >= ' ' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f) || c == '\t')
+		return kControlKeyFilterPassKey;
+	if (c == '\r' || c == 3) {	// return or Enter
+		AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+		ControlEditTextSelectionRec sel = { 0, 32767 };
+		SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
+		This->ControlToParameter();
+	}
+#endif
+	return kControlKeyFilterBlockKey;
+}
+
+pascal ControlKeyFilterResult	AUCarbonViewControl::NumericKeyFilterCallback(ControlRef theControl, 
+												SInt16 *keyCode, SInt16 *charCode, 
+												EventModifiers *modifiers)
+{
+#if !__LP64__
+	SInt16 c = *charCode;
+	if (isdigit(c) || c == '+' || c == '-' || c == '.' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f)
+	|| c == '\t')
+		return kControlKeyFilterPassKey;
+	if (c == '\r' || c == 3) {	// return or Enter
+		AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+		ControlEditTextSelectionRec sel = { 0, 32767 };
+		SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
+		This->ControlToParameter();
+	}
+#endif
+	return kControlKeyFilterBlockKey;
+}
+
+Boolean	AUCarbonViewControl::SizeControlToFit(ControlRef inControl, SInt16 *outWidth, SInt16 *outHeight)
+{
+#if !__LP64__
+	if (inControl == 0) return false;
+	
+	Boolean bValue = false;
+	// this only works on text controls -- returns an error for other controls, but doesn't do anything,
+	// so the error is irrelevant
+	SetControlData(inControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
+	
+	SInt16 baseLineOffset;
+	Rect bestRect;
+	OSErr err = GetBestControlRect(inControl, &bestRect, &baseLineOffset);  
+	if (err != noErr) return false;
+	
+	int width = (bestRect.right - bestRect.left) + 1;
+	int height = (bestRect.bottom - bestRect.top) + 1;
+	
+	Rect boundsRect;
+	GetControlBounds (inControl, &boundsRect);
+	
+	Rect newRect;
+	newRect.top = boundsRect.top;
+	newRect.bottom = newRect.top + height;
+	newRect.left = boundsRect.left;
+	newRect.right = newRect.left + width;
+	
+	SetControlBounds (inControl, &newRect);
+	
+	if (outWidth)
+		*outWidth = width;
+	
+	if (outHeight)
+		*outHeight = height;
+#endif	
+	return true;
+}
+
+#pragma mark ___AUPropertyControl
+bool	AUPropertyControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{	
+	UInt32 eclass = GetEventClass(event);
+	UInt32 ekind = GetEventKind(event);
+	switch (eclass) {
+	case kEventClassControl:
+		switch (ekind) {
+		case kEventControlValueFieldChanged:
+			HandleControlChange();
+			return true;	// handled
+		}
+	}
+
+	return false;
+}
+
+void	AUPropertyControl::RegisterEvents ()
+{
+#if !__LP64__
+	EventTypeSpec events[] = {
+		{ kEventClassControl, kEventControlValueFieldChanged }	// N.B. OS X only
+	};
+	
+	WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+#endif
+}
+
+void	AUPropertyControl::EmbedControl (ControlRef theControl) 
+{ 
+	mView->EmbedControl (theControl); 
+}
+
+WindowRef 	AUPropertyControl::GetCarbonWindow()
+{
+	return mView->GetCarbonWindow();
+}
+
+#pragma mark ___AUVPreset
+#if !__LP64__
+static CFStringRef kStringFactoryPreset = kAUViewLocalizedStringKey_FactoryPreset;
+static bool sAUVPresetLocalized = false;
+#endif
+
+AUVPresets::AUVPresets (AUCarbonViewBase* 		inParentView, 
+						CFArrayRef& 			inPresets,
+						Point 					inLocation, 
+						int 					nameWidth, 
+						int 					controlWidth, 
+						ControlFontStyleRec & 	inFontStyle)
+	: AUPropertyControl (inParentView),
+	  mPresets (inPresets),
+	  mView (inParentView)
+{
+#if !__LP64__
+	Rect r;
+	
+	// ok we now have an array of factory presets
+	// get their strings and display them
+
+	r.top = inLocation.v;		r.bottom = r.top;
+	r.left = inLocation.h;		r.right = r.left;
+	
+    // localize as necessary
+    if (!sAUVPresetLocalized) {
+        CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
+        if (mainBundle) {
+            kStringFactoryPreset =	CFCopyLocalizedStringFromTableInBundle(
+                                        kAUViewLocalizedStringKey_FactoryPreset, kLocalizedStringTable_AUView,
+                                        mainBundle, CFSTR("FactoryPreset title string"));
+            sAUVPresetLocalized = true;
+        }
+    }
+    
+    // create localized title string
+    CFMutableStringRef factoryPresetsTitle = CFStringCreateMutable(NULL, 0);
+    CFStringAppend(factoryPresetsTitle, kStringFactoryPreset);
+    CFStringAppend(factoryPresetsTitle, kAUViewUnlocalizedString_TitleSeparator);
+    
+	ControlRef theControl;
+    verify_noerr(CreateStaticTextControl(mView->GetCarbonWindow(), &r, factoryPresetsTitle, &inFontStyle, &theControl));
+	SInt16 width = 0;
+	AUCarbonViewControl::SizeControlToFit(theControl, &width, &mHeight);
+    CFRelease(factoryPresetsTitle);
+	EmbedControl(theControl);
+	
+	r.top -= 2;
+	r.left += width + 10;
+	r.right = r.left;
+	r.bottom = r.top;
+	
+	verify_noerr(CreatePopupButtonControl (	mView->GetCarbonWindow(), &r, NULL, 
+											-12345,	// DON'T GET MENU FROM RESOURCE mMenuID,!!!
+											FALSE,	// variableWidth, 
+											0,		// titleWidth, 
+											0,		// titleJustification, 
+											0,		// titleStyle, 
+											&mControl));
+	
+	MenuRef menuRef;
+	verify_noerr(CreateNewMenu(1, 0, &menuRef));
+	
+	int numPresets = CFArrayGetCount(mPresets);
+	
+	for (int i = 0; i < numPresets; ++i)
+	{
+		AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
+		verify_noerr(AppendMenuItemTextWithCFString (menuRef, preset->presetName, 0, 0, 0));
+	}
+	
+	verify_noerr(SetControlData(mControl, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
+	verify_noerr (SetControlFontStyle (mControl, &inFontStyle));
+	
+	SetControl32BitMaximum (mControl, numPresets);
+	
+	// size popup
+	SInt16 height = 0;
+	
+	AUCarbonViewControl::SizeControlToFit(mControl, &width, &height);
+	
+	if (height > mHeight) mHeight = height;
+	if (mHeight < 0) mHeight = 0;
+	
+	// find which menu item is the Default preset
+	UInt32 propertySize = sizeof(AUPreset);
+	AUPreset defaultPreset;
+	OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(), 
+									kAudioUnitProperty_PresentPreset,
+									kAudioUnitScope_Global, 
+									0, 
+									&defaultPreset, 
+									&propertySize);
+	
+	mPropertyID = kAudioUnitProperty_PresentPreset;
+#endif	
+#ifndef __LP64__
+	if (result != noErr) {	// if the PresentPreset property is not implemented, fall back to the CurrentPreset property
+		OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(), 
+									kAudioUnitProperty_CurrentPreset,
+									kAudioUnitScope_Global, 
+									0, 
+									&defaultPreset, 
+									&propertySize);
+		mPropertyID = kAudioUnitProperty_CurrentPreset;
+		if (result == noErr)
+			CFRetain (defaultPreset.presetName);
+	} 
+#endif
+#if !__LP64__		
+	EmbedControl (mControl);
+	
+	HandlePropertyChange(defaultPreset);
+	
+	RegisterEvents();
+#endif
+}
+
+void	AUVPresets::AddInterest (AUEventListenerRef		inListener,
+											void *		inObject)
+{
+	AudioUnitEvent e;
+	e.mEventType = kAudioUnitEvent_PropertyChange;
+	e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
+	e.mArgument.mProperty.mPropertyID = mPropertyID;
+	e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
+	e.mArgument.mProperty.mElement = 0;
+	
+	AUEventListenerAddEventType(inListener, inObject, &e);
+}
+
+void	AUVPresets::RemoveInterest (AUEventListenerRef	inListener,
+											void *		inObject)
+{
+	AudioUnitEvent e;
+	e.mEventType = kAudioUnitEvent_PropertyChange;
+	e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
+	e.mArgument.mProperty.mPropertyID = mPropertyID;
+	e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
+	e.mArgument.mProperty.mElement = 0;
+
+	AUEventListenerRemoveEventType(inListener, inObject, &e);
+}
+
+void	AUVPresets::HandleControlChange ()
+{
+#if !__LP64__
+	SInt32 i = GetControl32BitValue(mControl);
+	if (i > 0)
+	{
+		AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i-1);
+	
+		verify_noerr(AudioUnitSetProperty (mView->GetEditAudioUnit(), 
+									mPropertyID,	// either currentPreset or PresentPreset depending on which is supported
+									kAudioUnitScope_Global, 
+									0, 
+									preset, 
+									sizeof(AUPreset)));
+									
+		// when we change a preset we can't expect the AU to update its state
+		// as it isn't meant to know that its being viewed!
+		// so we broadcast a notification to all listeners that all parameters on this AU have changed
+		AudioUnitParameter changedUnit;
+		changedUnit.mAudioUnit = mView->GetEditAudioUnit();
+		changedUnit.mParameterID = kAUParameterListener_AnyParameter;
+		verify_noerr (AUParameterListenerNotify (NULL, NULL, &changedUnit) );
+	}
+#endif
+}
+
+void	AUVPresets::HandlePropertyChange(AUPreset &preset) 
+{
+#if !__LP64__
+	// check to see if the preset is in our menu
+	int numPresets = CFArrayGetCount(mPresets);
+	if (preset.presetNumber < 0) {	
+		SetControl32BitValue (mControl, 0); //controls are one-based
+	} else {
+		for (SInt32 i = 0; i < numPresets; ++i) {
+			AUPreset* currPreset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
+			if (preset.presetNumber == currPreset->presetNumber) {
+				SetControl32BitValue (mControl, ++i); //controls are one-based
+				break;
+			}
+		}
+	}
+	
+	if (preset.presetName)
+		CFRelease (preset.presetName);
+#endif
+}
+
+bool	AUVPresets::HandlePropertyChange (const AudioUnitProperty &inProp)
+{
+	if (inProp.mPropertyID == mPropertyID) 
+	{
+		UInt32 theSize = sizeof(AUPreset);
+		AUPreset currentPreset;
+		
+		OSStatus result = AudioUnitGetProperty(inProp.mAudioUnit, 
+												inProp.mPropertyID, 
+												inProp.mScope, 
+												inProp.mElement, &currentPreset, &theSize);
+		
+		if (result == noErr) {
+#ifndef __LP64__
+			if (inProp.mPropertyID == kAudioUnitProperty_CurrentPreset && currentPreset.presetName)
+				CFRetain (currentPreset.presetName);
+#endif
+			HandlePropertyChange(currentPreset);
+			return true;
+		}
+	}
+	return false;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
new file mode 100644
index 0000000..3d5f975
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
@@ -0,0 +1,230 @@
+/*
+     File: AUCarbonViewControl.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUCarbonViewControl_h__
+#define __AUCarbonViewControl_h__
+
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnitCarbonView.h>
+#include <AudioToolbox/AudioUnitUtilities.h>
+#include "CarbonEventHandler.h"
+#include "CAAUParameter.h"
+
+class AUCarbonViewBase;
+
+// ____________________________________________________________________________
+//	AUCarbonViewControl
+//	Wrapper for a control that is wired to an AudioUnit parameter.
+	/*! @class AUCarbonViewControl */
+class AUCarbonViewControl : public CarbonEventHandler {
+	// note that the controls are never disposed; that's managed by the AUCarbonViewBase's
+	// parent pane which contains all of them ... if we later need to be able to delete
+	// individual controls on the fly, extra work needed
+public:
+	enum ControlType {
+		kTypeContinuous,	// e.g. slider
+		kTypeDiscrete,		// e.g. pop-up menu
+		kTypeText
+	};
+	
+	AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control);
+	~AUCarbonViewControl();
+
+	/*! @method Bind */
+	virtual void		Bind();		// second-stage construction
+
+	/*! @method ControlToParameter */
+	virtual void		ControlToParameter();
+	/*! @method ParameterToControl */
+	virtual void		ParameterToControl(Float32 newValue);
+	
+	/*! @method SetValueFract */
+	virtual void		SetValueFract(double value);
+	/*! @method GetValueFract */
+	virtual double		GetValueFract();
+	/*! @method SetTextValue */
+	virtual void		SetTextValue(CFStringRef str);
+	/*! @method GetTextValue */
+	virtual CFStringRef	GetTextValue();
+	/*! @method SetValue */
+	virtual void		SetValue(long value);
+	/*! @method GetValue */
+	virtual long		GetValue();
+	
+	/*! @method GetOwnerView */
+	AUCarbonViewBase * GetOwnerView() {return mOwnerView;}
+
+	/*! @method Update */
+	void				Update (bool inUIThread) 
+	{ 
+				if (inUIThread)
+					ParameterToControl (mParam.GetValue());
+				else
+					AUParameterListenerNotify (mListener, this, &mParam);
+	}
+	
+	
+	// CarbonEventHandler overrides
+	/*! @method HandleEvent */
+	virtual bool		HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+	
+	/*! @method ControlRef */
+	operator ControlRef() { return mControl; }
+	
+	/*! @method SizeControlToFit */
+	static Boolean SizeControlToFit(ControlRef inControl, SInt16 *outWidth = NULL, SInt16 *outHeight = NULL);
+	
+	/*! @method SliderTrackProc */
+	static pascal void SliderTrackProc(ControlRef theControl, ControlPartCode partCode);
+	/*! @method NumericKeyFilterCallback */
+	static pascal ControlKeyFilterResult NumericKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode, 
+															EventModifiers *modifiers);
+protected:
+	/*! @method ParamInfo */
+	const AudioUnitParameterInfo &ParamInfo() { return mParam.ParamInfo(); }
+
+	/*! @var mOwnerView */
+	AUCarbonViewBase * 		mOwnerView;
+	/*! @var mListener */
+	AUParameterListenerRef	mListener;
+	/*! @var mType */
+	ControlType				mType;
+	/*! @var mParam */
+	CAAUParameter			mParam;
+
+	/*! @var mControl */
+	ControlRef				mControl;
+	
+	/*! @method StdKeyFilterCallback */
+	static pascal ControlKeyFilterResult StdKeyFilterCallback(ControlRef theControl, SInt16 *keyCode,   SInt16 *charCode, 
+																										EventModifiers *modifiers);
+	SInt16					mInControlInitialization;
+	
+	static AUCarbonViewControl*	mLastControl;
+};
+
+	/*! @class AUPropertyControl */
+class AUPropertyControl : public CarbonEventHandler {
+public:
+	/*! @ctor AUPropertyControl */
+	AUPropertyControl (AUCarbonViewBase * 		inBase) : mControl(0), mView (inBase), mHeight(0) {}
+	
+	/*! @method HandleEvent */
+	virtual bool	HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+
+	/*! @method HandlePropertyChange */
+	virtual bool	HandlePropertyChange (const AudioUnitProperty &inProp) = 0;
+	
+	/*! @method AddInterest */
+	virtual void	AddInterest (AUEventListenerRef		inListener,
+								void *					inObject) = 0;
+	
+	/*! @method RemoveInterest */
+	virtual void	RemoveInterest  (AUEventListenerRef	inListener,
+								void *					inObject) = 0;
+	
+	/*! @method GetHeight */
+	int			GetHeight()	{ return mHeight;}
+	
+protected:
+	/*! @method HandleControlChange */
+	virtual void	HandleControlChange () = 0;	
+
+	/*! @method RegisterEvents */
+			void	RegisterEvents ();
+
+	/*! @method EmbedControl */
+			void	EmbedControl (ControlRef theControl);
+			
+	/*! @method GetCarbonWindow */
+	WindowRef 	GetCarbonWindow();
+
+	/*! @var mControl */
+	ControlRef			mControl;
+	/*! @var mView */
+	AUCarbonViewBase*	mView;
+	/*! @var mHeight */
+	SInt16				mHeight;
+};
+
+	/*! @class AUVPresets */
+class AUVPresets : public AUPropertyControl {
+public:
+					/*! @ctor HandleControlChange */
+					AUVPresets (AUCarbonViewBase * 		inBase, 
+								CFArrayRef& 			inPresets,
+								Point 					inLocation, 
+								int 					nameWidth, 
+								int 					controlWidth, 
+								ControlFontStyleRec & 	inFontStyle);
+
+					virtual ~AUVPresets () { CFRelease (mPresets); }
+
+	/*! @method HandlePropertyChange */
+	virtual bool	HandlePropertyChange (const AudioUnitProperty &inProp);
+	
+	/*! @method AddInterest */
+	virtual void	AddInterest (AUEventListenerRef		inListener,
+								void *					inObject);
+	
+	/*! @method RemoveInterest */
+	virtual void	RemoveInterest  (AUEventListenerRef	inListener,
+								void *					inObject);
+
+protected:
+	/*! @method HandleControlChange */
+	virtual void	HandleControlChange ();	
+			
+	/*! @var mPresets */
+	CFArrayRef			mPresets;
+	/*! @var mView */
+	AUCarbonViewBase*	mView;
+	AudioUnitPropertyID mPropertyID;
+
+	void	HandlePropertyChange(AUPreset &preset);
+};
+
+#endif // __AUCarbonViewControl_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
new file mode 100644
index 0000000..15a04e8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
@@ -0,0 +1,125 @@
+/*
+     File: AUCarbonViewDispatch.cpp
+ Abstract: AUCarbonViewDispatch.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUCarbonViewBase.h"
+
+// ____________________________________________________________________________
+// component dispatch
+
+#if PRAGMA_STRUCT_ALIGN
+	#pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+	#pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+	#pragma pack(2)
+#endif
+	struct AudioUnitCarbonViewCreateGluePB {
+		unsigned char                  componentFlags;
+		unsigned char                  componentParamSize;
+		short                          componentWhat;
+		ControlRef*                    outControl;
+		const Float32Point*            inSize;
+		const Float32Point*            inLocation;
+		ControlRef                     inParentControl;
+		WindowRef                      inWindow;
+		AudioUnit                      inAudioUnit;
+		AudioUnitCarbonView            inView;
+	};
+#if !__LP64__
+	struct AudioUnitCarbonViewSetEventListenerGluePB {
+		unsigned char                    componentFlags;
+		unsigned char                    componentParamSize;
+		short                            componentWhat;
+		void*                            inUserData;
+		AudioUnitCarbonViewEventListener inCallback;
+		AudioUnitCarbonView              inView;
+	};
+#endif
+#if PRAGMA_STRUCT_ALIGN
+	#pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+	#pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+	#pragma pack()
+#endif
+
+#define CheckNull(x) if ((x) == NULL) return paramErr;
+
+OSStatus		AUCarbonViewBase::ComponentEntryDispatch(ComponentParameters *p, AUCarbonViewBase *This)
+{
+	if (This == NULL) return paramErr;
+
+	OSStatus result = noErr;
+	
+	switch (p->what) {
+	case kAudioUnitCarbonViewCreateSelect:
+		{
+			AudioUnitCarbonViewCreateGluePB *pb = (AudioUnitCarbonViewCreateGluePB *)p;
+			CheckNull(pb->inAudioUnit);
+			CheckNull(pb->inWindow);
+			CheckNull(pb->inParentControl);
+			CheckNull(pb->inSize);
+			CheckNull(pb->inLocation);
+			CheckNull(pb->outControl);
+			result = This->CreateCarbonView(pb->inAudioUnit, pb->inWindow, pb->inParentControl, 
+					*pb->inLocation, *pb->inSize, *pb->outControl);
+		}
+		break;
+#if !__LP64__
+	case kAudioUnitCarbonViewSetEventListenerSelect:
+		{
+			AudioUnitCarbonViewSetEventListenerGluePB *pb = (AudioUnitCarbonViewSetEventListenerGluePB *)p;
+			This->SetEventListener(pb->inCallback, pb->inUserData);
+		}
+		break;
+#endif
+	
+	default:
+		result = ComponentBase::ComponentEntryDispatch(p, This);
+		break;
+	}
+	return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
new file mode 100644
index 0000000..8976b40
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
@@ -0,0 +1,359 @@
+/*
+     File: AUControlGroup.cpp
+ Abstract: AUControlGroup.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include <Carbon/Carbon.h>
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include "AUControlGroup.h"
+#include "AUViewLocalizedStringKeys.h"
+
+#define kSliderThinDimension 10
+#define kLabelAndSliderSpacing	4
+
+#if !__LP64__
+static CFStringRef kStringManufacturer = kAUViewLocalizedStringKey_Manufacturer;
+static bool sLocalized = false;
+#endif
+
+void	AUControlGroup::CreateLabelledSlider(
+										AUCarbonViewBase *			auView, 
+										const CAAUParameter &		auvp, 
+										const Rect &				area, 
+										Point 						labelSize, 
+										const ControlFontStyleRec &	inFontStyle)
+{
+#if !__LP64__
+	ControlFontStyleRec fontStyle = inFontStyle;
+	Rect minValRect, maxValRect, sliderRect;
+	ControlRef newControl;
+	int width = area.right - area.left, height = area.bottom - area.top;
+	CFStringRef cfstr;
+	int sliderValueMax, sliderValueMin, sliderValueDefault;
+	AUCarbonViewControl::ControlType sliderType;
+	
+	bool horizontal = (width > height);
+
+	if (horizontal) {
+		maxValRect.top = minValRect.top = area.top + (height - labelSize.v) / 2;
+		minValRect.left = area.left;
+		maxValRect.left = area.right - labelSize.h;
+		
+		minValRect.bottom = minValRect.top + labelSize.v;
+		minValRect.right = minValRect.left + labelSize.h;
+		maxValRect.bottom = maxValRect.top + labelSize.v;
+		maxValRect.right = maxValRect.left + labelSize.h;
+
+		sliderRect.left = minValRect.right + kLabelAndSliderSpacing;
+		sliderRect.right = maxValRect.left - kLabelAndSliderSpacing;
+		sliderRect.top = area.top + (height - kSliderThinDimension) / 2;
+		sliderRect.bottom = sliderRect.top + kSliderThinDimension + 4;
+
+		if (auvp.IsIndexedParam ()) {
+			sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
+			sliderValueMax = int(auvp.ParamInfo().maxValue);
+			sliderType = AUCarbonViewControl::kTypeDiscrete;
+		} else {
+			sliderValueMin = sliderValueDefault = 0;
+			sliderValueMax = sliderRect.right - sliderRect.left;
+			sliderType = AUCarbonViewControl::kTypeContinuous;
+		}
+	} else {
+		maxValRect.left = minValRect.left = area.left + (width - labelSize.h) / 2;
+		maxValRect.top = area.top;
+		minValRect.top = area.bottom - labelSize.v;
+		
+		minValRect.bottom = minValRect.top + labelSize.v;
+		minValRect.right = minValRect.left + labelSize.h;
+		maxValRect.bottom = maxValRect.top + labelSize.v;
+		maxValRect.right = maxValRect.left + labelSize.h;
+	
+		sliderRect.left = area.left + (width - kSliderThinDimension) / 2;
+		sliderRect.right = sliderRect.left + kSliderThinDimension + 4;
+		sliderRect.top = maxValRect.bottom + kLabelAndSliderSpacing;
+		sliderRect.bottom = minValRect.top - kLabelAndSliderSpacing;
+
+		if (auvp.IsIndexedParam ()) {
+			sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
+			sliderValueMax = int(auvp.ParamInfo().maxValue);			
+			sliderType = AUCarbonViewControl::kTypeDiscrete;
+		} else {
+			sliderValueMin = sliderValueDefault = 0;
+			sliderValueMax = sliderRect.bottom - sliderRect.top;
+			sliderType = AUCarbonViewControl::kTypeContinuous;
+		}
+	}
+
+	// minimum value label
+	if (labelSize.v > 0 && labelSize.h > 0) {
+		// check to see if the minimum value has a label
+		cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().minValue);
+		fontStyle.just = horizontal ? teFlushRight : teCenter;
+		verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &minValRect, cfstr, &fontStyle, &newControl));
+		CFRelease(cfstr);
+		verify_noerr(auView->EmbedControl(newControl));
+	
+		// maximum value label
+		cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().maxValue);
+		fontStyle.just = horizontal ? teFlushLeft : teCenter;
+		verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &maxValRect, cfstr, &fontStyle, &newControl));
+		CFRelease(cfstr);
+		verify_noerr(auView->EmbedControl(newControl));
+	}
+	
+	// slider
+	verify_noerr(CreateSliderControl(auView->GetCarbonWindow(), &sliderRect, sliderValueDefault, sliderValueMin, sliderValueMax, kControlSliderDoesNotPoint, 0, true, AUCarbonViewControl::SliderTrackProc, &newControl));
+
+
+	ControlSize small = kControlSizeSmall;
+	SetControlData(newControl, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
+	auView->AddCarbonControl(sliderType, auvp, newControl);
+#endif
+}
+
+void	AUControlGroup::CreateLabelledSliderAndEditText(
+										AUCarbonViewBase *			auView, 
+										const CAAUParameter &		auvp, 
+										const Rect &				area, 
+										Point 						labelSize, 
+										Point						editTextSize,
+										const ControlFontStyleRec &	inFontStyle)
+{
+#if !__LP64__
+	ControlFontStyleRec fontStyle = inFontStyle;
+	Rect sliderArea, textArea;
+	ControlRef newControl;
+	int width = area.right - area.left, height = area.bottom - area.top;
+	
+	bool horizontal = (width > height);
+
+	sliderArea = area;
+	textArea = area;
+	if (horizontal) {
+		textArea.left = area.right - editTextSize.h;
+			// provide a large text box if param is generic and its values have strings...
+		if (auvp.ValuesHaveStrings() && (auvp.ParamInfo().unit == kAudioUnitParameterUnit_Generic))
+		{
+			textArea.right += 30;
+		}
+		sliderArea.right = textArea.left - kLabelAndSliderSpacing;
+		textArea.top = area.top + (height - editTextSize.v) / 2;
+		textArea.bottom = textArea.top + editTextSize.v;
+	} else {
+		textArea.top = area.bottom - editTextSize.v;
+		sliderArea.bottom = textArea.top - kLabelAndSliderSpacing;
+		textArea.left = area.left + (width - editTextSize.h) / 2;
+		textArea.right = textArea.left + editTextSize.h;
+	}
+	CreateLabelledSlider(auView, auvp, sliderArea, labelSize, fontStyle);
+	
+	verify_noerr(CreateEditUnicodeTextControl(auView->GetCarbonWindow(), &textArea, CFSTR(""), false, 
+			&fontStyle, &newControl));
+	auView->AddCarbonControl(AUCarbonViewControl::kTypeText, auvp, newControl);
+#endif
+}
+
+void	AUControlGroup::CreatePopupMenu (AUCarbonViewBase *			auView, 
+										const CAAUParameter &		auvp, 
+										const Rect &				area, 
+										const ControlFontStyleRec &	inFontStyle,
+										const bool					inSizeToFit)
+{
+#if !__LP64__
+	ControlRef thePopUp;
+			
+	verify_noerr(CreatePopupButtonControl (auView->GetCarbonWindow(), &area, NULL, 
+												-12345,	// DON'T GET MENU FROM RESOURCE mMenuID
+												FALSE,	// variableWidth, 
+												0,		// titleWidth, 
+												0,		// titleJustification, 
+												0,		// titleStyle, 
+												&thePopUp));
+	
+	ControlSize small = kControlSizeSmall;
+	SetControlData(thePopUp, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
+	
+	MenuRef menuRef;
+	verify_noerr(CreateNewMenu( 1, 0, &menuRef));
+	
+	for (int i = 0; i < auvp.GetNumIndexedParams(); ++i) {
+		verify_noerr(AppendMenuItemTextWithCFString (menuRef, auvp.GetParamName(i), kMenuItemAttrIgnoreMeta, 0, 0));
+	}
+	
+	verify_noerr(SetControlData(thePopUp, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
+	SetControl32BitMaximum(thePopUp, auvp.GetNumIndexedParams());
+
+	verify_noerr (SetControlFontStyle (thePopUp, &inFontStyle));
+	
+	if (inSizeToFit) {
+		AUCarbonViewControl::SizeControlToFit(thePopUp);
+	}
+	
+	auView->AddCarbonControl(AUCarbonViewControl::kTypeDiscrete, auvp, thePopUp);
+#endif
+}
+
+void	AUControlGroup::AddAUInfo (		AUCarbonViewBase *			auView, 
+										const Point &				inLocation, 
+										const SInt16 				inRightOffset,
+										const SInt16				inTotalWidth)
+{
+#if !__LP64__
+   // get component info
+	ComponentDescription desc;
+    Handle h1 = NewHandleClear(4);
+	OSStatus err = GetComponentInfo ((Component)auView->GetEditAudioUnit(), &desc, h1, 0, 0);
+    
+    if (err == noErr) {        
+        // Get the manufacturer's name... look for the ':' character convention
+        HLock(h1);
+        char* ptr1 = *h1;
+        int len = *ptr1++;
+        char* displayStr = 0;
+        
+        for (int i = 0; i < len; ++i) {
+            if (ptr1[i] == ':') { // found the name
+                ptr1[i++] = 0;
+                displayStr = ptr1;
+                break;
+            }
+        }
+        
+        // localize as necessary:
+        if (!sLocalized) {
+            CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
+            if (mainBundle) {
+                kStringManufacturer = CFCopyLocalizedStringFromTableInBundle(
+                                            kAUViewLocalizedStringKey_Manufacturer, kLocalizedStringTable_AUView,
+                                            mainBundle, CFSTR("Manufacturer title string"));
+                sLocalized = true;
+            }
+        }
+        
+        // display strings
+        ControlRef newControl;
+        Rect r;
+        r.top = SInt16(inLocation.v);		r.bottom = SInt16(inLocation.v) + 16;
+        ControlFontStyleRec fontStyle;
+        fontStyle.flags = kControlUseFontMask | kControlUseJustMask;
+        fontStyle.font = kControlFontSmallBoldSystemFont;
+        
+        // display manufacturer string
+        if (displayStr) {
+            CFMutableStringRef mfrstring = CFStringCreateMutable(NULL, 0);
+            CFStringAppend(mfrstring, kStringManufacturer);		// "Manufacturer"
+            CFStringAppend(mfrstring, kAUViewUnlocalizedString_TitleSeparator);
+                                                                // "Manufacturer: "
+            CFStringRef mfrname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
+            if (mfrname) {
+                CFStringAppend(mfrstring, mfrname);	// "Manufacturer: MFRName"
+                CFRelease (mfrname);
+            }
+            
+            r.left = inLocation.h + inRightOffset;	
+			r.right = inLocation.h + inTotalWidth - 28;
+			fontStyle.just = teFlushRight;
+            
+            verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, mfrstring, &fontStyle, &newControl));
+            verify_noerr(auView->EmbedControl(newControl));
+            CFRelease (mfrstring);
+                                        
+            //move displayStr ptr past the manu, to the name
+            // we move the characters down an index, because the handle doesn't have any room
+            // at the end for the \0
+			int i = strlen(displayStr), j = 0;
+			while (displayStr[++i] == ' ' && i < len)
+				;
+			while (i < len)
+				displayStr[j++] = displayStr[i++];
+			displayStr[j] = 0;
+        } else {
+			displayStr = ptr1;
+			int i = 0, j = 0;
+			do {
+				displayStr[j] = displayStr[i];
+				++j; ++i;
+			} while (i < len);
+			
+			displayStr[j] = 0;
+        }
+        
+        // display AudioUnit string
+        r.left = inLocation.h;	r.right = r.left + inRightOffset;
+        fontStyle.just = 0;
+        
+        CFMutableStringRef cfstr = CFStringCreateMutable(NULL, 0);
+        CFStringAppend(cfstr, kAUViewLocalizedStringKey_AudioUnit);		// "Audio Unit"
+        CFStringAppend(cfstr, kAUViewUnlocalizedString_TitleSeparator);
+                                                        // "Audio Unit: "
+        
+		CFStringRef auname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
+		CFStringAppend(cfstr, auname);				// "Audio Unit: AUName"
+		CFRelease (auname);
+        
+        verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, cfstr, &fontStyle, &newControl));
+		
+		// size text control correctly
+		Boolean bValue = false;
+		SetControlData(newControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
+		SInt16 baseLineOffset;
+		Rect bestRect;
+		err = GetBestControlRect(newControl, &bestRect, &baseLineOffset);  
+		if (err == noErr)
+		{
+			int width = (bestRect.right - bestRect.left) + 1;
+			int height = (bestRect.bottom - bestRect.top) + 1;
+			SizeControl (newControl, width, height);
+		}
+		
+        verify_noerr(auView->EmbedControl(newControl));
+        CFRelease (cfstr);
+    }
+    
+	DisposeHandle (h1);
+#endif
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
new file mode 100644
index 0000000..0e16100
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
@@ -0,0 +1,90 @@
+/*
+     File: AUControlGroup.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUControlGroup_h__
+#define __AUControlGroup_h__
+
+#include <Carbon/Carbon.h>
+
+class AUCarbonViewBase;
+class CAAUParameter;
+
+// Utility class to create clusters of controls related to a single parameter
+	/*! @class AUControlGroup */
+class AUControlGroup {
+public:
+	/*! @method CreateLabelledSlider */
+	static void	CreateLabelledSlider(	AUCarbonViewBase *			auView, 
+										const CAAUParameter &		auvp, 
+										const Rect &				area, 
+										Point 						labelSize, 
+										const ControlFontStyleRec &	fontStyle);
+
+	/*! @method CreateLabelledSliderAndEditText */
+	static void CreateLabelledSliderAndEditText(
+										AUCarbonViewBase *			auView, 
+										const CAAUParameter &		auvp, 
+										const Rect &				area, 
+										Point 						labelSize, 
+										Point						editTextSize,
+										const ControlFontStyleRec &	fontStyle);
+
+	/*! @method CreatePopupMenu */
+	static void CreatePopupMenu (		AUCarbonViewBase *			auView, 
+										const CAAUParameter &		auvp, 
+										const Rect &				area, 
+										const ControlFontStyleRec &	inFontStyle,
+										const bool					inSizeToFit = false);
+
+	/*! @method AddAUInfo */
+	static void AddAUInfo (				AUCarbonViewBase *			auView, 
+										const Point &				inLocation, 
+										const SInt16 				inRightOffset,
+										const SInt16				inTotalWidth);
+};
+
+
+#endif // __AUControlGroup_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
new file mode 100644
index 0000000..fe9a731
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
@@ -0,0 +1,90 @@
+/*
+     File: CarbonEventHandler.cpp
+ Abstract: CarbonEventHandler.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CarbonEventHandler.h"
+
+static pascal OSStatus TheEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData)
+{
+	CarbonEventHandler *handler = (CarbonEventHandler *)inUserData;
+	if (handler->HandleEvent(inHandlerRef, inEvent))
+		return noErr;
+	else return eventNotHandledErr;
+}
+
+CarbonEventHandler::CarbonEventHandler() :
+	mHandlers(NULL)
+{
+}
+
+CarbonEventHandler::~CarbonEventHandler()
+{
+	if (mHandlers != NULL) {
+		int count = static_cast<int>(CFDictionaryGetCount(mHandlers));
+		EventHandlerRef *theHandlers = (EventHandlerRef*) malloc(count * sizeof(EventHandlerRef));
+		CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **)theHandlers);
+		
+		for (int i = 0; i < count; i++)
+			RemoveEventHandler(theHandlers[i]);
+		CFDictionaryRemoveAllValues(mHandlers);
+		CFRelease (mHandlers);
+		free(theHandlers);
+	}	
+}
+
+void	CarbonEventHandler::WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList)
+{
+	if (mHandlers == NULL)
+		mHandlers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+		
+	EventHandlerRef handler;
+	
+	if (CFDictionaryGetValueIfPresent (mHandlers, target, (const void **)&handler))	// if there is already a handler for the target, add the type
+		verify_noerr(AddEventTypesToHandler(handler, inNumTypes, inList));
+	else {
+		verify_noerr(InstallEventHandler(target, TheEventHandler, inNumTypes, inList, this, &handler));
+		CFDictionaryAddValue(mHandlers, target, handler);
+	}
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
new file mode 100644
index 0000000..9225e1a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
@@ -0,0 +1,71 @@
+/*
+     File: CarbonEventHandler.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CarbonEventHandler_h__
+#define __CarbonEventHandler_h__
+
+#include <Carbon/Carbon.h>
+
+	/*! @class CarbonEventHandler */
+class CarbonEventHandler {
+public:
+	/*! @ctor CarbonEventHandler */
+	CarbonEventHandler();
+	/*! @dtor ~CarbonEventHandler */
+	virtual ~CarbonEventHandler();
+	
+	/*! @method WantEventTypes */
+	virtual void	WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList);
+
+	/*! @method HandleEvent */
+	virtual bool	HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event) = 0;
+
+protected:
+	/*! @var mHandlers */
+	CFMutableDictionaryRef mHandlers;
+};
+
+#endif // __CarbonEventHandler_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
new file mode 100644
index 0000000..1ce8b30
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
@@ -0,0 +1,843 @@
+/*
+     File: AUInstrumentBase.cpp
+ Abstract: AUInstrumentBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUInstrumentBase.h"
+#include "AUMIDIDefs.h"
+
+#if DEBUG
+	#define DEBUG_PRINT 0
+	#define DEBUG_PRINT_NOTE 0
+	#define DEBUG_PRINT_RENDER 0
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const UInt32 kEventQueueSize = 1024;
+
+AUInstrumentBase::AUInstrumentBase(
+							AudioComponentInstance			inInstance, 
+							UInt32							numInputs,
+							UInt32							numOutputs,
+							UInt32							numGroups,
+							UInt32							numParts)
+	: MusicDeviceBase(inInstance, numInputs, numOutputs, numGroups), 
+	mAbsoluteSampleFrame(0),
+	mEventQueue(kEventQueueSize),
+	mNumNotes(0),
+	mNumActiveNotes(0),
+	mMaxActiveNotes(0),
+	mNotes(0),
+	mNoteSize(0),
+	mInitNumPartEls(numParts)
+{
+#if DEBUG_PRINT
+	printf("new AUInstrumentBase\n");
+#endif
+	mFreeNotes.mState = kNoteState_Free;
+	SetWantsRenderThreadID(true);
+}
+	
+
+AUInstrumentBase::~AUInstrumentBase()
+{
+#if DEBUG_PRINT
+	printf("delete AUInstrumentBase\n");
+#endif
+}
+
+AUElement *	AUInstrumentBase::CreateElement(AudioUnitScope inScope, AudioUnitElement element)
+{
+	switch (inScope)
+	{
+		case kAudioUnitScope_Group:
+			return new SynthGroupElement(this, element, new MidiControls);
+		case kAudioUnitScope_Part:
+			return new SynthPartElement (this, element);
+	}
+	return MusicDeviceBase::CreateElement(inScope, element);
+}
+
+void		AUInstrumentBase::CreateExtendedElements() 
+{
+	Parts().Initialize(this, kAudioUnitScope_Part, mInitNumPartEls);
+}
+
+AUScope *	AUInstrumentBase::GetScopeExtended (AudioUnitScope inScope) 
+{
+	if (inScope == kAudioUnitScope_Part)
+		return &mPartScope;
+	return NULL;
+}
+
+
+void		AUInstrumentBase::SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteDataSize)
+{
+#if DEBUG_PRINT_NOTE
+	printf("AUInstrumentBase::SetNotes %d %d %p %d\n", inNumNotes, inMaxActiveNotes, inNotes, inNoteDataSize);
+#endif
+	mNumNotes = inNumNotes;
+	mMaxActiveNotes = inMaxActiveNotes;
+	mNoteSize = inNoteDataSize;
+	mNotes = inNotes;
+	
+	for (UInt32 i=0; i<mNumNotes; ++i)
+	{
+			SynthNote *note = GetNote(i);
+			note->Reset();
+			mFreeNotes.AddNote(note);
+	}
+}
+
+UInt32		AUInstrumentBase::CountActiveNotes()
+{
+	// debugging tool.
+	UInt32 sum = 0;
+	for (UInt32 i=0; i<mNumNotes; ++i)
+	{
+		SynthNote *note = GetNote(i);
+		if (note->GetState() <= kNoteState_Released) 
+			sum++;
+	}
+	return sum;
+}
+
+void		AUInstrumentBase::AddFreeNote(SynthNote* inNote)
+{
+	// Fast-released notes are already considered inactive and have already decr'd the active count
+	if (inNote->GetState() < kNoteState_FastReleased) {
+		DecNumActiveNotes();
+	}
+#if DEBUG_PRINT_NOTE
+	else {
+			printf("AUInstrumentBase::AddFreeNote: adding fast-released note %p\n", inNote);
+	}
+	printf("AUInstrumentBase::AddFreeNote (%p)  mNumActiveNotes %lu\n", inNote, mNumActiveNotes);
+#endif
+	mFreeNotes.AddNote(inNote);
+}
+
+OSStatus			AUInstrumentBase::Initialize()
+{
+/*
+TO DO:
+	Currently ValidFormat will check and validate that the num channels is not being
+	changed if the AU doesn't support the SupportedNumChannels property - which is correct
+	
+	What needs to happen here is that IFF the AU does support this property, (ie, the AU
+	can be configured to have different num channels than its original configuration) then
+	the state of the AU at Initialization needs to be validated.
+	
+	This is work still to be done - see AUEffectBase for the kind of logic that needs to be applied here
+*/
+
+	// override to call SetNotes
+	
+	mNoteIDCounter = 128; // reset this every time we initialise
+	mAbsoluteSampleFrame = 0;
+	return noErr;
+}
+
+void				AUInstrumentBase::Cleanup()
+{
+	mFreeNotes.Empty();
+}
+
+
+OSStatus			AUInstrumentBase::Reset(			AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement)
+{
+#if DEBUG_PRINT
+	printf("AUInstrumentBase::Reset\n");
+#endif
+	if (inScope == kAudioUnitScope_Global)
+	{
+		// kill all notes..
+		mFreeNotes.Empty();
+		for (UInt32 i=0; i<mNumNotes; ++i)
+		{
+			SynthNote *note = GetNote(i);
+			if (note->IsSounding()) 
+				note->Kill(0);
+			note->ListRemove();
+			mFreeNotes.AddNote(note);
+		}
+		mNumActiveNotes = 0;
+		mAbsoluteSampleFrame = 0;
+
+		// empty lists.
+		UInt32 numGroups = Groups().GetNumberOfElements();
+		for (UInt32 j = 0; j < numGroups; ++j)
+		{
+			SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+			group->Reset();
+		}
+	}
+	return MusicDeviceBase::Reset(inScope, inElement);
+}
+
+void		AUInstrumentBase::PerformEvents(const AudioTimeStamp& inTimeStamp)
+{
+#if DEBUG_PRINT_RENDER
+	printf("AUInstrumentBase::PerformEvents\n");
+#endif
+	SynthEvent *event;
+	SynthGroupElement *group;
+	
+	while ((event = mEventQueue.ReadItem()) != NULL)
+	{
+#if DEBUG_PRINT_RENDER
+		printf("event %08X %d\n", event, event->GetEventType());
+#endif
+		switch(event->GetEventType())
+		{
+			case SynthEvent::kEventType_NoteOn :
+				RealTimeStartNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(),
+									event->GetOffsetSampleFrame(), *event->GetParams());
+				break;
+			case SynthEvent::kEventType_NoteOff :
+				RealTimeStopNote(event->GetGroupID(), event->GetNoteID(),
+					event->GetOffsetSampleFrame());
+				break;
+			case SynthEvent::kEventType_SustainOn :
+				group = GetElForGroupID (event->GetGroupID());
+				group->SustainOn(event->GetOffsetSampleFrame());
+				break;
+			case SynthEvent::kEventType_SustainOff :
+				group = GetElForGroupID (event->GetGroupID());
+				group->SustainOff(event->GetOffsetSampleFrame());
+				break;
+			case SynthEvent::kEventType_SostenutoOn :
+				group = GetElForGroupID (event->GetGroupID());
+				group->SostenutoOn(event->GetOffsetSampleFrame());
+				break;
+			case SynthEvent::kEventType_SostenutoOff :
+				group = GetElForGroupID (event->GetGroupID());
+				group->SostenutoOff(event->GetOffsetSampleFrame());
+				break;
+			case SynthEvent::kEventType_AllNotesOff :
+				group = GetElForGroupID (event->GetGroupID());
+				group->AllNotesOff(event->GetOffsetSampleFrame());
+				break;
+			case SynthEvent::kEventType_AllSoundOff :
+				group = GetElForGroupID (event->GetGroupID());
+				group->AllSoundOff(event->GetOffsetSampleFrame());
+				break;
+			case SynthEvent::kEventType_ResetAllControllers :
+				group = GetElForGroupID (event->GetGroupID());
+				group->ResetAllControllers(event->GetOffsetSampleFrame());
+				break;
+		}
+		
+		mEventQueue.AdvanceReadPtr();
+	}
+}
+
+														
+OSStatus			AUInstrumentBase::Render(   AudioUnitRenderActionFlags &	ioActionFlags,
+												const AudioTimeStamp &			inTimeStamp,
+												UInt32							inNumberFrames)
+{
+	PerformEvents(inTimeStamp);
+
+	AUScope &outputs = Outputs();
+	UInt32 numOutputs = outputs.GetNumberOfElements();
+	for (UInt32 j = 0; j < numOutputs; ++j)
+	{
+		GetOutput(j)->PrepareBuffer(inNumberFrames);	// AUBase::DoRenderBus() only does this for the first output element
+		AudioBufferList& bufferList = GetOutput(j)->GetBufferList();
+		for (UInt32 k = 0; k < bufferList.mNumberBuffers; ++k)
+		{
+			memset(bufferList.mBuffers[k].mData, 0, bufferList.mBuffers[k].mDataByteSize);
+		}
+	}
+	UInt32 numGroups = Groups().GetNumberOfElements();
+	for (UInt32 j = 0; j < numGroups; ++j)
+	{
+		SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+		OSStatus err = group->Render((SInt64)inTimeStamp.mSampleTime, inNumberFrames, outputs);
+		if (err) return err;
+	}
+	mAbsoluteSampleFrame += inNumberFrames;
+	return noErr;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//	AUInstrumentBase::ValidFormat
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+bool				AUInstrumentBase::ValidFormat(	AudioUnitScope					inScope,
+													AudioUnitElement				inElement,
+													const CAStreamBasicDescription  & inNewFormat)
+{	
+		// if the AU supports this, then we should just let this go through to the Init call
+	if (SupportedNumChannels (NULL)) 
+		return MusicDeviceBase::ValidFormat(inScope, inElement, inNewFormat);
+
+	bool isGood = MusicDeviceBase::ValidFormat (inScope, inElement, inNewFormat);
+	if (!isGood) return false;
+	
+		// if we get to here, then the basic criteria is that the
+		// num channels cannot change on an existing bus
+	AUIOElement *el = GetIOElement (inScope, inElement);
+	return (el->GetStreamFormat().NumberChannels() == inNewFormat.NumberChannels()); 
+}
+
+
+bool				AUInstrumentBase::StreamFormatWritable(	AudioUnitScope					scope,
+															AudioUnitElement				element)
+{
+	return IsInitialized() ? false : true;
+}
+
+OSStatus			AUInstrumentBase::RealTimeStartNote(	SynthGroupElement 			*inGroup,
+															NoteInstanceID 				inNoteInstanceID, 
+															UInt32 						inOffsetSampleFrame, 
+															const MusicDeviceNoteParams &inParams)
+{
+	return noErr;
+}
+
+SynthPartElement *	AUInstrumentBase::GetPartElement (AudioUnitElement inPartElement)
+{
+	AUScope & parts = Parts();
+	unsigned int numEls = parts.GetNumberOfElements();
+	for (unsigned int i = 0; i < numEls; ++i) {
+		SynthPartElement* el = reinterpret_cast<SynthPartElement*>(parts.GetElement(i));
+		if (el->GetIndex() == inPartElement) {
+			return el;
+		}
+	}
+	return NULL;
+}
+
+SynthGroupElement *	AUInstrumentBase::GetElForGroupID (MusicDeviceGroupID	inGroupID)
+{
+	AUScope & groups = Groups();
+	unsigned int numEls = groups.GetNumberOfElements();
+	SynthGroupElement* unassignedEl = NULL;
+	
+	for (unsigned int i = 0; i < numEls; ++i) {
+		SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
+		if (el->GroupID() == inGroupID) 
+			return el;
+		if (el->GroupID() == SynthGroupElement::kUnassignedGroup) {
+			unassignedEl = el;
+			break; // we fill this up from the start of the group scope vector
+		}
+	}
+	if (unassignedEl) {
+		unassignedEl->SetGroupID(inGroupID);
+		return unassignedEl;
+	}
+	throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus			AUInstrumentBase::RealTimeStopNote(
+												MusicDeviceGroupID 			inGroupID, 
+												NoteInstanceID 				inNoteInstanceID, 
+												UInt32 						inOffsetSampleFrame)
+{
+#if DEBUG_PRINT
+	printf("AUInstrumentBase::RealTimeStopNote ch %d id %d\n", inGroupID, inNoteInstanceID);
+#endif
+	
+	SynthGroupElement *gp = (inGroupID == kMusicNoteEvent_Unused
+								? GetElForNoteID (inNoteInstanceID)
+								: GetElForGroupID(inGroupID));
+	if (gp)
+	{
+		gp->NoteOff (inNoteInstanceID, inOffsetSampleFrame);
+	}
+	
+	return noErr;
+}
+
+SynthGroupElement *	AUInstrumentBase::GetElForNoteID (NoteInstanceID inNoteID)
+{
+#if DEBUG_PRINT
+	printf("GetElForNoteID id %u\n", inNoteID);
+#endif
+	AUScope & groups = Groups();
+	unsigned int numEls = groups.GetNumberOfElements();
+	
+	for (unsigned int i = 0; i < numEls; ++i) {
+		SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
+		if (el->GetNote(inNoteID) != NULL)	// searches for any note state
+			return el;
+	}
+	throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus			AUInstrumentBase::StartNote(	MusicDeviceInstrumentID 	inInstrument, 
+													MusicDeviceGroupID 			inGroupID, 
+													NoteInstanceID *			outNoteInstanceID, 
+													UInt32 						inOffsetSampleFrame, 
+													const MusicDeviceNoteParams &inParams)
+{
+	OSStatus err = noErr;
+	
+	NoteInstanceID noteID; 
+	if (outNoteInstanceID) {
+		noteID = NextNoteID();
+		*outNoteInstanceID = noteID;
+	} else
+		noteID = (UInt32)inParams.mPitch;
+	
+#if DEBUG_PRINT
+	printf("AUInstrumentBase::StartNote ch %u, key %u, offset %u\n", inGroupID, (unsigned) inParams.mPitch, inOffsetSampleFrame);
+#endif
+
+	if (InRenderThread ())
+	{		
+		err = RealTimeStartNote(
+					GetElForGroupID(inGroupID),
+					noteID,
+					inOffsetSampleFrame,
+					inParams);
+	}
+	else
+	{
+		SynthEvent *event = mEventQueue.WriteItem();
+		if (!event) return -1; // queue full
+
+		event->Set(
+			SynthEvent::kEventType_NoteOn,
+			inGroupID,
+			noteID,
+			inOffsetSampleFrame,
+			&inParams
+		);
+		
+		mEventQueue.AdvanceWritePtr();
+	}
+	return err;
+}
+
+OSStatus			AUInstrumentBase::StopNote( MusicDeviceGroupID 			inGroupID, 
+												NoteInstanceID 				inNoteInstanceID, 
+												UInt32 						inOffsetSampleFrame)
+{
+#if DEBUG_PRINT
+	printf("AUInstrumentBase::StopNote ch %u, id %u, offset %u\n", (unsigned)inGroupID, (unsigned)inNoteInstanceID, inOffsetSampleFrame);
+#endif
+	OSStatus err = noErr;
+
+	if (InRenderThread ())
+	{		
+		err = RealTimeStopNote(
+			inGroupID,
+			inNoteInstanceID,
+			inOffsetSampleFrame);
+	}
+	else
+	{
+		SynthEvent *event = mEventQueue.WriteItem();
+		if (!event) return -1; // queue full
+
+		event->Set(
+			SynthEvent::kEventType_NoteOff,
+			inGroupID,
+			inNoteInstanceID,
+			inOffsetSampleFrame,
+			NULL
+		);
+		
+		mEventQueue.AdvanceWritePtr();
+	}
+	return err;
+}
+
+OSStatus	AUInstrumentBase::SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame)
+{
+	
+	if (InRenderThread ())
+	{
+		SynthGroupElement *group = GetElForGroupID(inGroupID);
+		if (!group)
+			return kAudioUnitErr_InvalidElement;
+		
+		switch (inEventType)
+		{
+			case SynthEvent::kEventType_SustainOn :
+				group->SustainOn(inOffsetSampleFrame);
+				break;
+			case SynthEvent::kEventType_SustainOff :
+				group->SustainOff(inOffsetSampleFrame);
+				break;
+			case SynthEvent::kEventType_SostenutoOn :
+				group->SostenutoOn(inOffsetSampleFrame);
+				break;
+			case SynthEvent::kEventType_SostenutoOff :
+				group->SostenutoOff(inOffsetSampleFrame);
+				break;
+			case SynthEvent::kEventType_AllNotesOff :
+				group->AllNotesOff(inOffsetSampleFrame);
+				mNumActiveNotes = CountActiveNotes();
+				break;
+			case SynthEvent::kEventType_AllSoundOff :
+				group->AllSoundOff(inOffsetSampleFrame);
+				mNumActiveNotes = CountActiveNotes();
+				break;
+			case SynthEvent::kEventType_ResetAllControllers :
+				group->ResetAllControllers(inOffsetSampleFrame);
+				break;
+		}
+	}
+	else
+	{
+		SynthEvent *event = mEventQueue.WriteItem();
+		if (!event) return -1; // queue full
+
+		event->Set(inEventType, inGroupID, 0, 0, NULL);
+		
+		mEventQueue.AdvanceWritePtr();
+	}
+	return noErr;
+}
+
+OSStatus	AUInstrumentBase::HandleControlChange(	UInt8 	inChannel,
+													UInt8 	inController,
+													UInt8 	inValue,
+													UInt32	inStartFrame)
+{
+#if DEBUG_PRINT
+	printf("AUInstrumentBase::HandleControlChange ch %u ctlr: %u val: %u frm: %u\n", inChannel, inController, inValue, inStartFrame);
+#endif
+	SynthGroupElement *gp = GetElForGroupID(inChannel);
+	if (gp)
+	{
+		gp->ChannelMessage(inController, inValue);
+	}
+	else
+		return kAudioUnitErr_InvalidElement;
+	switch (inController)
+	{
+		case kMidiController_Sustain :
+			if (inValue >= 64)
+				SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOn, inStartFrame);
+			else
+				SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOff, inStartFrame);
+			break;
+		case kMidiController_Sostenuto :
+			if (inValue >= 64)
+				SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOn, inStartFrame);
+			else
+				SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOff, inStartFrame);
+			break;
+        case kMidiController_OmniModeOff:
+        case kMidiController_OmniModeOn:
+        case kMidiController_MonoModeOn:
+        case kMidiController_MonoModeOff:
+            HandleAllSoundOff(inChannel);
+            break;
+	}
+	return noErr;
+}
+												
+OSStatus	AUInstrumentBase::HandlePitchWheel(		UInt8 	inChannel,
+													UInt8 	inPitch1,	// LSB
+													UInt8 	inPitch2,	// MSB
+													UInt32	inStartFrame)
+{
+	SynthGroupElement *gp = GetElForGroupID(inChannel);
+	if (gp)
+	{
+		gp->ChannelMessage(kMidiMessage_PitchWheel, (inPitch2 << 7) | inPitch1);
+		return noErr;
+	}
+	else
+		return kAudioUnitErr_InvalidElement;
+}
+
+												
+OSStatus	AUInstrumentBase::HandleChannelPressure(UInt8 	inChannel,
+													UInt8 	inValue,
+													UInt32	inStartFrame)
+{
+	SynthGroupElement *gp = GetElForGroupID(inChannel);
+	if (gp)
+	{
+		gp->ChannelMessage(kMidiMessage_ChannelPressure, inValue);
+		return noErr;
+	}
+	else
+		return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus	AUInstrumentBase::HandleProgramChange(	UInt8 	inChannel,
+													UInt8 	inValue)
+{
+#if DEBUG_PRINT
+	printf("AUInstrumentBase::HandleProgramChange %u %u\n", inChannel, inValue);
+#endif
+	SynthGroupElement *gp = GetElForGroupID(inChannel);
+	if (gp)
+	{
+		gp->ChannelMessage(kMidiMessage_ProgramChange, inValue);
+		return noErr;
+	}
+	else
+		return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus	AUInstrumentBase::HandlePolyPressure(	UInt8 	inChannel,
+													UInt8 	inKey,
+													UInt8	inValue,
+													UInt32	inStartFrame)
+{
+	SynthGroupElement *gp = GetElForGroupID(inChannel);
+	if (gp)
+	{
+		// Combine key and value into single argument.  UGLY!
+		gp->ChannelMessage(kMidiMessage_PolyPressure, (inKey << 7) | inValue);
+		return noErr;
+	}
+	else
+		return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus	AUInstrumentBase::HandleResetAllControllers(	UInt8 	inChannel)
+{
+	return SendPedalEvent (inChannel, SynthEvent::kEventType_ResetAllControllers, 0);
+}
+
+	
+OSStatus	AUInstrumentBase::HandleAllNotesOff(			UInt8 	inChannel)
+{
+	return SendPedalEvent (inChannel, SynthEvent::kEventType_AllNotesOff, 0);
+}
+
+	
+OSStatus	AUInstrumentBase::HandleAllSoundOff(			UInt8 	inChannel)
+{
+	return SendPedalEvent (inChannel, SynthEvent::kEventType_AllSoundOff, 0);
+}
+
+SynthNote*  AUInstrumentBase::GetAFreeNote(UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+	printf("AUInstrumentBase::GetAFreeNote:  %lu available\n", mFreeNotes.Length());
+#endif
+	SynthNote *note = mFreeNotes.mHead;
+	if (note)
+	{
+		mFreeNotes.RemoveNote(note);
+		return note;
+	}
+	
+	return VoiceStealing(inFrame, true);
+}
+
+SynthNote*  AUInstrumentBase::VoiceStealing(UInt32 inFrame, bool inKillIt)
+{
+
+#if DEBUG_PRINT_NOTE
+	printf("AUInstrumentBase::VoiceStealing\n");
+#endif
+	// free list was empty so we need to kill a note.
+	UInt32 startState = inKillIt ? kNoteState_FastReleased : kNoteState_Released;
+	for (UInt32 i = startState; i <= startState; --i)
+	{
+#if DEBUG_PRINT_NOTE
+		printf(" checking state %d...\n", i);
+#endif
+		UInt32 numGroups = Groups().GetNumberOfElements();
+		for (UInt32 j = 0; j < numGroups; ++j)
+		{
+			SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+#if DEBUG_PRINT_NOTE
+			printf("\tsteal group %d   size %d\n", j, group->mNoteList[i].Length());
+#endif
+			if (group->mNoteList[i].NotEmpty()) {
+#if DEBUG_PRINT_NOTE
+				printf("\t-- not empty\n");
+#endif
+				SynthNote *note = group->mNoteList[i].FindMostQuietNote();
+				if (inKillIt) {
+#if DEBUG_PRINT_NOTE
+					printf("\t--=== KILL ===---\n");
+#endif
+					note->Kill(inFrame);
+					group->mNoteList[i].RemoveNote(note);
+					if (i != kNoteState_FastReleased)
+						DecNumActiveNotes();
+					return note;
+				} else {
+#if DEBUG_PRINT_NOTE
+					printf("\t--=== FAST RELEASE ===---\n");
+#endif
+					group->mNoteList[i].RemoveNote(note);
+					note->FastRelease(inFrame);
+					group->mNoteList[kNoteState_FastReleased].AddNote(note);
+					DecNumActiveNotes(); // kNoteState_FastReleased counts as inactive for voice stealing purposes.
+					return NULL;
+				}
+			}
+		}
+	}
+#if DEBUG_PRINT_NOTE
+	printf("no notes to steal????\n");
+#endif
+	return NULL; // It should be impossible to get here. It means there were no notes to kill in any state. 
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+AUMonotimbralInstrumentBase::AUMonotimbralInstrumentBase(
+							AudioComponentInstance			inInstance, 
+							UInt32							numInputs,
+							UInt32							numOutputs,
+							UInt32							numGroups,
+							UInt32							numParts)
+	: AUInstrumentBase(inInstance, numInputs, numOutputs, numGroups, numParts)
+{
+}
+
+OSStatus			AUMonotimbralInstrumentBase::RealTimeStartNote(	
+															SynthGroupElement 			*inGroup, 
+															NoteInstanceID 				inNoteInstanceID, 
+															UInt32 						inOffsetSampleFrame, 
+															const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT_RENDER
+	printf("AUMonotimbralInstrumentBase::RealTimeStartNote %d\n", inNoteInstanceID);
+#endif
+
+	if (NumActiveNotes() + 1 > MaxActiveNotes()) 
+	{
+		VoiceStealing(inOffsetSampleFrame, false);
+	}
+	SynthNote *note = GetAFreeNote(inOffsetSampleFrame);
+	if (!note) return -1;
+	
+	SynthPartElement *part = GetPartElement (0);	// Only one part for monotimbral
+	
+	IncNumActiveNotes();
+	inGroup->NoteOn(note, part, inNoteInstanceID, inOffsetSampleFrame, inParams);
+	
+	return noErr;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+OSStatus			AUMultitimbralInstrumentBase::GetPropertyInfo(AudioUnitPropertyID	inID,
+												AudioUnitScope				inScope,
+												AudioUnitElement			inElement,
+												UInt32 &					outDataSize,
+												Boolean &					outWritable)
+{
+	OSStatus result = noErr;
+	
+	switch (inID) 
+	{
+#if !TARGET_OS_IPHONE
+		case kMusicDeviceProperty_PartGroup:
+			if (inScope != kAudioUnitScope_Part) return kAudioUnitErr_InvalidScope;
+			outDataSize = sizeof(UInt32);
+			outWritable = true;
+			break;
+#endif
+		default:
+			result = AUInstrumentBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+	}
+	return result;
+}
+
+OSStatus			AUMultitimbralInstrumentBase::GetProperty(	AudioUnitPropertyID 	inID,
+												AudioUnitScope 				inScope,
+												AudioUnitElement		 	inElement,
+												void *						outData)
+{
+	OSStatus result = noErr;
+
+	switch (inID) 
+	{
+#if !TARGET_OS_IPHONE
+		case kMusicDeviceProperty_PartGroup:
+			if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+			// ??
+			return -1; //unimpl
+			break;
+#endif
+		default:
+			result = AUInstrumentBase::GetProperty (inID, inScope, inElement, outData);
+	}
+	
+	return result;
+}
+
+
+
+OSStatus			AUMultitimbralInstrumentBase::SetProperty(  AudioUnitPropertyID 			inID,
+																AudioUnitScope 					inScope,
+																AudioUnitElement 				inElement,
+																const void *					inData,
+																UInt32 							inDataSize)
+{
+	OSStatus result = noErr;
+
+	switch (inID) 
+	{
+#if !TARGET_OS_IPHONE
+		case kMusicDeviceProperty_PartGroup:
+			if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+			// ??
+			return -1; //unimpl
+			break;
+#endif
+		default:
+			result = MusicDeviceBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+	}
+	
+	return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
new file mode 100644
index 0000000..3ad7e03
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
@@ -0,0 +1,269 @@
+/*
+     File: AUInstrumentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUInstrumentBase__
+#define __AUInstrumentBase__
+
+#include <vector>
+#include <stdexcept>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include <libkern/OSAtomic.h>
+#include "MusicDeviceBase.h"
+#include "LockFreeFIFO.h"
+#include "SynthEvent.h"
+#include "SynthNote.h"
+#include "SynthElement.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef LockFreeFIFOWithFree<SynthEvent> SynthEventQueue;
+
+class AUInstrumentBase : public MusicDeviceBase
+{
+public:
+			AUInstrumentBase(
+							AudioComponentInstance			inInstance, 
+							UInt32							numInputs,
+							UInt32							numOutputs,
+							UInt32							numGroups = 16,
+							UInt32							numParts = 1);
+	virtual ~AUInstrumentBase();
+
+	virtual OSStatus			Initialize();
+	
+	/*! @method Parts */
+	AUScope &					Parts()	{ return mPartScope; }
+
+	/*! @method GetPart */
+	AUElement *					GetPart( AudioUnitElement inElement)
+	{
+		return mPartScope.SafeGetElement(inElement);
+	}
+
+	virtual AUScope *			GetScopeExtended (AudioUnitScope inScope);
+
+	virtual AUElement *			CreateElement(			AudioUnitScope					inScope,
+														AudioUnitElement				inElement);
+
+	virtual void				CreateExtendedElements();
+
+	virtual void				Cleanup();
+	
+	virtual OSStatus			Reset(					AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement);
+														
+	virtual bool				ValidFormat(			AudioUnitScope					inScope,
+														AudioUnitElement				inElement,
+														const CAStreamBasicDescription  & inNewFormat);
+
+	virtual bool				StreamFormatWritable(	AudioUnitScope					scope,
+														AudioUnitElement				element);
+
+	virtual bool				CanScheduleParameters() const { return false; }
+
+	virtual OSStatus			Render(					AudioUnitRenderActionFlags &	ioActionFlags,
+														const AudioTimeStamp &			inTimeStamp,
+														UInt32							inNumberFrames);
+
+	virtual OSStatus			StartNote(		MusicDeviceInstrumentID 	inInstrument, 
+												MusicDeviceGroupID 			inGroupID, 
+												NoteInstanceID *			outNoteInstanceID, 
+												UInt32 						inOffsetSampleFrame, 
+												const MusicDeviceNoteParams &inParams);
+
+	virtual OSStatus			StopNote(		MusicDeviceGroupID 			inGroupID, 
+												NoteInstanceID 				inNoteInstanceID, 
+												UInt32 						inOffsetSampleFrame);
+
+	virtual OSStatus			RealTimeStartNote(		SynthGroupElement 			*inGroup,
+														NoteInstanceID 				inNoteInstanceID, 
+														UInt32 						inOffsetSampleFrame, 
+														const MusicDeviceNoteParams &inParams);
+	
+	virtual OSStatus			RealTimeStopNote(		MusicDeviceGroupID 			inGroupID, 
+														NoteInstanceID 				inNoteInstanceID, 
+														UInt32 						inOffsetSampleFrame);
+	
+	virtual OSStatus	HandleControlChange(	UInt8	inChannel,
+												UInt8 	inController,
+												UInt8 	inValue,
+												UInt32	inStartFrame);
+												
+	virtual OSStatus	HandlePitchWheel(		UInt8 	inChannel,
+												UInt8 	inPitch1,
+												UInt8 	inPitch2,
+												UInt32	inStartFrame);
+												
+	virtual OSStatus	HandleChannelPressure(	UInt8 	inChannel,
+												UInt8 	inValue,
+												UInt32	inStartFrame);
+
+	virtual OSStatus	HandleProgramChange(	UInt8	inChannel,
+												UInt8 	inValue);
+
+	virtual OSStatus	HandlePolyPressure(		UInt8 	inChannel,
+												UInt8 	inKey,
+												UInt8	inValue,
+												UInt32	inStartFrame);
+
+	virtual OSStatus	HandleResetAllControllers(		UInt8 	inChannel);
+	
+	virtual OSStatus	HandleAllNotesOff(				UInt8 	inChannel);
+	
+	virtual OSStatus	HandleAllSoundOff(				UInt8 	inChannel);
+
+	SynthNote*			GetNote(UInt32 inIndex) 
+						{ 
+							if (!mNotes)
+								throw std::runtime_error("no notes");
+							return (SynthNote*)((char*)mNotes + inIndex * mNoteSize); 
+						}
+	
+	SynthNote*			GetAFreeNote(UInt32 inFrame);
+	void				AddFreeNote(SynthNote* inNote);
+	
+	friend class SynthGroupElement;
+protected:
+
+	UInt32				NextNoteID() { return OSAtomicIncrement32((int32_t *)&mNoteIDCounter); }
+	
+	
+	// call SetNotes in your Initialize() method to give the base class your note structures and to set the maximum 
+	// number of active notes. inNoteData should be an array of size inMaxActiveNotes.
+	void				SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteSize);
+	
+	void				PerformEvents(   const AudioTimeStamp &			inTimeStamp);
+	OSStatus			SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame);
+	virtual SynthNote*  VoiceStealing(UInt32 inFrame, bool inKillIt);
+	UInt32				MaxActiveNotes() const { return mMaxActiveNotes; }
+	UInt32				NumActiveNotes() const { return mNumActiveNotes; }
+	void				IncNumActiveNotes() { ++mNumActiveNotes; }
+	void				DecNumActiveNotes() { --mNumActiveNotes; }
+	UInt32				CountActiveNotes();
+	
+	SynthPartElement *	GetPartElement (AudioUnitElement inPartElement);
+	
+			// this call throws if there's no assigned element for the group ID
+	virtual SynthGroupElement *	GetElForGroupID (MusicDeviceGroupID	inGroupID);
+	virtual SynthGroupElement *	GetElForNoteID (NoteInstanceID inNoteID);
+
+	SInt64 mAbsoluteSampleFrame;
+
+	
+private:
+				
+	SInt32 mNoteIDCounter;
+	
+	SynthEventQueue mEventQueue;
+	
+	UInt32 mNumNotes;
+	UInt32 mNumActiveNotes;
+	UInt32 mMaxActiveNotes;
+	SynthNote* mNotes;	
+	SynthNoteList mFreeNotes;
+	UInt32 mNoteSize;
+	
+	AUScope			mPartScope;
+	const UInt32	mInitNumPartEls;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AUMonotimbralInstrumentBase : public AUInstrumentBase
+{
+public:
+	AUMonotimbralInstrumentBase(
+							AudioComponentInstance			inInstance, 
+							UInt32							numInputs,
+							UInt32							numOutputs,
+							UInt32							numGroups = 16,
+							UInt32							numParts = 1);
+										
+	virtual OSStatus			RealTimeStartNote(			SynthGroupElement 			*inGroup, 
+															NoteInstanceID 				inNoteInstanceID, 
+															UInt32 						inOffsetSampleFrame, 
+															const MusicDeviceNoteParams &inParams);
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// this is a work in progress! The mono-timbral one is finished though!
+class AUMultitimbralInstrumentBase : public AUInstrumentBase
+{
+public:
+	AUMultitimbralInstrumentBase(
+							AudioComponentInstance			inInstance, 
+							UInt32							numInputs,
+							UInt32							numOutputs,
+							UInt32							numGroups,
+							UInt32							numParts);
+							
+	virtual OSStatus			GetPropertyInfo(		AudioUnitPropertyID				inID,
+														AudioUnitScope					inScope,
+														AudioUnitElement				inElement,
+														UInt32 &						outDataSize,
+														Boolean &						outWritable);
+
+	virtual OSStatus			GetProperty(			AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement,
+														void *							outData);
+
+	virtual OSStatus			SetProperty(			AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														const void *					inData,
+														UInt32 							inDataSize);
+
+private:
+
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
new file mode 100644
index 0000000..ea6c4c2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
@@ -0,0 +1,168 @@
+/*
+     File: LockFreeFIFO.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include <libkern/OSAtomic.h>
+
+template <class ITEM>
+class LockFreeFIFOWithFree
+{
+	LockFreeFIFOWithFree(); // private, unimplemented.
+public:
+	LockFreeFIFOWithFree(UInt32 inMaxSize)
+		: mReadIndex(0), mWriteIndex(0), mFreeIndex(0)
+	{
+		//assert(IsPowerOfTwo(inMaxSize));
+		mItems = new ITEM[inMaxSize];
+		mMask = inMaxSize - 1;
+	}
+	
+	~LockFreeFIFOWithFree()
+	{
+		delete [] mItems;
+	}
+
+	
+	void Reset() 
+	{
+		FreeItems();
+		mReadIndex = 0;
+		mWriteIndex = 0;
+		mFreeIndex = 0;
+	}
+	
+	ITEM* WriteItem() 
+	{
+		//printf("WriteItem %d %d\n", mReadIndex, mWriteIndex);
+		FreeItems(); // free items on the write thread.
+		int32_t nextWriteIndex = (mWriteIndex + 1) & mMask;
+		if (nextWriteIndex == mFreeIndex) return NULL;
+		return &mItems[mWriteIndex];
+	}
+	
+	ITEM* ReadItem() 
+	{
+		//printf("ReadItem %d %d\n", mReadIndex, mWriteIndex);
+		if (mReadIndex == mWriteIndex) return NULL;
+		return &mItems[mReadIndex];
+	}
+	void AdvanceWritePtr() { OSAtomicCompareAndSwap32(mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex); }
+	void AdvanceReadPtr()  { OSAtomicCompareAndSwap32(mReadIndex,  (mReadIndex  + 1) & mMask, &mReadIndex); }
+private:
+	ITEM* FreeItem() 
+	{
+		if (mFreeIndex == mReadIndex) return NULL;
+		return &mItems[mFreeIndex];
+	}
+	void AdvanceFreePtr() { OSAtomicCompareAndSwap32(mFreeIndex, (mFreeIndex + 1) & mMask, &mFreeIndex); }
+	
+	void FreeItems() 
+	{
+		ITEM* item;
+		while ((item = FreeItem()) != NULL)
+		{
+			item->Free();
+			AdvanceFreePtr();
+		}
+	}
+	
+	volatile int32_t mReadIndex, mWriteIndex, mFreeIndex;
+	int32_t mMask;
+	ITEM *mItems;
+};
+
+
+
+// Same as above but no free.
+
+template <class ITEM>
+class LockFreeFIFO
+{
+	LockFreeFIFO(); // private, unimplemented.
+public:
+	LockFreeFIFO(UInt32 inMaxSize)
+		: mReadIndex(0), mWriteIndex(0)
+	{
+		//assert(IsPowerOfTwo(inMaxSize));
+		mItems = new ITEM[inMaxSize];
+		mMask = inMaxSize - 1;
+	}
+	
+	~LockFreeFIFO()
+	{
+		delete [] mItems;
+	}
+	
+	void Reset() 
+	{
+		mReadIndex = 0;
+		mWriteIndex = 0;
+	}
+	
+	ITEM* WriteItem() 
+	{
+		int32_t nextWriteIndex = (mWriteIndex + 1) & mMask;
+		if (nextWriteIndex == mReadIndex) return NULL;
+		return &mItems[mWriteIndex];
+	}
+	
+	ITEM* ReadItem() 
+	{
+		if (mReadIndex == mWriteIndex) return NULL;
+		return &mItems[mReadIndex];
+	}
+	
+		// the CompareAndSwap will always succeed. We use CompareAndSwap because it calls the PowerPC sync instruction,
+		// plus any processor bug workarounds for various CPUs.
+	void AdvanceWritePtr() { OSAtomicCompareAndSwap32(mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex); }
+	void AdvanceReadPtr()  { OSAtomicCompareAndSwap32(mReadIndex,  (mReadIndex  + 1) & mMask, &mReadIndex); }
+	
+private:
+	
+	volatile int32_t mReadIndex, mWriteIndex;
+	int32_t mMask;
+	ITEM *mItems;
+};
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h
new file mode 100644
index 0000000..0f8003f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h
@@ -0,0 +1,92 @@
+/*
+     File: MIDIControlHandler.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __MIDICONTROLHANDLER_H__
+#define	__MIDICONTROLHANDLER_H__
+
+#include <CoreAudio/CoreAudio.h>
+
+/*! Abstract interface base class for classes which handle all incoming MIDI data */
+
+class MIDIControlHandler
+{
+public:
+	virtual			~MIDIControlHandler() {}
+	virtual void	Reset() = 0;								//! Restore all state to defaults
+	virtual bool	SetProgramChange(UInt16	inProgram) = 0;
+	virtual bool	SetPitchWheel(UInt16 inValue) = 0;
+	virtual bool	SetChannelPressure(UInt8 inValue) = 0;
+	virtual bool	SetPolyPressure(UInt8 inKey, UInt8 inValue) = 0;
+	virtual bool	SetController(UInt8 inControllerNumber, UInt8 inValue) = 0;
+	virtual bool	SetSysex(void *inSysexMsg) = 0;
+	
+	virtual float	GetPitchBend() const = 0;
+
+	/*! Default controller values.  These represent MSB values unless indicated in the name */
+	
+	enum
+	{
+		kDefault_Midpoint				= 0x40,		//! Used for all center-null-point controllers
+		kDefault_Volume				= 100,
+		kDefault_Pan					= kDefault_Midpoint,
+		kDefault_ModWheel				= 0,
+		kDefault_Pitch					= kDefault_Midpoint,
+		kDefault_Expression			= 0x7f,
+		kDefault_ChannelPressure	= 0,
+		kDefault_ReverbSend			= 40,
+		kDefault_ChorusSend			= 0,
+		
+		kDefault_RPN_LSB				= 0x7f,
+		kDefault_RPN_MSB				= 0x7f,
+		kDefault_PitchBendRange		= 2,
+		kDefault_FineTuning			= kDefault_Midpoint,
+		kDefault_CoarseTuning		= kDefault_Midpoint,
+		kDefault_ModDepthRange		= 0,
+		kDefault_ModDepthRangeLSB	= kDefault_Midpoint
+	};
+};
+
+#endif	// __MIDICONTROLHANDLER_H__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
new file mode 100644
index 0000000..fd329f8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
@@ -0,0 +1,419 @@
+/*
+     File: SynthElement.cpp
+ Abstract: SynthElement.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+#include "AUMIDIDefs.h"
+
+#undef DEBUG_PRINT
+#define DEBUG_PRINT 0
+#define DEBUG_PRINT_NOTE 0
+#define DEBUG_PRINT_RENDER 0
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+MidiControls::MidiControls()
+{
+	Reset();
+}
+
+void MidiControls::Reset()
+{
+	memset(mControls, 0, sizeof(mControls));
+	memset(mPolyPressure, 0, sizeof(mPolyPressure));
+	mMonoPressure = 0;
+	mProgramChange = 0;
+	mPitchBend = 0;
+	mActiveRPN = 0;
+	mActiveNRPN = 0;
+	mActiveRPValue = 0;
+	mActiveNRPValue = 0;
+	mControls[kMidiController_Pan] = 64;
+	mControls[kMidiController_Expression] = 127;
+	mPitchBendDepth = 24 << 7;
+	mFPitchBendDepth = 24.0f;
+	mFPitchBend = 0.0f;
+}
+
+
+SynthElement::SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement) 
+	: AUElement(audioUnit), mIndex(inElement)
+{
+}
+
+SynthElement::~SynthElement()
+{
+}
+
+SynthGroupElement::SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement, MIDIControlHandler *inHandler) 
+	: SynthElement(audioUnit, inElement),
+	mCurrentAbsoluteFrame(-1),
+	mMidiControlHandler(inHandler),
+	mSustainIsOn(false), mSostenutoIsOn(false), mOutputBus(0), mGroupID(kUnassignedGroup)
+{
+	for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+		mNoteList[i].mState = (SynthNoteState) i;
+}
+
+SynthGroupElement::~SynthGroupElement()
+{
+	delete mMidiControlHandler;
+}
+
+void	SynthGroupElement::SetGroupID (MusicDeviceGroupID inGroup)
+{
+		// can't re-assign a group once its been assigned
+	if (mGroupID != kUnassignedGroup) throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+	mGroupID = inGroup;
+}
+
+void SynthGroupElement::Reset() 
+{
+#if DEBUG_PRINT
+	printf("SynthGroupElement::Reset\n");
+#endif
+	mMidiControlHandler->Reset();
+	for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+		mNoteList[i].Empty();
+}
+
+SynthPartElement::SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement) 
+	: SynthElement(audioUnit, inElement)
+{
+}
+
+// Return the SynthNote with the given inNoteID, if found.  If unreleasedOnly is true, only look for
+// attacked and sostenutoed notes, otherwise search all states.  Return state of found note via outNoteState.
+
+SynthNote *SynthGroupElement::GetNote(NoteInstanceID inNoteID, bool unreleasedOnly, UInt32 *outNoteState)
+{
+#if DEBUG_PRINT_RENDER
+	printf("SynthGroupElement::GetNote %d, unreleased = %d\n", inNoteID, unreleasedOnly);
+#endif
+	const UInt32 lastNoteState = unreleasedOnly ? 
+									(mSostenutoIsOn ? kNoteState_Sostenutoed : kNoteState_Attacked)
+										: kNoteState_Released;
+	SynthNote *note = NULL;
+	// Search for notes in each successive state
+	for (UInt32 noteState = kNoteState_Attacked; noteState <= lastNoteState; ++noteState)
+	{
+		if (outNoteState) *outNoteState = noteState;	// even if we find nothing
+		note = mNoteList[noteState].mHead;
+		while (note && note->mNoteID != inNoteID)
+		{
+#if DEBUG_PRINT_RENDER
+			printf("   checking %p id: %d\n", note, note->mNoteID);
+#endif
+			note = note->mNext;
+		}
+		if (note)
+		{
+#if DEBUG_PRINT_RENDER
+			printf("  found %p\n", note);
+#endif
+			break;
+		}
+	}
+	return note;
+}
+
+void SynthGroupElement::NoteOn(SynthNote *note,
+							   SynthPartElement *part,
+							   NoteInstanceID inNoteID,
+							   UInt32 inOffsetSampleFrame,
+							   const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT_NOTE
+	printf("SynthGroupElement::NoteOn %d\n", inNoteID);
+#endif
+	// TODO: CONSIDER FIXING this to not need to initialize mCurrentAbsoluteFrame to -1.
+	UInt64 absoluteFrame = (mCurrentAbsoluteFrame == -1) ? inOffsetSampleFrame : mCurrentAbsoluteFrame + inOffsetSampleFrame;
+	if (note->AttackNote(part, this, inNoteID, absoluteFrame, inOffsetSampleFrame, inParams)) {
+		mNoteList[kNoteState_Attacked].AddNote(note);
+	}
+}
+
+void SynthGroupElement::NoteOff(NoteInstanceID inNoteID, UInt32 inFrame)
+{	
+#if DEBUG_PRINT_NOTE
+	printf("SynthGroupElement::NoteOff %d\n", inNoteID);
+#endif
+	UInt32 noteState = kNoteState_Attacked;
+	SynthNote *note = GetNote(inNoteID, true, &noteState);	// asking for unreleased only
+	if (note)
+	{
+#if DEBUG_PRINT_NOTE
+		printf("  old note state: %d\n", note->mState);
+#endif
+		if (noteState == kNoteState_Attacked)
+		{
+			mNoteList[noteState].RemoveNote(note);
+			if (mSustainIsOn) {
+				mNoteList[kNoteState_ReleasedButSustained].AddNote(note);
+			} else {
+				note->Release(inFrame);
+				mNoteList[kNoteState_Released].AddNote(note);
+			}
+#if DEBUG_PRINT_NOTE
+			printf("  new note state: %d\n", note->mState);
+#endif
+		}
+		else /* if (noteState == kNoteState_Sostenutoed) */
+		{
+			mNoteList[kNoteState_Sostenutoed].RemoveNote(note);
+			mNoteList[kNoteState_ReleasedButSostenutoed].AddNote(note);
+		}
+	}
+}
+
+void SynthGroupElement::NoteEnded(SynthNote *inNote, UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+	printf("SynthGroupElement::NoteEnded: id %d state %d\n", inNote->mNoteID, inNote->mState);
+#endif
+	if (inNote->IsSounding()) {
+		SynthNoteList *list = &mNoteList[inNote->GetState()];
+		list->RemoveNote(inNote);
+	}
+	
+	GetAUInstrument()->AddFreeNote(inNote);
+}
+
+void SynthGroupElement::NoteFastReleased(SynthNote *inNote)
+{
+#if DEBUG_PRINT_NOTE
+	printf("SynthGroupElement::NoteFastReleased id %d state %d\n", inNote->mNoteID, inNote->mState);
+#endif
+	if (inNote->IsActive()) {
+		mNoteList[inNote->GetState()].RemoveNote(inNote);
+		GetAUInstrument()->DecNumActiveNotes();
+		mNoteList[kNoteState_FastReleased].AddNote(inNote);
+	}
+	else {
+		Assert(true, "ASSERT FAILED:  Attempting to fast-release non-active note");
+	}
+}
+
+bool SynthGroupElement::ChannelMessage(UInt16 controllerID, UInt16 inValue)
+{
+	bool handled = true;
+#if DEBUG_PRINT
+	printf("SynthGroupElement::ChannelMessage(0x%x, %u)\n", controllerID, inValue);
+#endif
+	// Sustain and sostenuto are "pedal events", and are handled during render cycle
+	if (controllerID <= kMidiController_RPN_MSB && controllerID != kMidiController_Sustain && controllerID != kMidiController_Sostenuto)
+		handled = mMidiControlHandler->SetController(controllerID, UInt8(inValue));
+	else 
+	{
+		switch (controllerID)
+		{
+			case kMidiMessage_ProgramChange:
+				handled = mMidiControlHandler->SetProgramChange(inValue);
+				break;
+			case kMidiMessage_PitchWheel:
+				handled = mMidiControlHandler->SetPitchWheel(inValue);
+				break;
+			case kMidiMessage_ChannelPressure:
+#if DEBUG_PRINT
+				printf("SynthGroupElement::ChannelMessage: Channel Pressure %u\n", inValue);
+#endif
+				handled = mMidiControlHandler->SetChannelPressure(UInt8(inValue));
+				break;
+			case kMidiMessage_PolyPressure:
+			{	UInt8 inKey = inValue >> 7;
+				UInt8 val = inValue & 0x7f;
+				handled = mMidiControlHandler->SetPolyPressure(inKey, val);
+				break;
+			}
+			default:
+				handled = false;
+				break;
+		}
+	}
+	return handled;
+}
+
+void SynthGroupElement::SostenutoOn(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+	printf("SynthGroupElement::SostenutoOn\n");
+#endif
+	if (!mSostenutoIsOn) {
+		mMidiControlHandler->SetController(kMidiController_Sostenuto, 127);
+		mSostenutoIsOn = true;
+		mNoteList[kNoteState_Sostenutoed].TransferAllFrom(&mNoteList[kNoteState_Attacked], inFrame);
+	}
+}
+
+void SynthGroupElement::SostenutoOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+	printf("SynthGroupElement::SostenutoOff\n");
+#endif
+	if (mSostenutoIsOn) {
+		mMidiControlHandler->SetController(kMidiController_Sostenuto, 0);
+		mSostenutoIsOn = false;
+		mNoteList[kNoteState_Attacked].TransferAllFrom(&mNoteList[kNoteState_Sostenutoed], inFrame);
+		if (mSustainIsOn) 
+			mNoteList[kNoteState_ReleasedButSustained].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
+		else
+			mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
+	}
+}
+
+
+void SynthGroupElement::SustainOn(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+//	printf("SynthGroupElement::SustainOn\n");
+#endif
+	if (!mSustainIsOn) {
+		mMidiControlHandler->SetController(kMidiController_Sustain, 127);
+		mSustainIsOn = true;
+	}
+}
+
+void SynthGroupElement::SustainOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+//	printf("SynthGroupElement::SustainOff\n");
+#endif
+	if (mSustainIsOn) {
+		mMidiControlHandler->SetController(kMidiController_Sustain, 0);
+		mSustainIsOn = false;
+	
+		mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSustained], inFrame);
+	}
+}
+
+void SynthGroupElement::AllNotesOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+	printf("SynthGroupElement::AllNotesOff\n");
+#endif
+	SynthNote *note;
+	for (UInt32 i=0 ; i<=kNoteState_Sostenutoed; ++i)
+	{
+		UInt32 newState = (i == kNoteState_Attacked) ?
+			kNoteState_Released : kNoteState_ReleasedButSostenutoed;
+		note = mNoteList[i].mHead;
+		while (note)
+		{
+			SynthNote *nextNote = note->mNext;
+			
+			mNoteList[i].RemoveNote(note);
+			note->Release(inFrame);
+			mNoteList[newState].AddNote(note);
+			
+			note = nextNote;
+		}
+	}	
+}
+
+void SynthGroupElement::AllSoundOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+	printf("SynthGroupElement::AllSoundOff\n");
+#endif
+	SynthNote *note;
+	
+	for (UInt32 i=0 ; i<kNumberOfActiveNoteStates; ++i)
+	{
+		note = mNoteList[i].mHead;
+		while (note)
+		{
+			SynthNote *nextNote = note->mNext;
+			
+			mNoteList[i].RemoveNote(note);
+			note->FastRelease(inFrame);
+			mNoteList[kNoteState_FastReleased].AddNote(note);
+			GetAUInstrument()->DecNumActiveNotes();
+			note = nextNote;
+		}
+	}	
+}
+
+void SynthGroupElement::ResetAllControllers(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+	printf("SynthGroupElement::ResetAllControllers\n");
+#endif
+	mMidiControlHandler->Reset();
+}
+
+OSStatus SynthGroupElement::Render(SInt64 inAbsoluteSampleFrame, UInt32 inNumberFrames, AUScope &outputs)
+{
+	// Avoid duplicate calls at same sample offset
+	if (inAbsoluteSampleFrame != mCurrentAbsoluteFrame)
+	{
+		mCurrentAbsoluteFrame = inAbsoluteSampleFrame;
+		AudioBufferList* buffArray[16];
+		UInt32 numOutputs = outputs.GetNumberOfElements();
+		for (UInt32 outBus = 0; outBus < numOutputs && outBus < 16; ++outBus)
+		{
+			buffArray[outBus] = &GetAudioUnit()->GetOutput(outBus)->GetBufferList();
+		}
+		
+		for (UInt32 i=0 ; i<kNumberOfSoundingNoteStates; ++i)
+		{
+			SynthNote *note = mNoteList[i].mHead;
+			while (note)
+			{
+#if DEBUG_PRINT_RENDER
+				printf("SynthGroupElement::Render: state %d, note %p\n", i, note);
+#endif
+				SynthNote *nextNote = note->mNext;
+				
+				OSStatus err = note->Render(inAbsoluteSampleFrame, inNumberFrames, buffArray, numOutputs);
+				if (err) return err;
+				
+				note = nextNote;
+			}
+		}
+	}
+	return noErr;
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
new file mode 100644
index 0000000..4ca3643
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
@@ -0,0 +1,227 @@
+/*
+     File: SynthElement.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __SynthElement__
+#define __SynthElement__
+
+#include <AudioUnit/AudioUnit.h>
+#include "MusicDeviceBase.h"
+#include "SynthNoteList.h"
+#include "MIDIControlHandler.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class AUInstrumentBase;
+
+class SynthElement : public AUElement
+{
+public:
+	SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement);
+	virtual ~SynthElement();
+
+	UInt32 GetIndex() const { return mIndex; }
+	
+	AUInstrumentBase* GetAUInstrument() { return (AUInstrumentBase*)GetAudioUnit(); }
+	
+private:
+	UInt32 mIndex;
+};
+
+class MidiControls : public MIDIControlHandler
+{
+	enum { kMaxControls = 128 };
+public:
+	MidiControls();
+	virtual ~MidiControls() {}
+	virtual void	Reset();
+	virtual bool	SetProgramChange(UInt16	inProgram) { mProgramChange = inProgram; return true; }
+	virtual bool	SetPitchWheel(UInt16 inValue) {
+		mPitchBend = inValue;
+		mFPitchBend = (float)(((SInt16)mPitchBend - 8192) / 8192.);
+		return true;
+	}
+	virtual bool	SetChannelPressure(UInt8 inValue) { mMonoPressure = inValue; return true; }
+	virtual bool	SetPolyPressure(UInt8 inKey, UInt8 inValue) {
+		mPolyPressure[inKey] = inValue;
+		return true;
+	}
+	virtual bool	SetController(UInt8 inControllerNumber, UInt8 inValue) {
+		if (inControllerNumber < kMaxControls) {
+			mControls[inControllerNumber] = inValue;
+			return true;
+		}
+		return false;
+	}
+	virtual bool	SetSysex(void *inSysexMsg) { return false; }
+
+	virtual float GetPitchBend() const { return mFPitchBend * mFPitchBendDepth; }
+
+	SInt16 GetHiResControl(UInt32 inIndex) const 
+	{   
+		return ((mControls[inIndex] & 127) << 7) | (mControls[inIndex + 32] & 127);
+	}
+	
+	float GetControl(UInt32 inIndex) const
+	{
+		if (inIndex < 32) {
+			return (float)(mControls[inIndex] + (mControls[inIndex + 32] / 127.));
+		} else {
+			return (float)mControls[inIndex];
+		}
+	}
+	
+	
+private:
+	
+	UInt8 mControls[128];
+	UInt8 mPolyPressure[128];
+	UInt8 mMonoPressure;
+	UInt8 mProgramChange;
+	UInt16 mPitchBend;
+	UInt16 mActiveRPN;
+	UInt16 mActiveNRPN;
+	UInt16 mActiveRPValue;
+	UInt16 mActiveNRPValue;
+	
+	UInt16 mPitchBendDepth;
+	float mFPitchBendDepth;
+	float mFPitchBend;
+	
+	void SetHiResControl(UInt32 inIndex, UInt8 inMSB, UInt8 inLSB)
+		{ 
+			mControls[inIndex] = inMSB;
+			mControls[inIndex + 32] = inLSB;
+		}
+		
+};
+
+
+class SynthGroupElement : public SynthElement
+{
+public:
+	enum {
+		kUnassignedGroup = 0xFFFFFFFF
+	};
+	
+	SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement, MIDIControlHandler *inHandler);
+	virtual					~SynthGroupElement();
+
+	virtual void			NoteOn(SynthNote *note, SynthPartElement *part, NoteInstanceID inNoteID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams &inParams);
+	virtual void			NoteOff(NoteInstanceID inNoteID, UInt32 inOffsetSampleFrame);
+	void					SustainOn(UInt32 inFrame);
+	void					SustainOff(UInt32 inFrame);
+	void					SostenutoOn(UInt32 inFrame);
+	void					SostenutoOff(UInt32 inFrame);
+
+	void					NoteEnded(SynthNote *inNote, UInt32 inFrame);
+	void					NoteFastReleased(SynthNote *inNote);
+	
+	virtual bool			ChannelMessage(UInt16 controlID, UInt16 controlValue);
+	virtual void			AllNotesOff(UInt32 inFrame);
+	virtual void			AllSoundOff(UInt32 inFrame);
+	void					ResetAllControllers(UInt32 inFrame);
+	
+	SynthNote *				GetNote(NoteInstanceID inNoteID, bool unreleasedOnly=false, UInt32 *outNoteState=NULL);
+	
+	void					Reset();
+	
+	virtual OSStatus		Render(SInt64 inAbsoluteSampleFrame, UInt32 inNumberFrames, AUScope &outputs);
+	
+	float					GetPitchBend() const { return mMidiControlHandler->GetPitchBend(); }
+	SInt64					GetCurrentAbsoluteFrame() const { return mCurrentAbsoluteFrame; }
+	
+	MusicDeviceGroupID		GroupID () const { return mGroupID; }
+	virtual void			SetGroupID (MusicDeviceGroupID inGroup);
+
+	MIDIControlHandler *	GetMIDIControlHandler() const { return mMidiControlHandler; }
+	
+protected:	
+	SInt64					mCurrentAbsoluteFrame;
+	SynthNoteList 			mNoteList[kNumberOfSoundingNoteStates];
+	MIDIControlHandler		*mMidiControlHandler;
+
+private:
+	friend class AUInstrumentBase;
+	friend class AUMonotimbralInstrumentBase;
+	friend class AUMultitimbralInstrumentBase;
+	
+	bool					mSustainIsOn;
+	bool					mSostenutoIsOn;
+	UInt32					mOutputBus;
+	MusicDeviceGroupID		mGroupID;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct SynthKeyZone
+{
+	UInt8 mLoNote;
+	UInt8 mHiNote;
+	UInt8 mLoVelocity;
+	UInt8 mHiVelocity;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const UInt32 kUnlimitedPolyphony = 0xFFFFFFFF;
+
+class SynthPartElement : public SynthElement
+{
+public:
+	SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement);
+
+	UInt32		GetGroupIndex() const { return mGroupIndex; }
+	bool		InRange(Float32 inNote, Float32 inVelocity);
+	
+	UInt32		GetMaxPolyphony() const { return mMaxPolyphony; }
+	void		SetMaxPolyphony(UInt32 inMaxPolyphony) { mMaxPolyphony = inMaxPolyphony; }
+	
+private:
+	UInt32							mGroupIndex;
+	UInt32							mPatchIndex;
+	UInt32							mMaxPolyphony;
+	SynthKeyZone					mKeyZone;	
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
new file mode 100644
index 0000000..9c27aee
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
@@ -0,0 +1,145 @@
+/*
+     File: SynthEvent.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+/* You can either fill in code here or remove this and create or add new files. */
+
+#ifndef __SynthEvent__
+#define __SynthEvent__
+
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+#include <stdexcept>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+class SynthEvent
+{
+public:
+	enum {
+		kEventType_NoteOn = 1,
+		kEventType_NoteOff = 2,
+		kEventType_SustainOn = 3,
+		kEventType_SustainOff = 4,
+		kEventType_SostenutoOn = 5,
+		kEventType_SostenutoOff = 6,
+		kEventType_AllNotesOff = 7,
+		kEventType_AllSoundOff = 8,
+		kEventType_ResetAllControllers = 9
+	};
+
+
+	SynthEvent() {}
+	~SynthEvent() {}
+
+	void Set(   
+				UInt32							inEventType,
+				MusicDeviceGroupID				inGroupID,
+				NoteInstanceID					inNoteID,
+				UInt32							inOffsetSampleFrame,
+				const MusicDeviceNoteParams*	inNoteParams
+		)
+	{
+		mEventType = inEventType;
+		mGroupID = inGroupID;
+		mNoteID = inNoteID;
+		mOffsetSampleFrame = inOffsetSampleFrame;
+		
+		if (inNoteParams)
+		{
+			UInt32 paramSize = offsetof(MusicDeviceNoteParams, mControls) + (inNoteParams->argCount-2)*sizeof(NoteParamsControlValue); 
+			mNoteParams = inNoteParams->argCount > 3 
+								? (MusicDeviceNoteParams*)malloc(paramSize) 
+								: &mSmallNoteParams;
+			memcpy(mNoteParams, inNoteParams, paramSize);
+		}
+		else 
+			mNoteParams = NULL;
+	}
+	
+	
+	void Free()
+	{
+		if (mNoteParams)
+		{
+			if (mNoteParams->argCount > 3)
+				free(mNoteParams);
+			mNoteParams = NULL;
+		}
+	}
+	
+	UInt32					GetEventType() const { return mEventType; }
+	MusicDeviceGroupID		GetGroupID() const { return mGroupID; }
+	NoteInstanceID			GetNoteID() const { return mNoteID; }
+	UInt32					GetOffsetSampleFrame() const { return mOffsetSampleFrame; }
+	
+	MusicDeviceNoteParams*  GetParams() const { return mNoteParams; }
+
+	UInt32					GetArgCount() const { return mNoteParams->argCount; }
+	UInt32					NumberParameters() const { return mNoteParams->argCount - 2; }
+	
+	Float32					GetNote() const { return mNoteParams->mPitch; }
+	Float32					GetVelocity() const { return mNoteParams->mVelocity; }
+	
+	NoteParamsControlValue  GetParameter(UInt32 inIndex) const 
+							{
+								if (inIndex >= NumberParameters()) 
+									throw std::runtime_error("index out of range");
+								return mNoteParams->mControls[inIndex]; 
+							}
+	
+private:
+	UInt32					mEventType;
+	MusicDeviceGroupID		mGroupID;
+	NoteInstanceID			mNoteID;
+	UInt32					mOffsetSampleFrame;
+	MusicDeviceNoteParams*  mNoteParams;
+	MusicDeviceNoteParams   mSmallNoteParams; // inline a small one to eliminate malloc for the simple case.
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
new file mode 100644
index 0000000..96a24d3
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
@@ -0,0 +1,140 @@
+/*
+     File: SynthNote.cpp
+ Abstract: SynthNote.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "SynthNote.h"
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+
+bool SynthNote::AttackNote(
+			SynthPartElement *				inPart,
+			SynthGroupElement *				inGroup,
+			NoteInstanceID					inNoteID, 
+			UInt64							inAbsoluteSampleFrame, 
+			UInt32							inOffsetSampleFrame, 
+			const MusicDeviceNoteParams		&inParams)
+{
+#if DEBUG_PRINT
+	printf("SynthNote::AttackNote %lu %lu abs frame %llu rel frame %lu\n", (UInt32)inGroup->GroupID(), (UInt32)inNoteID, inAbsoluteSampleFrame, inOffsetSampleFrame);
+#endif
+	mPart = inPart;
+	mGroup = inGroup;
+	mNoteID = inNoteID;
+
+	mAbsoluteStartFrame = inAbsoluteSampleFrame;
+	mRelativeStartFrame = inOffsetSampleFrame;
+	mRelativeReleaseFrame = -1;
+	mRelativeKillFrame = -1;
+
+	mPitch = inParams.mPitch;
+	mVelocity = inParams.mVelocity;
+	
+	
+	return Attack(inParams);
+}
+
+
+void SynthNote::Reset()
+{
+	mPart = 0;
+	mGroup = 0;
+	mAbsoluteStartFrame = 0;
+	mRelativeStartFrame = 0;
+	mRelativeReleaseFrame = 0;
+	mRelativeKillFrame = 0;
+}
+
+void SynthNote::Kill(UInt32 inFrame)
+{
+	mRelativeKillFrame = inFrame;
+}
+
+void SynthNote::Release(UInt32 inFrame)
+{
+	mRelativeReleaseFrame = inFrame;
+}
+
+void SynthNote::FastRelease(UInt32 inFrame)
+{
+	mRelativeReleaseFrame = inFrame;
+}
+
+double SynthNote::TuningA() const
+{
+	return 440.0;
+}
+
+double SynthNote::Frequency()
+{
+	return TuningA() * pow(2., (mPitch - 69. + GetPitchBend()) / 12.);
+}
+
+double SynthNote::SampleRate()
+{
+	return GetAudioUnit()->GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+AUInstrumentBase* SynthNote::GetAudioUnit() const 
+{ 
+	return (AUInstrumentBase*)mGroup->GetAudioUnit(); 
+}
+
+Float32 SynthNote::GetGlobalParameter(AudioUnitParameterID inParamID) const 
+{
+	return mGroup->GetAudioUnit()->Globals()->GetParameter(inParamID);
+}
+
+void SynthNote::NoteEnded(UInt32 inFrame) 
+{ 
+	mGroup->NoteEnded(this, inFrame);
+	mNoteID = 0xFFFFFFFF; 
+}
+
+float SynthNote::GetPitchBend() const 
+{ 
+	return mGroup->GetPitchBend(); 
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
new file mode 100644
index 0000000..cec6377
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
@@ -0,0 +1,187 @@
+/*
+     File: SynthNote.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __SynthNote__
+#define __SynthNote__
+
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+enum SynthNoteState {
+	kNoteState_Attacked = 0,
+	kNoteState_Sostenutoed = 1,
+	kNoteState_ReleasedButSostenutoed = 2,
+	kNoteState_ReleasedButSustained = 3,
+	kNoteState_Released = 4,
+	kNoteState_FastReleased = 5,
+	kNoteState_Free = 6,
+	kNumberOfActiveNoteStates = 5,
+	kNumberOfSoundingNoteStates = 6,
+	kNumberOfNoteStates = 7,
+	kNoteState_Unset = kNumberOfNoteStates
+};
+
+/*
+		This table describes the state transitions for SynthNotes
+
+        EVENT                   CURRENT STATE                                   NEW STATE
+        note on                 free                                            attacked
+        note off                attacked (and sustain on)                       released but sustained
+        note off                attacked                                        released
+        note off                sostenutoed                                     released but sostenutoed
+        sustain on              -- no changes --
+        sustain off             released but sustained                          released
+        sostenuto on            attacked                                        sostenutoed
+        sostenuto off           sostenutoed                                     attacked
+        sostenuto off           released but sostenutoed (and sustain on)       released but sustained
+        sostenuto off           released but sostenutoed                        released
+        end of note             any state                                       free
+		soft voice stealing     any state                                       fast released
+		hard voice stealing     any state                                       free
+		
+		soft voice stealing happens when there is a note on event and NumActiveNotes > MaxActiveNotes
+		hard voice stealing happens when there is a note on event and NumActiveNotes == NumNotes (no free notes)
+		voice stealing removes the quietest note in the highest numbered state that has sounding notes.
+*/
+
+class SynthGroupElement;
+class SynthPartElement;
+class AUInstrumentBase;
+
+struct SynthNote
+{
+	SynthNote() :
+		mPrev(0), mNext(0), mPart(0), mGroup(0),
+		mNoteID(0xffffffff),
+		mState(kNoteState_Unset),
+		mAbsoluteStartFrame(0),
+		mRelativeStartFrame(0),
+		mRelativeReleaseFrame(-1),
+		mRelativeKillFrame(-1),
+		mPitch(0.0f),
+		mVelocity(0.0f)
+	{
+	}
+	
+	virtual					~SynthNote() {}
+	
+	virtual void			Reset();
+	//! Returns true if active note resulted from this call, otherwise false
+	virtual bool			AttackNote(
+									SynthPartElement *				inPart,
+									SynthGroupElement *				inGroup,
+									NoteInstanceID					inNoteID, 
+									UInt64							inAbsoluteSampleFrame, 
+									UInt32							inOffsetSampleFrame, 
+									const MusicDeviceNoteParams		&inParams
+							);
+								
+	virtual OSStatus		Render(UInt64 inAbsoluteSampleFrame, UInt32 inNumFrames, AudioBufferList** inBufferList, UInt32 inOutBusCount) = 0;
+	//! Returns true if active note resulted from this call, otherwise false
+	virtual bool			Attack(const MusicDeviceNoteParams &inParams) = 0;
+	virtual void			Kill(UInt32 inFrame); // voice is being stolen.
+	virtual void			Release(UInt32 inFrame);
+	virtual void			FastRelease(UInt32 inFrame);
+	virtual Float32			Amplitude() = 0; // used for finding quietest note for voice stealing.
+
+	virtual void			NoteEnded(UInt32 inFrame);
+
+	SynthGroupElement*		GetGroup() const { return mGroup; }
+	SynthPartElement*		GetPart() const { return mPart; }
+	
+	AUInstrumentBase*		GetAudioUnit() const;
+
+	Float32					GetGlobalParameter(AudioUnitParameterID inParamID) const;
+
+	NoteInstanceID			GetNoteID() const { return mNoteID; }
+	SynthNoteState			GetState() const { return mState; }
+	UInt8					GetMidiKey() const { return (UInt8) mPitch; }
+	UInt8					GetMidiVelocity() const { return (UInt8) mVelocity; }
+	
+	Boolean					IsSounding() const { return mState < kNumberOfSoundingNoteStates; }
+	Boolean					IsActive() const { return mState < kNumberOfActiveNoteStates; }
+	UInt64					GetAbsoluteStartFrame() const { return mAbsoluteStartFrame; }
+	SInt32					GetRelativeStartFrame() const { return mRelativeStartFrame; }
+	SInt32					GetRelativeReleaseFrame() const { return mRelativeReleaseFrame; }
+	SInt32					GetRelativeKillFrame() const { return mRelativeKillFrame; }
+
+	void					ListRemove() { mPrev = mNext = 0; } // only use when lists will be reset.
+
+	float					GetPitchBend() const;
+	double					TuningA() const;
+	
+	Float32					GetPitch() const { return mPitch; }	// returns raw pitch from MusicDeviceNoteParams
+	virtual double			Frequency(); // returns the frequency of note + pitch bend.
+	virtual double			SampleRate();
+
+	// linked list pointers
+	SynthNote				*mPrev;
+	SynthNote				*mNext;
+	
+	friend class			SynthGroupElement;
+	friend struct			SynthNoteList;
+protected:
+	void					SetState(SynthNoteState inState) { mState = inState; }
+private:
+	SynthPartElement*		mPart;
+	SynthGroupElement*	mGroup;
+		
+	NoteInstanceID			mNoteID;
+	SynthNoteState			mState;
+	UInt64					mAbsoluteStartFrame;
+	SInt32					mRelativeStartFrame;
+	SInt32					mRelativeReleaseFrame;
+	SInt32					mRelativeKillFrame;
+	
+	Float32					mPitch;
+	Float32					mVelocity;
+};
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
new file mode 100644
index 0000000..849abd2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
@@ -0,0 +1,93 @@
+/*
+     File: SynthNoteList.cpp
+ Abstract: SynthNoteList.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "SynthNoteList.h"
+#include <stdexcept>
+
+void SynthNoteList::SanityCheck() const
+{
+	if (mState >= kNoteState_Unset) {
+		throw std::runtime_error("SanityCheck: mState is bad");
+	}
+	
+	if (mHead == NULL) {
+		if (mTail != NULL) 
+			throw std::runtime_error("SanityCheck: mHead is NULL but not mTail");
+		return;
+	}
+	if (mTail == NULL) {
+		throw std::runtime_error("SanityCheck: mTail is NULL but not mHead");
+	}
+	
+	if (mHead->mPrev) {
+		throw std::runtime_error("SanityCheck: mHead has a mPrev");
+	}
+	if (mTail->mNext) {
+		throw std::runtime_error("SanityCheck: mTail has a mNext");
+	}
+	
+	SynthNote *note = mHead;
+	while (note)
+	{
+		if (note->mState != mState)
+			throw std::runtime_error("SanityCheck: note in wrong state");
+		if (note->mNext) {
+			if (note->mNext->mPrev != note)
+				throw std::runtime_error("SanityCheck: bad link 1");
+		} else {
+			if (mTail != note)
+				throw std::runtime_error("SanityCheck: note->mNext is nil, but mTail != note");
+		}
+		if (note->mPrev) {
+			if (note->mPrev->mNext != note)
+				throw std::runtime_error("SanityCheck: bad link 2");
+		} else {
+			if (mHead != note)
+				throw std::runtime_error("SanityCheck: note->mPrev is nil, but mHead != note");
+		}
+		note = note->mNext;
+	}
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
new file mode 100644
index 0000000..47a3593
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
@@ -0,0 +1,232 @@
+/*
+     File: SynthNoteList.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __SynthNoteList__
+#define __SynthNoteList__
+
+#include "SynthNote.h"
+
+#if DEBUG
+#ifndef DEBUG_PRINT
+	#define DEBUG_PRINT 0
+#endif
+	#define USE_SANITY_CHECK 0
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct SynthNoteList
+{
+	SynthNoteList() : mState(kNoteState_Unset), mHead(0), mTail(0) {}
+	
+	bool NotEmpty() const { return mHead != NULL; }
+	bool IsEmpty() const { return mHead == NULL; }
+	void Empty() { 
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+		mHead = mTail = NULL; 
+	}
+	
+	UInt32 Length() const {
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+		UInt32 length = 0;
+		for (SynthNote* note = mHead; note; note = note->mNext) 
+			length++;
+		return length;
+	};
+	
+	void AddNote(SynthNote *inNote)
+	{
+#if DEBUG_PRINT
+		printf("AddNote(inNote=%p) to state: %lu\n", inNote, mState);
+#endif
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+		inNote->SetState(mState);
+		inNote->mNext = mHead;
+		inNote->mPrev = NULL;
+		
+		if (mHead) { mHead->mPrev = inNote; mHead = inNote; }
+		else mHead = mTail = inNote;
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+	}
+	
+	void RemoveNote(SynthNote *inNote)
+	{
+#if DEBUG_PRINT
+		printf("RemoveNote(inNote=%p) from state: %lu\n", inNote, mState);
+#endif
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+		if (inNote->mPrev) inNote->mPrev->mNext = inNote->mNext;
+		else mHead = inNote->mNext;
+
+		if (inNote->mNext) inNote->mNext->mPrev = inNote->mPrev;
+		else mTail = inNote->mPrev;
+		
+		inNote->mPrev = 0;
+		inNote->mNext = 0;
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+	}
+
+	void TransferAllFrom(SynthNoteList *inNoteList, UInt32 inFrame)
+	{
+#if DEBUG_PRINT
+		printf("TransferAllFrom: from state %lu into state %lu\n", inNoteList->mState, mState);
+#endif
+#if USE_SANITY_CHECK
+		SanityCheck();
+		inNoteList->SanityCheck();
+#endif
+		if (!inNoteList->mTail) return;
+		
+		if (mState == kNoteState_Released)
+		{
+			for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
+			{
+#if DEBUG_PRINT
+				printf("TransferAllFrom: releasing note %p\n", note);
+#endif
+				note->Release(inFrame);
+				note->SetState(mState);
+			}
+		}
+		else
+		{
+			for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
+			{
+				note->SetState(mState);
+			}
+		}
+		
+		inNoteList->mTail->mNext = mHead;
+		
+		if (mHead) mHead->mPrev = inNoteList->mTail;
+		else mTail = inNoteList->mTail;
+		
+		mHead = inNoteList->mHead;
+		
+		inNoteList->mHead = NULL;
+		inNoteList->mTail = NULL;
+#if USE_SANITY_CHECK
+		SanityCheck();
+		inNoteList->SanityCheck();
+#endif
+	}
+	
+	SynthNote* FindOldestNote()
+	{
+#if DEBUG_PRINT
+		printf("FindOldestNote\n");
+#endif
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+		UInt64 minStartFrame = -1;
+		SynthNote* oldestNote = NULL;
+		for (SynthNote* note = mHead; note; note = note->mNext)
+		{
+			if (note->mAbsoluteStartFrame < minStartFrame)
+			{
+				oldestNote = note;
+				minStartFrame = note->mAbsoluteStartFrame;
+			}
+		}
+		return oldestNote;
+	}
+	
+	SynthNote* FindMostQuietNote()
+	{
+#if DEBUG_PRINT
+		printf("FindMostQuietNote\n");
+#endif
+		Float32 minAmplitude = 1e9f;
+		UInt64 minStartFrame = -1;
+		SynthNote* mostQuietNote = NULL;
+		for (SynthNote* note = mHead; note; note = note->mNext)
+		{
+			Float32 amp = note->Amplitude();
+#if DEBUG_PRINT
+			printf("   amp %g   minAmplitude %g\n", amp, minAmplitude);
+#endif
+			if (amp < minAmplitude)
+			{
+				mostQuietNote = note;
+				minAmplitude = amp;
+				minStartFrame = note->mAbsoluteStartFrame;
+			}
+			else if (amp == minAmplitude && note->mAbsoluteStartFrame < minStartFrame)
+			{
+				// use earliest start time as a tie breaker
+				mostQuietNote = note;
+				minStartFrame = note->mAbsoluteStartFrame;
+			}
+		}
+#if USE_SANITY_CHECK
+		SanityCheck();
+#endif
+		return mostQuietNote;
+	}
+	
+	void SanityCheck() const;
+	
+	SynthNoteState	mState;
+	SynthNote *		mHead;
+	SynthNote *		mTail;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
new file mode 100644
index 0000000..741be00
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
@@ -0,0 +1,88 @@
+/*
+     File: AUViewLocalizedStringKeys.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUViewLocalizedStringKeys_h__
+#define __AUViewLocalizedStringKeys_h__
+
+// ACCESS POINT:
+#define	kLocalizedStringBundle_AUView 		CFSTR("com.apple.audio.units.Components")
+#define	kLocalizedStringTable_AUView 		CFSTR("CustomUI")
+
+// UNLOCALIZED STRINGS:
+    #define	kAUViewUnlocalizedString_TitleSeparator  			CFSTR(": ")
+    
+// Generic View:
+    #define	kAUViewLocalizedStringKey_AudioUnit 				CFSTR("Audio Unit")
+    #define	kAUViewLocalizedStringKey_Manufacturer 			CFSTR("Manufacturer")
+    
+    #define	kAUViewLocalizedStringKey_FactoryPreset 			CFSTR("Factory Preset")
+    
+    #define	kAUViewLocalizedStringKey_Properties 				CFSTR("Properties")
+    #define	kAUViewLocalizedStringKey_Parameters 				CFSTR("Parameters")
+    
+    #define	kAUViewLocalizedStringKey_Standard 				CFSTR("Standard")
+    #define	kAUViewLocalizedStringKey_Expert 					CFSTR("Expert")
+    
+// AULoadCPU:
+    #define	kAUViewLocalizedStringKey_RestrictCPULoad 			CFSTR("Restrict CPU Load")
+    #define	kAUViewLocalizedStringKey_PercentSymbol 			CFSTR("%")
+    #define	kAUViewLocalizedStringKey_NotApplicable 			CFSTR("n/a")
+    
+// AUDiskStreamingCheckbox:
+    #define	kAUViewLocalizedStringKey_StreamFromDisk 			CFSTR("Stream From Disk")
+    
+// AURenderQualityPopup:
+    #define	kAUViewLocalizedStringKey_RenderQuality 			CFSTR("Render Quality")
+    #define	kAUViewLocalizedStringKey_Maximum 					CFSTR("Maximum")
+    #define	kAUViewLocalizedStringKey_High 					CFSTR("High")
+    #define	kAUViewLocalizedStringKey_Medium 					CFSTR("Medium")
+    #define	kAUViewLocalizedStringKey_Low 						CFSTR("Low")
+    #define	kAUViewLocalizedStringKey_Minimum 					CFSTR("Minimum")
+
+// AUChannelLayoutPopUp:
+	#define	kAUViewLocalizedStringKey_AudioChannelLayout 		CFSTR("Audio Channel Layout")
+    
+#endif //__AUViewLocalizedStringKeys_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
new file mode 100644
index 0000000..010082f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
@@ -0,0 +1,466 @@
+/*
+     File: AUEffectBase.cpp
+ Abstract: AUEffectBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUEffectBase.h"
+
+/* 
+	This class does not deal as well as it should with N-M effects...
+	
+	The problem areas are (if the channels don't match):
+		ProcessInPlace if the channels don't match - there will be problems if InputChan != OutputChan
+		Bypass - its just passing the buffers through when not processing them
+
+	This will be fixed in a future update...
+*/
+
+//_____________________________________________________________________________
+//
+AUEffectBase::AUEffectBase(	AudioComponentInstance	audioUnit,
+							bool					inProcessesInPlace ) :
+	AUBase(audioUnit, 1, 1),		// 1 in bus, 1 out bus
+	mBypassEffect(false),
+	mParamSRDep (false),
+	mProcessesInPlace(inProcessesInPlace),
+	mMainOutput(NULL), mMainInput(NULL)
+#if TARGET_OS_IPHONE
+	, mOnlyOneKernel(false)
+#endif
+{
+}
+
+//_____________________________________________________________________________
+//
+AUEffectBase::~AUEffectBase()
+{
+	Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+void AUEffectBase::Cleanup()
+{
+	for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it)
+		delete *it;
+		
+	mKernelList.clear();
+	mMainOutput = NULL;
+	mMainInput = NULL;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUEffectBase::Initialize()
+{
+		// get our current numChannels for input and output
+	SInt16 auNumInputs = (SInt16) GetInput(0)->GetStreamFormat().mChannelsPerFrame;
+	SInt16 auNumOutputs = (SInt16) GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
+
+		// does the unit publish specific information about channel configurations?
+    const AUChannelInfo *auChannelConfigs = NULL;
+    UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs);
+
+    if ((numIOconfigs > 0) && (auChannelConfigs != NULL))
+    {
+        bool foundMatch = false;
+        for (UInt32 i = 0; (i < numIOconfigs) && !foundMatch; ++i)
+        {
+            SInt16 configNumInputs = auChannelConfigs[i].inChannels;
+            SInt16 configNumOutputs = auChannelConfigs[i].outChannels;
+            if ((configNumInputs < 0) && (configNumOutputs < 0))
+            {
+					// unit accepts any number of channels on input and output
+                if (((configNumInputs == -1) && (configNumOutputs == -2)) 
+					|| ((configNumInputs == -2) && (configNumOutputs == -1)))
+                {
+				    foundMatch = true;
+					// unit accepts any number of channels on input and output IFF they are the same number on both scopes
+                }
+				else if (((configNumInputs == -1) && (configNumOutputs == -1)) && (auNumInputs == auNumOutputs))
+                {
+				    foundMatch = true;
+					// unit has specified a particular number of channels on both scopes
+                }
+				else
+                    continue;
+            }
+            else
+            {
+					// the -1 case on either scope is saying that the unit doesn't care about the 
+					// number of channels on that scope
+                bool inputMatch = (auNumInputs == configNumInputs) || (configNumInputs == -1);
+                bool outputMatch = (auNumOutputs == configNumOutputs) || (configNumOutputs == -1);
+                if (inputMatch && outputMatch)
+                    foundMatch = true;
+            }
+        }
+        if (!foundMatch)
+            return kAudioUnitErr_FormatNotSupported;
+    }
+    else
+    {
+			// there is no specifically published channel info
+			// so for those kinds of effects, the assumption is that the channels (whatever their number)
+			// should match on both scopes
+        if ((auNumOutputs != auNumInputs) || (auNumOutputs == 0))
+		{
+		    return kAudioUnitErr_FormatNotSupported;
+		}
+    }
+
+    MaintainKernels();
+	
+	mMainOutput = GetOutput(0);
+	mMainInput = GetInput(0);
+	
+	const CAStreamBasicDescription& format = GetStreamFormat(kAudioUnitScope_Output, 0);
+	format.IdentifyCommonPCMFormat(mCommonPCMFormat, NULL);
+	mBytesPerFrame = format.mBytesPerFrame;
+	
+    return noErr;
+}
+
+OSStatus			AUEffectBase::Reset(		AudioUnitScope 		inScope,
+								 				AudioUnitElement 	inElement)
+{
+	for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it) {
+		AUKernelBase *kernel = *it;
+		if (kernel != NULL)
+			kernel->Reset();
+	}
+	
+	return AUBase::Reset(inScope, inElement);
+}
+
+OSStatus			AUEffectBase::GetPropertyInfo (AudioUnitPropertyID	inID,
+												AudioUnitScope					inScope,
+												AudioUnitElement				inElement,
+												UInt32 &						outDataSize,
+												Boolean &						outWritable)
+{
+	if (inScope == kAudioUnitScope_Global) {
+		switch (inID) {
+			case kAudioUnitProperty_BypassEffect:
+				outWritable = true;
+				outDataSize = sizeof (UInt32);
+				return noErr;
+			case kAudioUnitProperty_InPlaceProcessing:
+				outWritable = true;
+				outDataSize = sizeof (UInt32);
+				return noErr;
+		}
+	}
+	return AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+}
+
+
+OSStatus			AUEffectBase::GetProperty (AudioUnitPropertyID 		inID,
+									  AudioUnitScope 					inScope,
+									  AudioUnitElement			 		inElement,
+									  void *							outData)
+{
+	if (inScope == kAudioUnitScope_Global) {
+		switch (inID) {
+			case kAudioUnitProperty_BypassEffect:
+				*((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+				return noErr;
+			case kAudioUnitProperty_InPlaceProcessing:
+				*((UInt32*)outData) = (mProcessesInPlace ? 1 : 0);
+				return noErr;
+		}
+	}
+	return AUBase::GetProperty (inID, inScope, inElement, outData);
+}
+
+
+OSStatus			AUEffectBase::SetProperty(		AudioUnitPropertyID inID,
+									   AudioUnitScope 		inScope,
+									   AudioUnitElement 	inElement,
+									   const void *			inData,
+									   UInt32 				inDataSize)
+{
+	if (inScope == kAudioUnitScope_Global) {
+		switch (inID) {
+			case kAudioUnitProperty_BypassEffect:
+			{
+				if (inDataSize < sizeof(UInt32))
+					return kAudioUnitErr_InvalidPropertyValue;
+					
+				bool tempNewSetting = *((UInt32*)inData) != 0;
+					// we're changing the state of bypass
+				if (tempNewSetting != IsBypassEffect()) 
+				{
+					if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+						Reset(0, 0);
+					SetBypassEffect (tempNewSetting);
+				}
+				return noErr;
+			}
+			case kAudioUnitProperty_InPlaceProcessing:
+				mProcessesInPlace = (*((UInt32*)inData) != 0);
+				return noErr;
+		}
+	}
+	return AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+}
+ 
+
+void	AUEffectBase::MaintainKernels()
+{
+#if TARGET_OS_IPHONE
+	UInt32 nKernels = mOnlyOneKernel ? 1 : GetNumberOfChannels();
+#else 
+	UInt32 nKernels = GetNumberOfChannels();
+#endif
+	
+	if (mKernelList.size() < nKernels) {
+		mKernelList.reserve(nKernels);
+		for (UInt32 i = (UInt32)mKernelList.size(); i < nKernels; ++i)
+			mKernelList.push_back(NewKernel());
+	} else {
+		while (mKernelList.size() > nKernels) {
+			AUKernelBase *kernel = mKernelList.back();
+			delete kernel;
+			mKernelList.pop_back();
+		}
+	}
+	
+	for(unsigned int i = 0; i < nKernels; i++ )
+	{
+		if(mKernelList[i]) {
+			mKernelList[i]->SetChannelNum (i);
+		}
+	}
+}
+
+bool		AUEffectBase::StreamFormatWritable(	AudioUnitScope					scope,
+												AudioUnitElement				element)
+{
+	return IsInitialized() ? false : true;
+}
+
+OSStatus			AUEffectBase::ChangeStreamFormat(	AudioUnitScope				inScope,
+														AudioUnitElement			inElement,
+														const CAStreamBasicDescription & inPrevFormat,
+														const CAStreamBasicDescription & inNewFormat)
+{
+	OSStatus result = AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+	if (result == noErr)
+	{	
+		// for the moment this only dependency we know about
+		// where a parameter's range may change is with the sample rate
+		// and effects are only publishing parameters in the global scope!
+		if (GetParamHasSampleRateDependency() && fnotequal(inPrevFormat.mSampleRate, inNewFormat.mSampleRate))
+			PropertyChanged(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0);
+	}
+
+	return result;
+}
+
+
+// ____________________________________________________________________________
+//
+//	This method is called (potentially repeatedly) by ProcessForScheduledParams()
+//	in order to perform the actual DSP required for this portion of the entire buffer
+//	being processed.  The entire buffer can be divided up into smaller "slices"
+//	according to the timestamps on the scheduled parameters...
+//
+OSStatus		AUEffectBase::ProcessScheduledSlice(	void				*inUserData,
+														UInt32				inStartFrameInBuffer,
+														UInt32				inSliceFramesToProcess,
+														UInt32				inTotalBufferFrames )
+{
+	ScheduledProcessParams	&sliceParams = *((ScheduledProcessParams*)inUserData);
+	
+	AudioUnitRenderActionFlags 	&actionFlags = *sliceParams.actionFlags;
+	AudioBufferList 			&inputBufferList = *sliceParams.inputBufferList;
+	AudioBufferList 			&outputBufferList = *sliceParams.outputBufferList;
+	
+	UInt32 channelSize = inSliceFramesToProcess * mBytesPerFrame;
+		// fix the size of the buffer we're operating on before we render this slice of time
+	for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+		inputBufferList.mBuffers[i].mDataByteSize = inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+	}
+
+	for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+		outputBufferList.mBuffers[i].mDataByteSize = outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+	}
+		// process the buffer
+	OSStatus result = ProcessBufferLists(actionFlags, inputBufferList, outputBufferList, inSliceFramesToProcess );
+
+		// we just partially processed the buffers, so increment the data pointers to the next part of the buffer to process
+	for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+		inputBufferList.mBuffers[i].mData = 
+			(char *)inputBufferList.mBuffers[i].mData + inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+	}
+	
+	for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+		outputBufferList.mBuffers[i].mData = 
+			(char *)outputBufferList.mBuffers[i].mData + outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+	}
+	
+	return result;
+}
+
+// ____________________________________________________________________________
+//
+
+OSStatus 	AUEffectBase::Render(	AudioUnitRenderActionFlags &ioActionFlags,
+											const AudioTimeStamp &		inTimeStamp,
+											UInt32						nFrames)
+{
+	if (!HasInput(0))
+		return kAudioUnitErr_NoConnection;
+
+	OSStatus result = noErr;
+
+	result = mMainInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, nFrames);
+	
+	if (result == noErr)
+	{
+		if(ProcessesInPlace() && mMainOutput->WillAllocateBuffer())
+		{
+			mMainOutput->SetBufferList(mMainInput->GetBufferList() );
+		}
+
+		if (ShouldBypassEffect())
+		{
+			// leave silence bit alone
+			
+			if(!ProcessesInPlace() )
+			{
+				mMainInput->CopyBufferContentsTo (mMainOutput->GetBufferList());
+			}
+		}
+		else
+		{
+			if(mParamList.size() == 0 )
+			{
+				// this will read/write silence bit
+				result = ProcessBufferLists(ioActionFlags, mMainInput->GetBufferList(), mMainOutput->GetBufferList(), nFrames);
+			}
+			else
+			{
+				// deal with scheduled parameters...
+				
+				AudioBufferList &inputBufferList = mMainInput->GetBufferList();
+				AudioBufferList &outputBufferList = mMainOutput->GetBufferList();
+				
+				ScheduledProcessParams processParams;
+				processParams.actionFlags = &ioActionFlags;
+				processParams.inputBufferList = &inputBufferList;
+				processParams.outputBufferList = &outputBufferList;
+	
+				// divide up the buffer into slices according to scheduled params then
+				// do the DSP for each slice (ProcessScheduledSlice() called for each slice)
+				result = ProcessForScheduledParams(	mParamList,
+													nFrames,
+													&processParams );
+	
+				
+				// fixup the buffer pointers to how they were before we started
+				UInt32 channelSize = nFrames * mBytesPerFrame;
+				for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+					UInt32 size = inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+					inputBufferList.mBuffers[i].mData = (char *)inputBufferList.mBuffers[i].mData - size;
+					inputBufferList.mBuffers[i].mDataByteSize = size;
+				}
+				
+				for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+					UInt32 size = outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+					outputBufferList.mBuffers[i].mData = (char *)outputBufferList.mBuffers[i].mData - size;
+					outputBufferList.mBuffers[i].mDataByteSize = size;
+				}
+			}
+		}
+	
+		if ( (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) && !ProcessesInPlace() )
+		{
+			AUBufferList::ZeroBuffer(mMainOutput->GetBufferList() );
+		}
+	}
+	
+	return result;
+}
+
+
+OSStatus	AUEffectBase::ProcessBufferLists(
+									AudioUnitRenderActionFlags &	ioActionFlags,
+									const AudioBufferList &			inBuffer,
+									AudioBufferList &				outBuffer,
+									UInt32							inFramesToProcess )
+{
+	if (ShouldBypassEffect())
+		return noErr;
+		
+	// interleaved (or mono)
+	switch (mCommonPCMFormat) {
+		case CAStreamBasicDescription::kPCMFormatFloat32 :
+			ProcessBufferListsT<Float32>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+			break;
+		case CAStreamBasicDescription::kPCMFormatFixed824 :
+			ProcessBufferListsT<SInt32>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+			break;
+		case CAStreamBasicDescription::kPCMFormatInt16 :
+			ProcessBufferListsT<SInt16>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+			break;
+		default :
+			throw CAException(kAudio_UnimplementedError);
+	}
+	
+	return noErr;
+}
+
+Float64		AUEffectBase::GetSampleRate()
+{
+	return GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+UInt32		AUEffectBase::GetNumberOfChannels()
+{
+	return GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
new file mode 100644
index 0000000..13ba96b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
@@ -0,0 +1,377 @@
+/*
+     File: AUEffectBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUEffectBase_h__
+#define __AUEffectBase_h__
+
+#include "AUBase.h"
+#include "AUSilentTimeout.h"
+#include "CAException.h"
+
+class AUKernelBase;
+
+//	Base class for an effect with one input stream, one output stream,
+//	any number of channels.
+	/*! @class AUEffectBase */
+class AUEffectBase : public AUBase {
+public:
+	/*! @ctor AUEffectBase */
+								AUEffectBase(	AudioComponentInstance		audioUnit,
+												bool						inProcessesInPlace = true );
+	/*! @dtor ~AUEffectBase */
+								~AUEffectBase();
+	
+	/*! @method Initialize */
+	virtual OSStatus			Initialize();
+
+	/*! @method Cleanup */
+	virtual void				Cleanup();
+
+
+	/*! @method Reset */
+	virtual OSStatus			Reset(		AudioUnitScope 				inScope,
+											AudioUnitElement 			inElement);
+
+	/*! @method GetPropertyInfo */
+	virtual OSStatus			GetPropertyInfo (AudioUnitPropertyID	inID,
+											AudioUnitScope				inScope,
+											AudioUnitElement			inElement,
+											UInt32 &					outDataSize,
+											Boolean &					outWritable);
+
+	/*! @method GetProperty */
+	virtual OSStatus			GetProperty (AudioUnitPropertyID 		inID,
+											AudioUnitScope 				inScope,
+											AudioUnitElement	 		inElement,
+											void *						outData);
+
+	/*! @method SetProperty */
+	virtual OSStatus			SetProperty(AudioUnitPropertyID 		inID,
+											AudioUnitScope 				inScope,
+											AudioUnitElement 			inElement,
+											const void *				inData,
+											UInt32 						inDataSize);
+
+	/*! @method StreamFormatWritable */
+	virtual bool				StreamFormatWritable (AudioUnitScope	scope,
+											AudioUnitElement			element);
+
+	/*! @method ChangeStreamFormat */
+	virtual	OSStatus			ChangeStreamFormat (
+										AudioUnitScope						inScope,
+										AudioUnitElement					inElement,
+										const CAStreamBasicDescription & 	inPrevFormat,
+										const CAStreamBasicDescription &	inNewFormat);
+
+	/*! @method Render */
+	virtual OSStatus 	Render(AudioUnitRenderActionFlags &		ioActionFlags,
+										const AudioTimeStamp &			inTimeStamp,
+										UInt32							inNumberFrames);
+
+	// our virtual methods
+	
+	// If your unit processes N to N channels, and there are no interactions between channels,
+	// it can override NewKernel to create a mono processing object per channel.  Otherwise,
+	// don't override NewKernel, and instead, override ProcessBufferLists.
+	/*! @method NewKernel */
+	virtual AUKernelBase *		NewKernel() { return NULL; }
+
+	/*! @method ProcessBufferLists */
+	virtual OSStatus			ProcessBufferLists(
+											AudioUnitRenderActionFlags &	ioActionFlags,
+											const AudioBufferList &			inBuffer,
+											AudioBufferList &				outBuffer,
+											UInt32							inFramesToProcess );
+
+	// convenience format accessors (use output 0's format)
+	/*! @method GetSampleRate */
+	Float64						GetSampleRate();
+	
+	/*! @method GetNumberOfChannels */
+	UInt32						GetNumberOfChannels();
+
+	// convenience wrappers for accessing parameters in the global scope
+	/*! @method SetParameter */
+	using AUBase::SetParameter;
+	void						SetParameter(			AudioUnitParameterID			paramID,
+														AudioUnitParameterValue			value)
+								{
+									Globals()->SetParameter(paramID, value);
+								}
+								
+	/*! @method GetParameter */
+	using AUBase::GetParameter;
+	AudioUnitParameterValue		GetParameter(			AudioUnitParameterID			paramID )
+								{
+									return Globals()->GetParameter(paramID );
+								}
+
+	/*! @method CanScheduleParameters */
+	virtual bool				CanScheduleParameters() const { return true; }
+	
+	/*! @method IsBypassEffect */
+	// This is used for the property value - to reflect to the UI if an effect is bypassed
+	bool						IsBypassEffect () { return mBypassEffect; }
+	
+protected:
+											
+	/*! @method MaintainKernels */
+	void						MaintainKernels();
+
+	/*! @method ShouldBypassEffect */
+	// This is used in the render call to see if an effect is bypassed
+	// It can return a different status than IsBypassEffect (though it MUST take that into account)
+	virtual	bool				ShouldBypassEffect () { return IsBypassEffect(); }
+					
+public:
+	/*! @method SetBypassEffect */
+	virtual void				SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+	
+	/*! @method SetParamHasSampleRateDependency */
+	void						SetParamHasSampleRateDependency (bool inFlag) 
+								{ 
+									mParamSRDep = inFlag; 
+								}
+	
+	/*! @method GetParamHasSampleRateDependency */
+	bool						GetParamHasSampleRateDependency () const { return mParamSRDep; }
+
+	struct ScheduledProcessParams	// pointer passed in as void* userData param for ProcessScheduledSlice()
+	{
+		AudioUnitRenderActionFlags 	*actionFlags;
+		AudioBufferList 			*inputBufferList;
+		AudioBufferList 			*outputBufferList;
+	};
+
+	virtual OSStatus			ProcessScheduledSlice(	void				*inUserData,
+														UInt32				inStartFrameInBuffer,
+														UInt32				inSliceFramesToProcess,
+														UInt32				inTotalBufferFrames );
+
+
+	bool							ProcessesInPlace() const {return mProcessesInPlace;};
+	void							SetProcessesInPlace(bool inProcessesInPlace) {mProcessesInPlace = inProcessesInPlace;};
+		
+	typedef std::vector<AUKernelBase *> KernelList;
+	
+	
+
+protected:	
+	/*! @var mKernelList */
+	KernelList						mKernelList;
+
+	AUKernelBase* GetKernel(UInt32 index) { return mKernelList[index]; }
+
+	/*! @method IsInputSilent */
+	bool 							IsInputSilent (AudioUnitRenderActionFlags 	inActionFlags, UInt32 inFramesToProcess)
+									{
+										bool inputSilent = (inActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0;
+									
+										// take latency and tail time into account when propagating the silent bit
+										UInt32 silentTimeoutFrames = UInt32(GetSampleRate() * (GetLatency() + GetTailTime()));
+										mSilentTimeout.Process (inFramesToProcess, silentTimeoutFrames, inputSilent);
+										return inputSilent;
+									}
+									
+#if TARGET_OS_IPHONE
+	void SetOnlyOneKernel(bool inUseOnlyOneKernel) { mOnlyOneKernel = inUseOnlyOneKernel; } // set in ctor of subclass that wants it.
+#endif
+
+	template <typename T>
+	void	ProcessBufferListsT(
+										AudioUnitRenderActionFlags &	ioActionFlags,
+										const AudioBufferList &			inBuffer,
+										AudioBufferList &				outBuffer,
+										UInt32							inFramesToProcess );
+
+	CAStreamBasicDescription::CommonPCMFormat GetCommonPCMFormat() const { return mCommonPCMFormat; }
+	
+
+private:
+	/*! @var mBypassEffect */
+	bool							mBypassEffect;
+	/*! @var mParamSRDep */
+	bool							mParamSRDep;
+	
+	/*! @var mProcessesInplace */
+	bool							mProcessesInPlace;
+	
+	/*! @var mSilentTimeout */
+	AUSilentTimeout					mSilentTimeout;
+
+	/*! @var mMainOutput */
+	AUOutputElement *				mMainOutput;
+	
+	/*! @var mMainInput */
+	AUInputElement *				mMainInput;
+	
+#if TARGET_OS_IPHONE
+	/*! @var mOnlyOneKernel */
+	bool							mOnlyOneKernel;
+#endif
+
+	/*! @var mCommonPCMFormat */
+	CAStreamBasicDescription::CommonPCMFormat		mCommonPCMFormat;
+	UInt32							mBytesPerFrame;
+};
+
+
+//	Base class for a "kernel", an object that performs DSP on one channel of an interleaved stream.
+	/*! @class AUKernelBase */
+class AUKernelBase {
+public:
+	/*! @ctor AUKernelBase */
+								AUKernelBase(AUEffectBase *inAudioUnit ) :
+									mAudioUnit(inAudioUnit) { }
+
+	/*! @dtor ~AUKernelBase */
+	virtual						~AUKernelBase() { }
+
+	/*! @method Reset */
+	virtual void				Reset() { }
+
+	/*! @method Process */
+	virtual void 				Process(	const Float32 *						inSourceP,
+											Float32 *							inDestP,
+											UInt32								inFramesToProcess,
+											UInt32								inNumChannels,
+											bool &								ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+	/*! @method Process */
+	virtual void 				Process(	const SInt32 *						inSourceP,
+											SInt32 *							inDestP,
+											UInt32								inFramesToProcess,
+											UInt32								inNumChannels,
+											bool &								ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+	/*! @method Process */
+	virtual void 				Process(	const SInt16 *						inSourceP,
+											SInt16 *							inDestP,
+											UInt32								inFramesToProcess,
+											UInt32								inNumChannels,
+											bool &								ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+	/*! @method GetSampleRate */
+	Float64						GetSampleRate()
+								{
+									return mAudioUnit->GetSampleRate();
+								}
+								
+	/*! @method GetParameter */
+	AudioUnitParameterValue		GetParameter (AudioUnitParameterID	paramID) 
+								{
+									return mAudioUnit->GetParameter(paramID);
+								}
+	
+	void						SetChannelNum (UInt32 inChan) { mChannelNum = inChan; }
+	UInt32						GetChannelNum () { return mChannelNum; }
+	
+protected:
+	/*! @var mAudioUnit */
+	AUEffectBase * 		mAudioUnit;
+	UInt32				mChannelNum;
+
+};
+
+template <typename T>
+void	AUEffectBase::ProcessBufferListsT(
+									AudioUnitRenderActionFlags &	ioActionFlags,
+									const AudioBufferList &			inBuffer,
+									AudioBufferList &				outBuffer,
+									UInt32							inFramesToProcess )
+{
+	bool ioSilence;
+
+	bool silentInput = IsInputSilent (ioActionFlags, inFramesToProcess);
+	ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
+
+	// call the kernels to handle either interleaved or deinterleaved
+	if (inBuffer.mNumberBuffers == 1) {
+		if (inBuffer.mBuffers[0].mNumberChannels == 0)
+			throw CAException(kAudio_ParamError);
+			
+		for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) {
+			AUKernelBase *kernel = mKernelList[channel];
+			
+			if (kernel == NULL) continue;
+			ioSilence = silentInput;
+			
+			// process each interleaved channel individually
+			kernel->Process(
+				(const T *)inBuffer.mBuffers[0].mData + channel, 
+				(T *)outBuffer.mBuffers[0].mData + channel,
+				inFramesToProcess,
+				inBuffer.mBuffers[0].mNumberChannels,
+				ioSilence);
+				
+			if (!ioSilence)
+				ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+		}
+	} else {
+		for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) {
+			AUKernelBase *kernel = mKernelList[channel];
+			
+			if (kernel == NULL) continue;
+			
+			ioSilence = silentInput;
+			const AudioBuffer *srcBuffer = &inBuffer.mBuffers[channel];
+			AudioBuffer *destBuffer = &outBuffer.mBuffers[channel];
+			
+			kernel->Process(
+				(const T *)srcBuffer->mData, 
+				(T *)destBuffer->mData, 
+				inFramesToProcess,
+				1,
+				ioSilence);
+				
+			if (!ioSilence)
+				ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+		}
+	}
+}
+
+
+#endif // __AUEffectBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
new file mode 100644
index 0000000..e5e358d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
@@ -0,0 +1,495 @@
+/*
+     File: AUMIDIBase.cpp
+ Abstract: AUMIDIBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUMIDIBase.h"
+#include <CoreMIDI/CoreMIDI.h>
+#include "CAXException.h"
+
+//temporaray location
+enum
+{
+	kMidiMessage_NoteOff 			= 0x80,
+	kMidiMessage_NoteOn 			= 0x90,
+	kMidiMessage_PolyPressure 		= 0xA0,
+	kMidiMessage_ControlChange 		= 0xB0,
+	kMidiMessage_ProgramChange 		= 0xC0,
+	kMidiMessage_ChannelPressure 	= 0xD0,
+	kMidiMessage_PitchWheel 		= 0xE0,
+
+	kMidiController_AllSoundOff			= 120,
+	kMidiController_ResetAllControllers	= 121,
+	kMidiController_AllNotesOff			= 123
+};
+
+AUMIDIBase::AUMIDIBase(AUBase* inBase) 
+	: mAUBaseInstance (*inBase) 
+{
+#if CA_AUTO_MIDI_MAP
+	mMapManager = new CAAUMIDIMapManager();
+#endif
+}
+
+AUMIDIBase::~AUMIDIBase() 
+{
+#if CA_AUTO_MIDI_MAP
+	if (mMapManager) 
+		delete mMapManager;
+#endif
+}
+
+#if TARGET_API_MAC_OSX
+OSStatus			AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID				inID,
+														AudioUnitScope					inScope,
+														AudioUnitElement				inElement,
+														UInt32 &						outDataSize,
+														Boolean &						outWritable)
+{
+	OSStatus result = noErr;
+	
+	switch (inID) {
+#if !TARGET_OS_IPHONE
+	case kMusicDeviceProperty_MIDIXMLNames:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		if (GetXMLNames(NULL) == noErr) {
+			outDataSize = sizeof(CFURLRef);
+			outWritable = false;
+		} else
+			result = kAudioUnitErr_InvalidProperty;
+		break;
+#endif		
+#if CA_AUTO_MIDI_MAP				
+	case kAudioUnitProperty_AllParameterMIDIMappings:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		outWritable = true;
+		outDataSize = sizeof (AUParameterMIDIMapping)*mMapManager->NumMaps();
+		result = noErr;
+		break;
+	
+	case kAudioUnitProperty_HotMapParameterMIDIMapping:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		outWritable = true;
+		outDataSize = sizeof (AUParameterMIDIMapping); 
+		result = noErr;
+		break;
+		
+	case kAudioUnitProperty_AddParameterMIDIMapping:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		outWritable = true;
+		outDataSize = sizeof (AUParameterMIDIMapping);
+		result = noErr;
+		break;
+		
+	case kAudioUnitProperty_RemoveParameterMIDIMapping:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		outWritable = true;
+		outDataSize = sizeof (AUParameterMIDIMapping); 
+		result = noErr;
+		break;
+#endif
+
+	default:
+		result = kAudioUnitErr_InvalidProperty;
+		break;
+	}
+	return result;
+
+#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
+InvalidScope:
+	return kAudioUnitErr_InvalidScope;
+InvalidElement:
+	return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+OSStatus			AUMIDIBase::DelegateGetProperty(	AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement,
+														void *							outData)
+{
+	OSStatus result;
+	
+	switch (inID) {
+#if !TARGET_OS_IPHONE
+	case kMusicDeviceProperty_MIDIXMLNames:
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		result = GetXMLNames((CFURLRef *)outData);
+		break;
+#endif		
+#if CA_AUTO_MIDI_MAP
+	case kAudioUnitProperty_AllParameterMIDIMappings:{
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		AUParameterMIDIMapping*  maps =  (static_cast<AUParameterMIDIMapping*>(outData));
+		mMapManager->GetMaps(maps);
+//		printf ("GETTING MAPS\n");
+//		mMapManager->Print();
+		result = noErr;
+		break;
+	}
+		
+	case kAudioUnitProperty_HotMapParameterMIDIMapping:{
+		ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+		ca_require(inElement == 0, InvalidElement);
+		AUParameterMIDIMapping *  map =  (static_cast<AUParameterMIDIMapping*>(outData));
+		mMapManager->GetHotParameterMap (*map);
+		result = noErr;
+		break;
+	}
+#endif
+	
+	default:
+		result = kAudioUnitErr_InvalidProperty;
+		break;
+	}
+	return result;
+
+#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
+InvalidScope:
+	return kAudioUnitErr_InvalidScope;
+InvalidElement:
+	return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+OSStatus			AUMIDIBase::DelegateSetProperty(	AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement			 	inElement,
+														const void *					inData,
+														UInt32							inDataSize)
+{
+	OSStatus result;
+	
+	switch (inID) {
+#if CA_AUTO_MIDI_MAP
+		case kAudioUnitProperty_AddParameterMIDIMapping:{
+			ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+			ca_require(inElement == 0, InvalidElement);
+			AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
+			mMapManager->SortedInsertToParamaterMaps (maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
+			mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);	 
+			result = noErr;
+			break;
+		}
+			
+		case kAudioUnitProperty_RemoveParameterMIDIMapping:{
+			ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+			ca_require(inElement == 0, InvalidElement);
+			AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
+			bool didChange;
+			mMapManager->SortedRemoveFromParameterMaps(maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange);
+			if (didChange)
+				mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);	 
+			result = noErr;
+			break;
+		}
+					
+		case kAudioUnitProperty_HotMapParameterMIDIMapping:{
+			ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+			ca_require(inElement == 0, InvalidElement);
+			AUParameterMIDIMapping & map = *((AUParameterMIDIMapping*)inData);
+			mMapManager->SetHotMapping (map);			
+			result = noErr;
+			break;
+		}
+		case kAudioUnitProperty_AllParameterMIDIMappings:{
+			ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+			ca_require(inElement == 0, InvalidElement);
+			AUParameterMIDIMapping * mappings = (AUParameterMIDIMapping*)inData;
+			mMapManager->ReplaceAllMaps (mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
+			result = noErr;
+			break;
+		}
+#endif
+		
+	default:
+		result = kAudioUnitErr_InvalidProperty;
+		break;
+	}
+	return result;
+#if CA_AUTO_MIDI_MAP
+	InvalidScope:
+		return kAudioUnitErr_InvalidScope;
+	InvalidElement:
+		return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+
+
+#endif //TARGET_API_MAC_OSX
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#pragma mark ____MidiDispatch
+
+
+inline const Byte *	NextMIDIEvent(const Byte *event, const Byte *end)
+{
+	Byte c = *event;
+	switch (c >> 4) {
+	default:	// data byte -- assume in sysex
+		while ((*++event & 0x80) == 0 && event < end)
+			;
+		break;
+	case 0x8:
+	case 0x9:
+	case 0xA:
+	case 0xB:
+	case 0xE:
+		event += 3;
+		break;
+	case 0xC:
+	case 0xD:
+		event += 2;
+		break;
+	case 0xF:
+		switch (c) {
+		case 0xF0:
+			while ((*++event & 0x80) == 0 && event < end)
+				;
+			break;
+		case 0xF1:
+		case 0xF3:
+			event += 2;
+			break;
+		case 0xF2:
+			event += 3;
+			break;
+		default:
+			++event;
+			break;
+		}
+	}
+	return (event >= end) ? end : event;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//	AUMIDIBase::HandleMIDIPacketList
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus			AUMIDIBase::HandleMIDIPacketList(const MIDIPacketList *pktlist)
+{
+	if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+	
+	int nPackets = pktlist->numPackets;
+	const MIDIPacket *pkt = pktlist->packet;
+	
+	while (nPackets-- > 0) {
+		const Byte *event = pkt->data, *packetEnd = event + pkt->length;
+		long startFrame = (long)pkt->timeStamp;
+		while (event < packetEnd) {
+			Byte status = event[0];
+			if (status & 0x80) {
+				// really a status byte (not sysex continuation)
+				HandleMidiEvent(status & 0xF0, status & 0x0F, event[1], event[2], static_cast<UInt32>(startFrame));
+					// note that we're generating a bogus channel number for system messages (0xF0-FF)
+			}
+			event = NextMIDIEvent(event, packetEnd);
+		}
+		pkt = reinterpret_cast<const MIDIPacket *>(packetEnd);
+	}
+	return noErr;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//	AUMIDIBase::HandleMidiEvent
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus 	AUMIDIBase::HandleMidiEvent(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+	if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+		
+#if CA_AUTO_MIDI_MAP	
+// you potentially have a choice to make here - if a param mapping matches, do you still want to process the 
+// MIDI event or not. The default behaviour is to continue on with the MIDI event.
+	if (mMapManager->HandleHotMapping (status, channel, data1, mAUBaseInstance)) {
+		mAUBaseInstance.PropertyChanged (kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
+	}
+	else {
+		mMapManager->FindParameterMapEventMatch(status, channel, data1, data2, inStartFrame, mAUBaseInstance);
+	}	
+#endif	
+	
+	OSStatus result = noErr;
+	
+	switch(status)
+	{
+		case kMidiMessage_NoteOn:
+			if(data2)
+			{
+				result = HandleNoteOn(channel, data1, data2, inStartFrame);
+			}
+			else
+			{
+				// zero velocity translates to note off
+				result = HandleNoteOff(channel, data1, data2, inStartFrame);
+			}
+			break;
+			
+		case kMidiMessage_NoteOff:
+			result = HandleNoteOff(channel, data1, data2, inStartFrame);
+			break;
+		
+		default:
+			result = HandleNonNoteEvent (status, channel, data1, data2, inStartFrame);
+			break;
+	}
+	
+	return result;
+}
+
+OSStatus	AUMIDIBase::HandleNonNoteEvent (UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+	OSStatus result = noErr;
+
+	switch (status)
+	{
+		case kMidiMessage_PitchWheel:
+			result = HandlePitchWheel(channel, data1, data2, inStartFrame);
+			break;
+			
+		case kMidiMessage_ProgramChange:
+			result = HandleProgramChange(channel, data1);
+			break;
+			
+		case kMidiMessage_ChannelPressure:
+			result = HandleChannelPressure(channel, data1, inStartFrame);
+			break;
+			
+		case kMidiMessage_ControlChange:
+		{
+			switch (data1) {
+				case kMidiController_AllNotesOff:
+					result = HandleAllNotesOff(channel);
+					break;
+
+				case kMidiController_ResetAllControllers:
+					result = HandleResetAllControllers(channel);
+					break;
+
+				case kMidiController_AllSoundOff:
+					result = HandleAllSoundOff(channel);
+					break;
+								
+				default:
+					result = HandleControlChange(channel, data1, data2, inStartFrame);
+					break;
+			}
+			break;
+		}
+		case kMidiMessage_PolyPressure:
+			result = HandlePolyPressure (channel, data1, data2, inStartFrame);
+			break;
+	}
+	return result;
+}
+
+OSStatus 	AUMIDIBase::SysEx (const UInt8 *	inData, 
+										UInt32			inLength)
+{
+	if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+	return HandleSysEx(inData, inLength );
+}
+
+
+
+#if TARGET_OS_MAC
+	#if __LP64__
+		// comp instance, parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index + 1];
+	#else
+		// parameters in reverse order, then comp instance
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+	#endif
+#elif TARGET_OS_WIN32
+		// (no comp instance), parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus			AUMIDIBase::ComponentEntryDispatch(	ComponentParameters *			params,
+															AUMIDIBase *				This)
+{
+	if (This == NULL) return kAudio_ParamError;
+
+	OSStatus result;
+	
+	switch (params->what) {
+	case kMusicDeviceMIDIEventSelect:
+		{
+			PARAM(UInt32, pbinStatus, 0, 4);
+			PARAM(UInt32, pbinData1, 1, 4);
+			PARAM(UInt32, pbinData2, 2, 4);
+			PARAM(UInt32, pbinOffsetSampleFrame, 3, 4);
+			result = This->MIDIEvent(pbinStatus, pbinData1, pbinData2, pbinOffsetSampleFrame);
+		}
+		break;
+	case kMusicDeviceSysExSelect:
+		{
+			PARAM(const UInt8 *, pbinData, 0, 2);
+			PARAM(UInt32, pbinLength, 1, 2);
+			result = This->SysEx(pbinData, pbinLength);
+		}
+		break;
+
+	default:
+		result = badComponentSelector;
+		break;
+	}
+	
+	return result;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
new file mode 100644
index 0000000..40c6a77
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
@@ -0,0 +1,213 @@
+/*
+     File: AUMIDIBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUMIDIBase_h__
+#define __AUMIDIBase_h__
+
+#include "AUBase.h"
+
+#if CA_AUTO_MIDI_MAP
+	#include "CAAUMIDIMapManager.h"
+#endif
+
+struct MIDIPacketList;
+
+// ________________________________________________________________________
+//	MusicDeviceBase
+//
+	/*! @class AUMIDIBase */
+class AUMIDIBase {
+public:
+									// this is NOT a copy constructor!
+	/*! @ctor AUMIDIBase */
+								AUMIDIBase(AUBase* inBase);
+	/*! @dtor ~AUMIDIBase */
+	virtual						~AUMIDIBase();
+	
+	/*! @method MIDIEvent */
+	virtual OSStatus	MIDIEvent(		UInt32 						inStatus, 
+										UInt32 						inData1, 
+										UInt32 						inData2, 
+										UInt32 						inOffsetSampleFrame)
+	{
+		UInt32 strippedStatus = inStatus & 0xf0;
+		UInt32 channel = inStatus & 0x0f;
+	
+		return HandleMidiEvent(strippedStatus, channel, inData1, inData2, inOffsetSampleFrame);
+	}
+	
+	/*! @method HandleMIDIPacketList */
+	OSStatus			HandleMIDIPacketList(const MIDIPacketList *pktlist);
+	
+	/*! @method SysEx */
+	virtual OSStatus	SysEx(			const UInt8 *				inData, 
+										UInt32 						inLength);
+
+#if TARGET_API_MAC_OSX
+	/*! @method DelegateGetPropertyInfo */
+	virtual OSStatus			DelegateGetPropertyInfo(AudioUnitPropertyID			inID,
+														AudioUnitScope				inScope,
+														AudioUnitElement			inElement,
+														UInt32 &					outDataSize,
+														Boolean &					outWritable);
+
+	/*! @method DelegateGetProperty */
+	virtual OSStatus			DelegateGetProperty(	AudioUnitPropertyID 		inID,
+														AudioUnitScope 				inScope,
+														AudioUnitElement		 	inElement,
+														void *						outData);
+														
+	/*! @method DelegateSetProperty */
+	virtual OSStatus			DelegateSetProperty(	AudioUnitPropertyID 		inID,
+														AudioUnitScope 				inScope,
+														AudioUnitElement		 	inElement,
+														const void *				inData,
+														UInt32						inDataSize);
+#endif
+
+protected:
+	// MIDI dispatch
+	/*! @method HandleMidiEvent */
+	virtual OSStatus	HandleMidiEvent(		UInt8 	inStatus,
+												UInt8 	inChannel,
+												UInt8 	inData1,
+												UInt8 	inData2,
+												UInt32 	inStartFrame);
+
+	/*! @method HandleNonNoteEvent */
+	virtual OSStatus	HandleNonNoteEvent (	UInt8	status, 
+												UInt8	channel, 
+												UInt8	data1, 
+												UInt8	data2, 
+												UInt32	inStartFrame);
+
+#if TARGET_API_MAC_OSX
+	/*! @method GetXMLNames */
+	virtual OSStatus			GetXMLNames(CFURLRef *outNameDocument) 
+	{ return kAudioUnitErr_InvalidProperty; }	// if not overridden, it's unsupported
+#endif
+
+// channel messages
+	/*! @method HandleNoteOn */
+	virtual OSStatus	HandleNoteOn(			UInt8 	inChannel,
+												UInt8 	inNoteNumber,
+												UInt8 	inVelocity,
+												UInt32 	inStartFrame) { return noErr; }
+												
+	/*! @method HandleNoteOff */
+	virtual OSStatus	HandleNoteOff(			UInt8 	inChannel,
+												UInt8 	inNoteNumber,
+												UInt8 	inVelocity,
+												UInt32 	inStartFrame) { return noErr; }
+												
+	/*! @method HandleControlChange */
+	virtual OSStatus	HandleControlChange(	UInt8 	inChannel,
+												UInt8 	inController,
+												UInt8 	inValue,
+												UInt32	inStartFrame) { return noErr; }
+												
+	/*! @method HandlePitchWheel */
+	virtual OSStatus	HandlePitchWheel(		UInt8 	inChannel,
+												UInt8 	inPitch1,
+												UInt8 	inPitch2,
+												UInt32	inStartFrame) { return noErr; }
+												
+	/*! @method HandleChannelPressure */
+	virtual OSStatus	HandleChannelPressure(	UInt8 	inChannel,
+												UInt8 	inValue,
+												UInt32	inStartFrame) { return noErr; }
+
+	/*! @method HandleProgramChange */
+	virtual OSStatus	HandleProgramChange(	UInt8 	inChannel,
+												UInt8 	inValue) { return noErr; }
+
+	/*! @method HandlePolyPressure */
+	virtual OSStatus	HandlePolyPressure(		UInt8 	inChannel,
+												UInt8 	inKey,
+												UInt8	inValue,
+												UInt32	inStartFrame) { return noErr; }
+
+	/*! @method HandleResetAllControllers */
+	virtual OSStatus	HandleResetAllControllers(UInt8 inChannel) { return noErr; }
+	
+	/*! @method HandleAllNotesOff */
+	virtual OSStatus	HandleAllNotesOff(		UInt8	inChannel) { return noErr; }
+	
+	/*! @method HandleAllSoundOff */
+	virtual OSStatus	HandleAllSoundOff(		UInt8	inChannel) { return noErr; }
+
+
+//System messages   
+	/*! @method HandleSysEx */
+	virtual OSStatus	HandleSysEx(			const UInt8 *	inData,
+                                        		UInt32			inLength ) { return noErr; }
+
+#if CA_AUTO_MIDI_MAP
+	/* map manager */
+	CAAUMIDIMapManager			*GetMIDIMapManager() {return mMapManager;};
+	
+#endif
+
+												
+private:
+	/*! @var mAUBaseInstance */
+	AUBase						& mAUBaseInstance;
+	
+#if CA_AUTO_MIDI_MAP
+	/* map manager */
+	CAAUMIDIMapManager			* mMapManager;
+#endif
+	
+public:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	// component dispatcher
+	/*! @method ComponentEntryDispatch */
+	static OSStatus			ComponentEntryDispatch(	ComponentParameters 		*params,
+														AUMIDIBase 					*This);
+#endif
+};
+
+#endif // __AUMIDIBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
new file mode 100644
index 0000000..dfe307c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
@@ -0,0 +1,164 @@
+/*
+     File: AUMIDIEffectBase.cpp
+ Abstract: AUMIDIEffectBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUMIDIEffectBase.h"
+
+// compatibility with older OS SDK releases
+typedef OSStatus
+(*TEMP_MusicDeviceMIDIEventProc)(	void *				inComponentStorage,
+				UInt32					inStatus,
+				UInt32					inData1,
+				UInt32					inData2,
+				UInt32					inOffsetSampleFrame);
+
+static OSStatus		AUMIDIEffectBaseMIDIEvent(void *				inComponentStorage,
+						UInt32					inStatus,
+						UInt32					inData1,
+						UInt32					inData2,
+						UInt32					inOffsetSampleFrame);
+
+AUMIDIEffectBase::AUMIDIEffectBase(		AudioComponentInstance				inInstance,
+						bool 						inProcessesInPlace ) 
+	: AUEffectBase(inInstance, inProcessesInPlace),
+	  AUMIDIBase(this)
+{
+}
+
+OSStatus			AUMIDIEffectBase::GetPropertyInfo(AudioUnitPropertyID			inID,
+							AudioUnitScope				inScope,
+							AudioUnitElement			inElement,
+							UInt32 &				outDataSize,
+							Boolean &				outWritable)
+{
+	OSStatus result;
+	
+	result = AUEffectBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+	
+	if (result == kAudioUnitErr_InvalidProperty)
+		result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+	
+	return result;
+}
+
+OSStatus			AUMIDIEffectBase::GetProperty(	AudioUnitPropertyID		inID,
+													AudioUnitScope 			inScope,
+													AudioUnitElement		inElement,
+													void *					outData)
+{
+	OSStatus result;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	if (inID == kAudioUnitProperty_FastDispatch) {
+		if (inElement == kMusicDeviceMIDIEventSelect) {
+			*(TEMP_MusicDeviceMIDIEventProc *)outData = AUMIDIEffectBaseMIDIEvent;
+			return noErr;
+		}
+		return kAudioUnitErr_InvalidElement;
+	}
+#endif
+	
+	result = AUEffectBase::GetProperty (inID, inScope, inElement, outData);
+	
+	if (result == kAudioUnitErr_InvalidProperty)
+		result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
+	
+	return result;
+}
+
+OSStatus			AUMIDIEffectBase::SetProperty(	AudioUnitPropertyID			inID,
+							AudioUnitScope 				inScope,
+							AudioUnitElement		 	inElement,
+							const void *				inData,
+							UInt32					inDataSize)
+{
+
+	OSStatus result = AUEffectBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+		
+	if (result == kAudioUnitErr_InvalidProperty)
+		result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
+		
+	return result;
+}
+
+
+#if !TARGET_OS_IPHONE
+OSStatus			AUMIDIEffectBase::ComponentEntryDispatch(ComponentParameters *			params,
+								AUMIDIEffectBase *			This)
+{
+	if (This == NULL) return paramErr;
+
+	OSStatus result;
+	
+	switch (params->what) {
+	case kMusicDeviceMIDIEventSelect:
+	case kMusicDeviceSysExSelect:
+		result = AUMIDIBase::ComponentEntryDispatch (params, This);
+		break;
+	default:
+		result = AUEffectBase::ComponentEntryDispatch(params, This);
+		break;
+	}
+	
+	return result;
+}
+#endif
+
+// fast dispatch
+static OSStatus		AUMIDIEffectBaseMIDIEvent(void *				inComponentStorage,
+						UInt32					inStatus,
+						UInt32					inData1,
+						UInt32					inData2,
+						UInt32					inOffsetSampleFrame)
+{
+	OSStatus result = noErr;
+	try {
+		AUMIDIEffectBase *This = static_cast<AUMIDIEffectBase *>(inComponentStorage);
+		if (This == NULL) return paramErr;
+		result = This->AUMIDIBase::MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+	}
+	COMPONENT_CATCH
+	return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
new file mode 100644
index 0000000..b38f506
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
@@ -0,0 +1,104 @@
+/*
+     File: AUMIDIEffectBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUMIDIEffectBase_h__
+#define __AUMIDIEffectBase_h__
+
+#include "AUMIDIBase.h"
+#include "AUEffectBase.h"
+
+// ________________________________________________________________________
+//	AUMIDIEffectBase
+//
+	/*! @class AUMIDIEffectBase */
+class AUMIDIEffectBase : public AUEffectBase, public AUMIDIBase {
+public:
+	/*! @ctor AUMIDIEffectBase */
+								AUMIDIEffectBase(	AudioComponentInstance	inInstance,
+													bool					inProcessesInPlace = false );
+    /*! @method MIDIEvent */
+    virtual OSStatus            MIDIEvent(UInt32            inStatus,
+                                          UInt32            inData1,
+                                          UInt32            inData2,
+                                          UInt32            inOffsetSampleFrame)
+	{
+		return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
+	}
+    
+	/*! @method SysEx */
+	virtual OSStatus            SysEx(const UInt8 *         inData,
+                                      UInt32                inLength)
+	{
+		return AUMIDIBase::SysEx (inData, inLength);
+	}
+
+	/*! @method GetPropertyInfo */
+	virtual OSStatus			GetPropertyInfo(AudioUnitPropertyID			inID,
+												AudioUnitScope				inScope,
+												AudioUnitElement			inElement,
+												UInt32 &					outDataSize,
+												Boolean &					outWritable);
+
+	/*! @method GetProperty */
+	virtual OSStatus			GetProperty(	AudioUnitPropertyID 		inID,
+												AudioUnitScope 				inScope,
+												AudioUnitElement		 	inElement,
+												void *						outData);
+	/*! @method SetProperty */
+	virtual OSStatus			SetProperty(	AudioUnitPropertyID 		inID,
+												AudioUnitScope 				inScope,
+												AudioUnitElement		 	inElement,
+												const void *				inData,
+												UInt32						inDataSize);
+#if !TARGET_OS_IPHONE
+	// component dispatcher
+	/*! @method ComponentEntryDispatch */
+	static OSStatus			ComponentEntryDispatch(	ComponentParameters *			params,
+														AUMIDIEffectBase *				This);
+#endif
+};
+
+#endif // __AUMIDIEffectBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
new file mode 100644
index 0000000..591c43a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
@@ -0,0 +1,76 @@
+/*
+     File: AUOutputBase.cpp
+ Abstract: AUOutputBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#include "AUOutputBase.h"
+
+OSStatus		AUOutputBase::ComponentEntryDispatch(ComponentParameters *params, AUOutputBase *This)
+{
+	if (This == NULL) return paramErr;
+
+	OSStatus result;
+	
+	switch (params->what) {
+	case kAudioOutputUnitStartSelect:
+		{
+			result = This->Start();
+		}
+		break;
+
+	case kAudioOutputUnitStopSelect:
+		{
+			result = This->Stop();
+		}
+		break;
+
+	default:
+		result = badComponentSelector;
+		break;
+	}
+	
+	return result;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
new file mode 100644
index 0000000..8e5399b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
@@ -0,0 +1,82 @@
+/*
+     File: AUOutputBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUOutputBase_h__
+#define __AUOutputBase_h__
+
+#include "AUBase.h"
+
+// ________________________________________________________________________
+//	AUOutputBase
+//	this is now a mix-in rather than an AUBase subclass
+
+	/*! @class AUOutputBase */
+class AUOutputBase {
+public:
+	/*! @ctor AUOutputBase */
+								AUOutputBase(AUBase *inBase) : mAUBaseInstance(*inBase) { }
+	virtual ~AUOutputBase() { }
+
+	// additional component entry points
+	/*! @method Start */
+	virtual OSStatus			Start() = 0;
+	
+	/*! @method Stop */
+	virtual OSStatus			Stop() = 0;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	// component dispatcher
+	/*! @method ComponentEntryDispatch */
+	static OSStatus			ComponentEntryDispatch(	ComponentParameters *			params,
+														AUOutputBase *					This);
+#endif
+
+private:
+	/*! @var mAUBaseInstance */
+	AUBase &					mAUBaseInstance;
+};
+
+#endif // __AUOutputBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
new file mode 100644
index 0000000..f1e2f24
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
@@ -0,0 +1,706 @@
+/*
+     File: AUPannerBase.cpp
+ Abstract: AUPannerBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUPannerBase.h"
+#include "CABundleLocker.h"
+#include <AudioToolbox/AudioToolbox.h>
+#include <Accelerate/Accelerate.h>
+
+static bool sLocalized = false;
+
+static CFStringRef kPanner_Azimuth_Name = CFSTR("azimuth"); 	
+static CFStringRef kPanner_Elevation_Name = CFSTR("elevation"); 	
+static CFStringRef kPanner_Distance_Name = CFSTR("distance");
+
+static CFStringRef kPanner_CoordScale_Name = CFSTR("coordinate scale"); 	
+static CFStringRef kPanner_RefDistance_Name = CFSTR("reference distance"); 	
+static CFStringRef kPanner_Gain_Name = CFSTR("gain"); 	
+
+static Float32 kPannerParamDefault_Azimuth = 0.;
+static Float32 kPannerParamDefault_Elevation = 0.;
+static Float32 kPannerParamDefault_Distance = 1.;
+
+static Float32 kPannerParamDefault_CoordScale = 10.;
+static Float32 kPannerParamDefault_RefDistance = 1.;
+static Float32 kPannerParamDefault_Gain = 1.;
+
+//_____________________________________________________________________________
+//
+AUPannerBase::AUPannerBase(AudioComponentInstance inAudioUnit)
+    : AUBase(inAudioUnit, 1, 1), mBypassEffect(false)
+{
+	{
+		CABundleLocker lock;
+		if (!sLocalized)
+		{		
+			CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.audio.units.Components") );
+			if (bundle != NULL)
+			{
+				kPanner_Azimuth_Name 	= CFCopyLocalizedStringFromTableInBundle(kPanner_Azimuth_Name,    CFSTR("AudioUnits"), bundle, CFSTR(""));
+				kPanner_Elevation_Name 	= CFCopyLocalizedStringFromTableInBundle(kPanner_Elevation_Name,  CFSTR("AudioUnits"), bundle, CFSTR(""));
+				kPanner_Distance_Name 	= CFCopyLocalizedStringFromTableInBundle(kPanner_Distance_Name,   CFSTR("AudioUnits"), bundle, CFSTR(""));
+				
+				kPanner_CoordScale_Name  = CFCopyLocalizedStringFromTableInBundle(kPanner_CoordScale_Name,  CFSTR("AudioUnits"), bundle, CFSTR(""));
+				kPanner_RefDistance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_RefDistance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+				kPanner_Gain_Name 	     = CFCopyLocalizedStringFromTableInBundle(kPanner_Gain_Name,        CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+			}
+			
+			sLocalized = true;
+		}
+	}
+	
+	CreateElements();
+	
+    SetParameter(kPannerParam_Azimuth, kPannerParamDefault_Azimuth);
+    SetParameter(kPannerParam_Elevation, kPannerParamDefault_Elevation);
+    SetParameter(kPannerParam_Distance, kPannerParamDefault_Distance);
+    
+    SetParameter(kPannerParam_CoordScale, kPannerParamDefault_CoordScale);
+    SetParameter(kPannerParam_RefDistance, kPannerParamDefault_RefDistance);
+    SetParameter(kPannerParam_Gain, kPannerParamDefault_Gain);
+}
+
+//_____________________________________________________________________________
+//
+AUPannerBase::~AUPannerBase()
+{
+    Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Initialize */
+OSStatus			AUPannerBase::Initialize()
+{
+	OSStatus err = noErr;
+	AllocBypassMatrix();
+	err = UpdateBypassMatrix();
+	return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method AllocBypassMatrix */
+void		AUPannerBase::AllocBypassMatrix()
+{
+	UInt32 inChannels = GetNumberOfInputChannels();
+	UInt32 outChannels = GetNumberOfOutputChannels();
+	mBypassMatrix.alloc(inChannels * outChannels, true);
+}
+
+static AudioChannelLayoutTag DefaultTagForNumberOfChannels(UInt32 inNumberChannels)
+{
+	switch (inNumberChannels) {
+		case 1: return kAudioChannelLayoutTag_Mono; 
+		case 2: return kAudioChannelLayoutTag_Stereo; 
+		case 4: return kAudioChannelLayoutTag_Quadraphonic; 
+		case 5: return kAudioChannelLayoutTag_AudioUnit_5_0; 
+		case 6: return kAudioChannelLayoutTag_AudioUnit_6_0; 
+		case 7: return kAudioChannelLayoutTag_AudioUnit_7_0; 
+		case 8: return kAudioChannelLayoutTag_AudioUnit_8; 
+
+		default: return 0xFFFF0000 | inNumberChannels;
+	}
+}
+
+//_____________________________________________________________________________
+//
+/*! @method UpdateBypassMatrix */
+OSStatus			AUPannerBase::SetDefaultChannelLayoutsIfNone()
+{
+	OSStatus err = noErr;
+	
+	// if layout has not been set, then guess layout from number of channels
+	UInt32 inChannels = GetNumberOfInputChannels();
+	AudioChannelLayout inputLayoutSubstitute;
+	const AudioChannelLayout* inputLayout = &GetInputLayout();
+	if (inputLayout == NULL || inputLayout->mChannelLayoutTag == 0) {
+		inputLayout = &inputLayoutSubstitute;
+		inputLayoutSubstitute.mNumberChannelDescriptions = 0;
+		inputLayoutSubstitute.mChannelBitmap = 0;
+		inputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(inChannels);
+
+		mInputLayout = &inputLayoutSubstitute;
+		err = SetAudioChannelLayout(kAudioUnitScope_Input, 0, &GetInputLayout());
+		if (err) return err;
+	}
+		
+	// if layout has not been set, then guess layout from number of channels
+	UInt32 outChannels = GetNumberOfOutputChannels();
+	AudioChannelLayout outputLayoutSubstitute;
+	const AudioChannelLayout* outputLayout = &GetOutputLayout();
+	if (outputLayout == NULL || outputLayout->mChannelLayoutTag == 0) {
+		outputLayout = &outputLayoutSubstitute;
+		outputLayoutSubstitute.mNumberChannelDescriptions = 0;
+		outputLayoutSubstitute.mChannelBitmap = 0;
+		outputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(outChannels);
+
+		mOutputLayout = &outputLayoutSubstitute;
+		err = SetAudioChannelLayout(kAudioUnitScope_Output, 0, &GetOutputLayout());
+		if (err) return err;
+	}
+	
+	return err;
+}
+
+
+	
+OSStatus			AUPannerBase::UpdateBypassMatrix()
+{
+	OSStatus err = SetDefaultChannelLayoutsIfNone();
+	if (err) return err;
+	
+	UInt32 inChannels = GetNumberOfInputChannels();
+	UInt32 outChannels = GetNumberOfOutputChannels();	
+	
+	const AudioChannelLayout* inoutACL[2];
+	
+	inoutACL[0] = &GetInputLayout();
+	inoutACL[1] = &GetOutputLayout();
+
+	mBypassMatrix.alloc(inChannels * outChannels, true);
+	
+	UInt32 propSize = inChannels * outChannels * sizeof(Float32);
+	
+	err = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap, sizeof(inoutACL), inoutACL, &propSize, mBypassMatrix());
+	if (err) {
+		// if there is an error, use a diagonal matrix.
+		Float32* bypass = mBypassMatrix();
+		for (UInt32 chan = 0; chan < std::min(inChannels, outChannels); ++chan)
+		{
+			float *amp = bypass + (chan * outChannels + chan);
+			*amp = 1.;
+		}
+	}
+
+    return noErr;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Cleanup */
+void				AUPannerBase::Cleanup()
+{
+    
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method Reset */
+OSStatus			AUPannerBase::Reset(		AudioUnitScope 				inScope,
+										AudioUnitElement 			inElement)
+{
+    return AUBase::Reset(inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetParameterInfo */
+OSStatus			AUPannerBase::GetParameterInfo(	AudioUnitScope			inScope,
+												AudioUnitParameterID	inParameterID,
+												AudioUnitParameterInfo	&outParameterInfo )
+{
+	OSStatus result = noErr;
+
+	outParameterInfo.flags = 	kAudioUnitParameterFlag_IsWritable
+						+		kAudioUnitParameterFlag_IsReadable;
+		
+	if (inScope == kAudioUnitScope_Global) {
+		
+		switch(inParameterID)
+		{
+			case kPannerParam_Azimuth:
+				AUBase::FillInParameterName (outParameterInfo, kPanner_Azimuth_Name, false);
+				outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+				outParameterInfo.minValue = -180.;
+				outParameterInfo.maxValue = 180;
+				outParameterInfo.defaultValue = kPannerParamDefault_Azimuth;
+			break;
+
+			case kPannerParam_Elevation:
+				AUBase::FillInParameterName (outParameterInfo, kPanner_Elevation_Name, false);
+				outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+				outParameterInfo.minValue = -90.;
+				outParameterInfo.maxValue = 90;
+				outParameterInfo.defaultValue = kPannerParamDefault_Elevation;
+			break;
+
+			case kPannerParam_Distance:
+				AUBase::FillInParameterName (outParameterInfo, kPanner_Distance_Name, false);
+				outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+				outParameterInfo.minValue = 0.0;
+				outParameterInfo.maxValue = 1.;
+				outParameterInfo.defaultValue = kPannerParamDefault_Distance;
+				outParameterInfo.flags += kAudioUnitParameterFlag_IsHighResolution;
+				//outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+			break;
+ 
+ 			case kPannerParam_CoordScale:
+				AUBase::FillInParameterName (outParameterInfo, kPanner_CoordScale_Name, false);
+				outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+				outParameterInfo.minValue = 0.01;
+				outParameterInfo.maxValue = 1000.;
+				outParameterInfo.defaultValue = kPannerParamDefault_CoordScale;
+				outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+			break;
+
+ 			case kPannerParam_RefDistance:
+				AUBase::FillInParameterName (outParameterInfo, kPanner_RefDistance_Name, false);
+				outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+				outParameterInfo.minValue = 0.01;
+				outParameterInfo.maxValue = 1000.;
+				outParameterInfo.defaultValue = kPannerParamDefault_RefDistance;
+				outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+			break;
+
+			case kPannerParam_Gain:
+				AUBase::FillInParameterName (outParameterInfo, kPanner_Gain_Name, false);
+				outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+				outParameterInfo.minValue = 0.;
+				outParameterInfo.maxValue = 1.;
+				outParameterInfo.defaultValue = kPannerParamDefault_Gain;
+			break;
+
+			default:
+				result = kAudioUnitErr_InvalidParameter;
+				break;
+		}
+	} else {
+		result = kAudioUnitErr_InvalidParameter;
+	}
+	
+	return result;
+}												
+
+//_____________________________________________________________________________
+//
+OSStatus 	AUPannerBase::GetParameter(		AudioUnitParameterID			inParamID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement,
+													Float32 &						outValue)
+{
+	if (inScope != kAudioUnitScope_Global) 
+		return kAudioUnitErr_InvalidScope;
+		
+	outValue = Globals()->GetParameter(inParamID);
+
+	return noErr;
+}
+
+											
+//_____________________________________________________________________________
+//
+OSStatus 	AUPannerBase::SetParameter(		AudioUnitParameterID			inParamID,
+													AudioUnitScope 					inScope,
+													AudioUnitElement 				inElement,
+													Float32							inValue,
+													UInt32							inBufferOffsetInFrames)
+{
+	if (inScope != kAudioUnitScope_Global) 
+		return kAudioUnitErr_InvalidScope;
+
+	Globals()->SetParameter(inParamID, inValue);
+	
+	return noErr;
+}
+
+
+
+//_____________________________________________________________________________
+//
+/*! @method GetPropertyInfo */
+OSStatus			AUPannerBase::GetPropertyInfo (AudioUnitPropertyID	inID,
+										AudioUnitScope				inScope,
+										AudioUnitElement			inElement,
+										UInt32 &					outDataSize,
+										Boolean &					outWritable)
+{
+	OSStatus err = noErr;
+	switch (inID) {
+		case kAudioUnitProperty_BypassEffect:
+			if (inScope != kAudioUnitScope_Global)
+				return kAudioUnitErr_InvalidScope;
+				
+			outWritable = true;
+			outDataSize = sizeof (UInt32);
+			break;
+		default:
+			err = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+	}
+	return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetProperty */
+OSStatus			AUPannerBase::GetProperty (AudioUnitPropertyID 		inID,
+										AudioUnitScope 				inScope,
+										AudioUnitElement	 		inElement,
+										void *						outData)
+{
+	OSStatus err = noErr;
+	switch (inID) 
+	{
+		case kAudioUnitProperty_BypassEffect:
+			if (inScope != kAudioUnitScope_Global)
+				return kAudioUnitErr_InvalidScope;
+
+			*((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+			break;
+		default:
+			err = AUBase::GetProperty(inID, inScope, inElement, outData);
+	}
+	return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method SetProperty */
+OSStatus			AUPannerBase::SetProperty(AudioUnitPropertyID 		inID,
+										AudioUnitScope 				inScope,
+										AudioUnitElement 			inElement,
+										const void *				inData,
+										UInt32 						inDataSize)
+{
+	switch (inID) 
+	{
+		case kAudioUnitProperty_BypassEffect:
+				if (inDataSize < sizeof(UInt32))
+					return kAudioUnitErr_InvalidPropertyValue;
+				bool tempNewSetting = *((UInt32*)inData) != 0;
+					// we're changing the state of bypass
+				if (tempNewSetting != IsBypassEffect()) 
+				{
+					if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+						Reset(0, 0);
+					SetBypassEffect (tempNewSetting);
+				}
+				return noErr;
+	}
+    return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method StreamFormatWritable */
+bool				AUPannerBase::StreamFormatWritable (AudioUnitScope	scope,
+										AudioUnitElement			element)
+{
+    return true;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method ChangeStreamFormat */
+OSStatus			AUPannerBase::ChangeStreamFormat (
+									AudioUnitScope						inScope,
+									AudioUnitElement					inElement,
+									const CAStreamBasicDescription & 	inPrevFormat,
+									const CAStreamBasicDescription &	inNewFormat)
+{
+	if (inScope == kAudioUnitScope_Input && !InputChannelConfigIsSupported(inNewFormat.NumberChannels())) 
+		return kAudioUnitErr_FormatNotSupported;
+		
+	if (inScope == kAudioUnitScope_Output && !OutputChannelConfigIsSupported(inNewFormat.NumberChannels())) 
+		return kAudioUnitErr_FormatNotSupported;
+		
+	if (inNewFormat.NumberChannels() != inPrevFormat.NumberChannels())
+		RemoveAudioChannelLayout(inScope, inElement);
+		
+	return AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus 	AUPannerBase::Render(AudioUnitRenderActionFlags &		ioActionFlags,
+									const AudioTimeStamp &			inTimeStamp,
+									UInt32							inNumberFrames)
+{
+	if (IsBypassEffect()) 
+		return BypassRender(ioActionFlags, inTimeStamp, inNumberFrames);
+	else 
+		return PannerRender(ioActionFlags, inTimeStamp, inNumberFrames);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus 	AUPannerBase::BypassRender(AudioUnitRenderActionFlags &		ioActionFlags,
+									const AudioTimeStamp &			inTimeStamp,
+									UInt32							inNumberFrames)
+{
+	AudioUnitRenderActionFlags xflags = 0;
+	OSStatus result = PullInput(0, xflags, inTimeStamp, inNumberFrames);
+	if (result) return false;
+	bool isSilent = xflags & kAudioUnitRenderAction_OutputIsSilence;
+
+	AudioBufferList& outputBufferList = GetOutput(0)->GetBufferList();
+	AUBufferList::ZeroBuffer(outputBufferList);
+	
+	if (!isSilent) 
+	{
+		UInt32 inChannels = GetNumberOfInputChannels();
+		UInt32 outChannels = GetNumberOfOutputChannels();
+		Float32* bypass = mBypassMatrix();
+		for (UInt32 outChan = 0; outChan < outChannels; ++outChan)
+		{
+			float* outData = GetOutput(0)->GetChannelData(outChan);	
+			
+			for (UInt32 inChan = 0; inChan < inChannels; ++inChan)
+			{
+				float* inData = GetInput(0)->GetChannelData(inChan);
+				float *amp = bypass + (inChan * outChannels + outChan);
+				vDSP_vsma(inData, 1, amp, outData, 1, outData, 1, inNumberFrames);
+			}
+		}
+	}
+    return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32		AUPannerBase::GetAudioChannelLayout(	AudioUnitScope				inScope,
+													AudioUnitElement 			inElement,
+													AudioChannelLayout *		outLayoutPtr,
+													Boolean &					outWritable)
+{	
+	SetDefaultChannelLayoutsIfNone();
+	
+	outWritable = true;
+	
+	CAAudioChannelLayout* caacl = NULL;
+	switch (inScope) 
+	{
+		case kAudioUnitScope_Input:
+			caacl = &mInputLayout;
+			break;
+		case kAudioUnitScope_Output:
+			caacl = &mOutputLayout;
+			break;
+		default:
+			COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+	}
+	
+	if (inElement != 0)
+		COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+		
+	UInt32 size = caacl->IsValid() ? caacl->Size() : 0;
+	if (size > 0 && outLayoutPtr)
+		memcpy(outLayoutPtr, &caacl->Layout(), size);
+		
+	return size;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus	AUPannerBase::RemoveAudioChannelLayout(		AudioUnitScope				inScope,
+														AudioUnitElement			inElement)
+{
+	CAAudioChannelLayout* caacl = NULL;
+	switch (inScope) 
+	{
+		case kAudioUnitScope_Input:
+			caacl = &mInputLayout;
+			break;
+		case kAudioUnitScope_Output:
+			caacl = &mOutputLayout;
+			break;
+		default:
+			return kAudioUnitErr_InvalidScope;
+	}
+	
+	if (inElement != 0)
+		return kAudioUnitErr_InvalidElement;
+	
+	*caacl = NULL;
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus 	AUPannerBase::SetAudioChannelLayout(		AudioUnitScope 				inScope, 
+														AudioUnitElement 			inElement,
+														const AudioChannelLayout *	inLayout)
+{
+	if (!inLayout)
+		return RemoveAudioChannelLayout(inScope, inElement);
+
+	if (!ChannelLayoutTagIsSupported(inScope, inElement, inLayout->mChannelLayoutTag))
+		return kAudioUnitErr_FormatNotSupported;
+	
+	CAAudioChannelLayout* caacl = NULL;
+	UInt32 currentChannels;
+	switch (inScope) 
+	{
+		case kAudioUnitScope_Input:
+			caacl = &mInputLayout;
+			currentChannels = GetNumberOfInputChannels();
+			break;
+		case kAudioUnitScope_Output:
+			caacl = &mOutputLayout;
+			currentChannels = GetNumberOfOutputChannels();
+			break;
+		default:
+			return kAudioUnitErr_InvalidScope;
+	}
+	
+	if (inElement != 0)
+		return kAudioUnitErr_InvalidElement;
+
+	UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+	if (currentChannels != numChannelsInLayout)
+		return kAudioUnitErr_InvalidPropertyValue;
+	
+	*caacl = inLayout;
+	if (IsInitialized())
+		UpdateBypassMatrix();
+		
+	return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetChannelLayoutTags(		AudioUnitScope				inScope,
+												AudioUnitElement 			inElement, 
+												AudioChannelLayoutTag*		outTags)
+{
+	switch (inScope) 
+	{
+		case kAudioUnitScope_Input:
+			if (outTags) {
+				outTags[0] = kAudioChannelLayoutTag_Mono;
+				outTags[1] = kAudioChannelLayoutTag_Stereo;
+				outTags[2] = kAudioChannelLayoutTag_Ambisonic_B_Format;
+			}
+			return 3;
+		case kAudioUnitScope_Output:
+			if (outTags) {
+				outTags[0] = kAudioChannelLayoutTag_Stereo;
+				outTags[1] = kAudioChannelLayoutTag_Quadraphonic;
+				outTags[2] = kAudioChannelLayoutTag_AudioUnit_5_0;
+				outTags[3] = kAudioChannelLayoutTag_AudioUnit_6_0;
+				outTags[4] = kAudioChannelLayoutTag_AudioUnit_7_0;
+				outTags[5] = kAudioChannelLayoutTag_AudioUnit_7_0_Front;
+				outTags[6] = kAudioChannelLayoutTag_AudioUnit_8;
+			}
+			return 7;
+		default: {
+			OSStatus err = kAudioUnitErr_InvalidScope;
+			throw err;
+		}
+	}
+}
+
+
+
+//_____________________________________________________________________________
+//
+bool 	AUPannerBase::ChannelConfigIsSupported()
+{
+	UInt32 inChannels = GetNumberOfInputChannels();
+	UInt32 outChannels = GetNumberOfOutputChannels();
+	const AUChannelInfo* cinfo = NULL;
+	UInt32 numConfigs = SupportedNumChannels(&cinfo);
+	for (UInt32 i = 0; i < numConfigs; ++i)
+	{
+		if (cinfo[i].inChannels == (SInt16)inChannels && cinfo[i].outChannels == (SInt16)outChannels)
+			return true;
+	}
+	return false;
+}
+
+
+//_____________________________________________________________________________
+//
+bool 	AUPannerBase::InputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+	const AUChannelInfo* cinfo = NULL;
+	UInt32 numConfigs = SupportedNumChannels(&cinfo);
+	for (UInt32 i = 0; i < numConfigs; ++i)
+	{
+		if (cinfo[i].inChannels == (SInt16)inNumberChannels)
+			return true;
+	}
+	return false;
+}
+
+//_____________________________________________________________________________
+//
+bool 	AUPannerBase::OutputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+	const AUChannelInfo* cinfo = NULL;
+	UInt32 numConfigs = SupportedNumChannels(&cinfo);
+	for (UInt32 i = 0; i < numConfigs; ++i)
+	{
+		if (cinfo[i].outChannels == (SInt16)inNumberChannels)
+			return true;
+	}
+	return false;
+}
+
+//_____________________________________________________________________________
+//
+bool 	AUPannerBase::ChannelLayoutTagIsSupported(		AudioUnitScope			inScope, 
+														AudioUnitElement		inElement, 
+														AudioChannelLayoutTag	inTag)
+{
+	UInt32 numTags = GetChannelLayoutTags(inScope, inElement, NULL);
+	CAAutoFree<AudioChannelLayoutTag> tags(numTags);
+	GetChannelLayoutTags(inScope, inElement, tags());
+	
+	for (UInt32 i = 0; i < numTags; ++i)
+	{
+		if (tags[i] == inTag)
+			return true;
+	}
+	
+	return false;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
new file mode 100644
index 0000000..3184830
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
@@ -0,0 +1,272 @@
+/*
+     File: AUPannerBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUPannerBase_h__
+#define __AUPannerBase_h__
+
+#include "AUBase.h"
+#include <math.h>
+#include "CAAutoDisposer.h"
+#include "CAAudioChannelLayout.h"
+
+
+/*! @class AUPannerBase */
+class AUPannerBase : public AUBase
+{
+public:
+/*! @ctor AUPannerBase */
+    AUPannerBase(AudioComponentInstance inAudioUnit);
+/*! @dtor ~AUPannerBase */
+    virtual ~AUPannerBase();
+    
+	/*! @method Initialize */
+	virtual OSStatus			Initialize();
+
+	/*! @method Cleanup */
+	virtual void				Cleanup();
+
+
+	/*! @method Reset */
+	virtual OSStatus			Reset(		AudioUnitScope 				inScope,
+											AudioUnitElement 			inElement);
+
+	/*! @method CanScheduleParameters */
+	virtual bool				CanScheduleParameters() const { return false; }
+
+	/*! @method GetParameterInfo */
+	virtual OSStatus			GetParameterInfo(	AudioUnitScope			inScope,
+													AudioUnitParameterID	inParameterID,
+													AudioUnitParameterInfo	&outParameterInfo );
+
+
+	/*! @method GetPropertyInfo */
+	virtual OSStatus			GetPropertyInfo (AudioUnitPropertyID	inID,
+											AudioUnitScope				inScope,
+											AudioUnitElement			inElement,
+											UInt32 &					outDataSize,
+											Boolean &					outWritable);
+
+	/*! @method GetProperty */
+	virtual OSStatus			GetProperty (AudioUnitPropertyID 		inID,
+											AudioUnitScope 				inScope,
+											AudioUnitElement	 		inElement,
+											void *						outData);
+
+	/*! @method SetProperty */
+	virtual OSStatus			SetProperty(AudioUnitPropertyID 		inID,
+											AudioUnitScope 				inScope,
+											AudioUnitElement 			inElement,
+											const void *				inData,
+											UInt32 						inDataSize);
+
+
+	/*! @method StreamFormatWritable */
+	virtual bool				StreamFormatWritable (AudioUnitScope	scope,
+											AudioUnitElement			element);
+
+	/*! @method ChangeStreamFormat */
+	virtual	OSStatus			ChangeStreamFormat (
+										AudioUnitScope						inScope,
+										AudioUnitElement					inElement,
+										const CAStreamBasicDescription & 	inPrevFormat,
+										const CAStreamBasicDescription &	inNewFormat);
+
+	
+	/*! @method IsBypassEffect */
+	// This is used for the property value - to reflect to the UI if an effect is bypassed
+	bool						IsBypassEffect () { return mBypassEffect; }
+						
+	/*! @method SetBypassEffect */
+	virtual void				SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+	
+
+	/*! @method Render */
+	virtual OSStatus 	Render(AudioUnitRenderActionFlags &		ioActionFlags,
+										const AudioTimeStamp &			inTimeStamp,
+										UInt32							inNumberFrames);
+
+	/*! @method Render */
+	virtual OSStatus 	PannerRender(AudioUnitRenderActionFlags &		ioActionFlags,
+										const AudioTimeStamp &			inTimeStamp,
+										UInt32							inNumberFrames) = 0;
+
+	/*! @method BypassRender */
+	virtual OSStatus 	BypassRender(AudioUnitRenderActionFlags &		ioActionFlags,
+										const AudioTimeStamp &			inTimeStamp,
+										UInt32							inNumberFrames);
+
+
+	/*! @method GetAudioChannelLayout */
+	virtual UInt32				GetAudioChannelLayout(	AudioUnitScope				inScope,
+														AudioUnitElement 			inElement,
+														AudioChannelLayout *		outLayoutPtr,
+														Boolean &					outWritable);
+
+	/*! @method SetAudioChannelLayout */
+	virtual OSStatus			SetAudioChannelLayout(	AudioUnitScope 				inScope, 
+														AudioUnitElement 			inElement,
+														const AudioChannelLayout *	inLayout);
+
+	/*! @method RemoveAudioChannelLayout */
+	virtual OSStatus			RemoveAudioChannelLayout(	AudioUnitScope			inScope, 
+															AudioUnitElement		inElement);
+
+	/*! @method GetChannelLayoutTags */
+	virtual UInt32				GetChannelLayoutTags(		AudioUnitScope				inScope,
+															AudioUnitElement 			inElement, 
+															AudioChannelLayoutTag*		outTags);
+
+	/*! @method GetNumberOfInputChannels */
+	UInt32						GetNumberOfInputChannels() { return ((AUIOElement*)Inputs().SafeGetElement(0))->NumberChannels(); };
+	/*! @method GetNumberOfOutputChannels */
+	UInt32						GetNumberOfOutputChannels() { return ((AUIOElement*)Outputs().SafeGetElement(0))->NumberChannels(); }
+
+	/*! @method GetParameter */
+	virtual OSStatus 	GetParameter(			AudioUnitParameterID			inParamID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														Float32 &						outValue);
+												
+	/*! @method SetParameter */
+	virtual OSStatus 	SetParameter(			AudioUnitParameterID			inParamID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														Float32							inValue,
+														UInt32							inBufferOffsetInFrames);
+
+	// convenience wrappers for accessing parameters in the global scope
+	/*! @method SetParameter */
+	void						SetParameter(			UInt32							inParamID,
+														Float32							inValue)
+								{
+									OSStatus err = SetParameter(inParamID, kAudioUnitScope_Global, 0, inValue, 0);
+									if (err) throw err;
+								}
+								
+	/*! @method GetParameter */
+	Float32						GetParameter(			UInt32							inParamID )
+								{
+									Float32 outValue = 0.;
+									OSStatus err = GetParameter(inParamID, kAudioUnitScope_Global, 0, outValue);
+									if (err) throw err;
+									return outValue;
+								}
+
+	/*! @method InputChannelConfigIsSupported */
+	bool						InputChannelConfigIsSupported(UInt32 inNumberChannels);
+	/*! @method OutputChannelConfigIsSupported */
+	bool						OutputChannelConfigIsSupported(UInt32 inNumberChannels);
+	/*! @method ChannelConfigIsSupported */
+	bool						ChannelConfigIsSupported();
+
+	/*! @method SupportsTail */
+	virtual	bool				SupportsTail () { return true; }
+	/*! @method GetTailTime */
+    virtual Float64				GetTailTime() { return 0; }
+
+
+	/*! @method GetGain */
+	Float32						GetGain()        { return GetParameter(kPannerParam_Gain); }
+	/*! @method GetTailTime */
+	Float32						GetAzimuth()     { return GetParameter(kPannerParam_Azimuth); }
+	/*! @method GetElevation */
+	Float32						GetElevation()   { return GetParameter(kPannerParam_Elevation); }
+	/*! @method GetDistance */
+	Float32						GetDistance()    { return GetParameter(kPannerParam_Distance); }
+	/*! @method GetCoordScale */
+	Float32						GetCoordScale()  { return GetParameter(kPannerParam_CoordScale); }
+	/*! @method GetRefDistance */
+	Float32						GetRefDistance() { return GetParameter(kPannerParam_RefDistance); }	                        	
+	                        	
+	/*! @method SetGain */
+	void						SetGain(Float32 inValue)        { SetParameter(kPannerParam_Gain, inValue); }
+	/*! @method SetAzimuth */
+	void						SetAzimuth(Float32 inValue)     { SetParameter(kPannerParam_Azimuth, inValue); }
+	/*! @method SetElevation */
+	void						SetElevation(Float32 inValue)   { SetParameter(kPannerParam_Elevation, inValue); }
+	/*! @method SetDistance */
+	void						SetDistance(Float32 inValue)    { SetParameter(kPannerParam_Distance, inValue); }
+	/*! @method SetCoordScale */
+	void						SetCoordScale(Float32 inValue)  { SetParameter(kPannerParam_CoordScale, inValue); }
+	/*! @method SetRefDistance */
+	void						SetRefDistance(Float32 inValue) { SetParameter(kPannerParam_RefDistance, inValue); }
+	
+protected:
+	/*! @method ShouldBypassEffect */
+	// This is used in the render call to see if an effect is bypassed
+	// It can return a different status than IsBypassEffect (though it MUST take that into account)
+	virtual	bool				ShouldBypassEffect () { return IsBypassEffect(); }
+
+	/*! @method AllocBypassMatrix */
+	void						AllocBypassMatrix();
+
+	/*! @method UpdateBypassMatrix */
+	OSStatus					UpdateBypassMatrix();
+
+	/*! @method SetDefaultChannelLayoutsIfNone */
+	OSStatus					SetDefaultChannelLayoutsIfNone();
+	
+	/*! @method ChannelLayoutTagIsSupported */
+	bool						ChannelLayoutTagIsSupported(	AudioUnitScope			inScope, 
+																AudioUnitElement		inElement, 
+																AudioChannelLayoutTag	inTag);
+	
+	const AudioChannelLayout&	GetInputLayout() const { return mInputLayout.Layout(); }
+	const AudioChannelLayout&	GetOutputLayout() const { return mOutputLayout.Layout(); }
+	
+private:
+	
+	/*! @var UpdateBypassMatrix */
+	bool mBypassEffect;
+	/*! @var mBypassMatrix */
+	CAAutoFree<Float32> mBypassMatrix;
+	/*! @var mInputLayout */
+	CAAudioChannelLayout mInputLayout;
+	/*! @var mOutputLayout */
+	CAAudioChannelLayout mOutputLayout;
+};
+
+#endif /* __AUPannerBase_h__ */
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
new file mode 100644
index 0000000..28e4d36
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
@@ -0,0 +1,354 @@
+/*
+     File: MusicDeviceBase.cpp
+ Abstract: MusicDeviceBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "MusicDeviceBase.h"
+
+// compatibility with older OS SDK releases
+typedef OSStatus
+(*TEMP_MusicDeviceMIDIEventProc)(	void *			inComponentStorage,
+							UInt32					inStatus,
+							UInt32					inData1,
+							UInt32					inData2,
+							UInt32					inOffsetSampleFrame);
+
+typedef OSStatus
+(*TEMP_MusicDeviceStartNoteProc)(	void *				inComponentStorage,
+						MusicDeviceInstrumentID			inInstrument,
+						MusicDeviceGroupID				inGroupID,
+						NoteInstanceID *				outNoteInstanceID,
+						UInt32							inOffsetSampleFrame,
+						const MusicDeviceNoteParams *	inParams);
+
+typedef OSStatus
+(*TEMP_MusicDeviceStopNoteProc)(void *					inComponentStorage,
+						MusicDeviceGroupID				inGroupID,
+						NoteInstanceID					inNoteInstanceID,
+						UInt32							inOffsetSampleFrame);
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+
+static OSStatus		MusicDeviceBaseMIDIEvent(void *			inComponentStorage,
+						UInt32				inStatus,
+						UInt32				inData1,
+						UInt32				inData2,
+						UInt32				inOffsetSampleFrame);
+
+static OSStatus		MusicDeviceBaseStartNote(	void *		inComponentStorage,
+						MusicDeviceInstrumentID			inInstrument,
+						MusicDeviceGroupID				inGroupID,
+						NoteInstanceID *				outNoteInstanceID,
+						UInt32							inOffsetSampleFrame,
+						const MusicDeviceNoteParams *	inParams);
+
+static OSStatus		MusicDeviceBaseStopNote(void *			inComponentStorage,
+						MusicDeviceGroupID				inGroupID,
+						NoteInstanceID					inNoteInstanceID,
+						UInt32							inOffsetSampleFrame);
+
+#endif
+
+MusicDeviceBase::MusicDeviceBase(AudioComponentInstance			inInstance, 
+									UInt32						numInputs,
+									UInt32						numOutputs,
+									UInt32						numGroups) 
+	: AUBase(inInstance, numInputs, numOutputs, numGroups),
+	  AUMIDIBase(this)
+{
+}
+
+OSStatus			MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID	inID,
+							AudioUnitScope				inScope,
+							AudioUnitElement			inElement,
+							UInt32 &				outDataSize,
+							Boolean &				outWritable)
+{
+	OSStatus result;
+	
+	switch (inID) 
+	{
+#if !TARGET_OS_IPHONE
+		case kMusicDeviceProperty_InstrumentCount:
+			if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+			outDataSize = sizeof(UInt32);
+			outWritable = false;
+			result = noErr;
+			break;
+#endif
+		default:
+			result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+			
+			if (result == kAudioUnitErr_InvalidProperty)
+				result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+			break;
+	}
+	return result;
+}
+
+OSStatus			MusicDeviceBase::GetProperty(	AudioUnitPropertyID			inID,
+							AudioUnitScope 				inScope,
+							AudioUnitElement		 	inElement,
+							void *					outData)
+{
+	OSStatus result;
+
+	switch (inID) 
+	{
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+		case kAudioUnitProperty_FastDispatch:
+			if (!IsCMgrObject()) return kAudioUnitErr_InvalidProperty;
+			if (inElement == kMusicDeviceMIDIEventSelect) {
+				*(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
+				return noErr;
+			}
+			else if (inElement == kMusicDeviceStartNoteSelect) {
+				*(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
+				return noErr;
+			}	
+			else if (inElement == kMusicDeviceStopNoteSelect) {
+				*(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
+				return noErr;
+			}
+			return kAudioUnitErr_InvalidElement;
+#endif
+
+#if !TARGET_OS_IPHONE
+		case kMusicDeviceProperty_InstrumentCount:
+			if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+			return GetInstrumentCount (*(UInt32*)outData);
+#endif
+		default:
+			result = AUBase::GetProperty (inID, inScope, inElement, outData);
+			
+			if (result == kAudioUnitErr_InvalidProperty)
+				result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
+	}
+	
+	return result;
+}
+
+
+OSStatus			MusicDeviceBase::SetProperty(	AudioUnitPropertyID 			inID,
+							AudioUnitScope 				inScope,
+							AudioUnitElement 			inElement,
+							const void *				inData,
+							UInt32 					inDataSize)
+
+{
+
+	OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+		
+	if (result == kAudioUnitErr_InvalidProperty)
+		result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
+		
+	return result;
+}
+
+// For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
+// then this call should return an instrument count of zero and noErr
+OSStatus			MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
+{
+	outInstCount = 0;
+	return noErr;
+}
+
+OSStatus	MusicDeviceBase::HandleNoteOn(	UInt8 	inChannel,
+											UInt8 	inNoteNumber,
+											UInt8 	inVelocity,
+											UInt32 	inStartFrame)
+{
+	MusicDeviceNoteParams params;
+	params.argCount = 2;
+	params.mPitch = inNoteNumber;
+	params.mVelocity = inVelocity;
+	return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
+}
+											
+OSStatus	MusicDeviceBase::HandleNoteOff(	UInt8 	inChannel,
+											UInt8 	inNoteNumber,
+											UInt8 	inVelocity,
+											UInt32 	inStartFrame)
+{
+	return StopNote (inChannel, inNoteNumber, inStartFrame);
+}
+
+OSStatus			
+MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID		inInstrument, 
+										MusicDeviceGroupID				inGroupID, 
+										NoteInstanceID *				outNoteInstanceID, 
+										UInt32							inOffsetSampleFrame, 
+										const MusicDeviceNoteParams *	inParams)
+{
+	if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
+
+	if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
+	
+	return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+}
+
+#if TARGET_OS_MAC
+	#if __LP64__
+		// comp instance, parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index + 1];
+	#else
+		// parameters in reverse order, then comp instance
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+	#endif
+#elif TARGET_OS_WIN32
+		// (no comp instance), parameters in forward order
+		#define PARAM(_typ, _name, _index, _nparams) \
+			_typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus			MusicDeviceBase::ComponentEntryDispatch(	ComponentParameters *		params,
+																MusicDeviceBase *			This)
+{
+	if (This == NULL) return kAudio_ParamError;
+
+	OSStatus result;
+	
+	switch (params->what) {
+	case kMusicDeviceMIDIEventSelect:
+	case kMusicDeviceSysExSelect:
+		{
+			result = AUMIDIBase::ComponentEntryDispatch (params, This);
+		}
+		break;
+	case kMusicDevicePrepareInstrumentSelect:
+		{
+			PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
+			result = This->PrepareInstrument(inInstrument);
+		}
+		break;
+	case kMusicDeviceReleaseInstrumentSelect:
+		{
+			PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
+			result = This->ReleaseInstrument(inInstrument);
+		}
+		break;
+	case kMusicDeviceStartNoteSelect:
+		{
+			PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
+			PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
+			PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
+			PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
+			PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
+			result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
+		}
+		break;
+	case kMusicDeviceStopNoteSelect:
+		{
+			PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
+			PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
+			PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
+			result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
+		}
+		break;
+
+	default:
+		result = AUBase::ComponentEntryDispatch(params, This);
+		break;
+	}
+	
+	return result;
+}
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+
+// fast dispatch
+static OSStatus		MusicDeviceBaseMIDIEvent(void *					inComponentStorage,
+						UInt32					inStatus,
+						UInt32					inData1,
+						UInt32					inData2,
+						UInt32					inOffsetSampleFrame)
+{
+	OSStatus result = noErr;
+	try {
+		MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+		if (This == NULL) return kAudio_ParamError;
+		result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+OSStatus		MusicDeviceBaseStartNote(	void *		inComponentStorage,
+						MusicDeviceInstrumentID			inInstrument,
+						MusicDeviceGroupID				inGroupID,
+						NoteInstanceID *				outNoteInstanceID,
+						UInt32							inOffsetSampleFrame,
+						const MusicDeviceNoteParams *	inParams)
+{
+	OSStatus result = noErr;
+	try {
+		if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
+		MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+		if (This == NULL) return kAudio_ParamError;
+		result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+OSStatus		MusicDeviceBaseStopNote(void *			inComponentStorage,
+						MusicDeviceGroupID				inGroupID,
+						NoteInstanceID					inNoteInstanceID,
+						UInt32							inOffsetSampleFrame)
+{
+	OSStatus result = noErr;
+	try {
+		MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+		if (This == NULL) return kAudio_ParamError;
+		result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+	}
+	COMPONENT_CATCH
+	return result;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
new file mode 100644
index 0000000..4850b8f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
@@ -0,0 +1,126 @@
+/*
+     File: MusicDeviceBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __MusicDeviceBase_h__
+#define __MusicDeviceBase_h__
+
+#include "AUMIDIBase.h"
+
+// ________________________________________________________________________
+//	MusicDeviceBase
+//
+
+/*! @class MusicDeviceBase */
+class MusicDeviceBase : public AUBase, public AUMIDIBase {
+public:
+	/*! @ctor MusicDeviceBase */
+								MusicDeviceBase(		AudioComponentInstance			inInstance, 
+														UInt32							numInputs,
+														UInt32							numOutputs,
+														UInt32							numGroups = 0);
+
+
+	virtual OSStatus	MIDIEvent(		UInt32 						inStatus, 
+										UInt32 						inData1, 
+										UInt32 						inData2, 
+										UInt32 						inOffsetSampleFrame)
+	{
+		return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
+	}
+
+	/*! @method SysEx */
+	virtual OSStatus	SysEx(			const UInt8 *				inData, 
+										UInt32 						inLength) 
+	{
+		return AUMIDIBase::SysEx (inData, inLength);
+	}
+
+	/*! @method GetPropertyInfo */
+	virtual OSStatus			GetPropertyInfo(AudioUnitPropertyID			inID,
+												AudioUnitScope				inScope,
+												AudioUnitElement			inElement,
+												UInt32 &					outDataSize,
+												Boolean &					outWritable);
+
+	/*! @method GetProperty */
+	virtual OSStatus			GetProperty(	AudioUnitPropertyID 		inID,
+												AudioUnitScope 				inScope,
+												AudioUnitElement		 	inElement,
+												void *						outData);
+												
+	/*! @method SetProperty */
+	virtual OSStatus			SetProperty(			AudioUnitPropertyID 			inID,
+														AudioUnitScope 					inScope,
+														AudioUnitElement 				inElement,
+														const void *					inData,
+														UInt32 							inDataSize);
+
+	/*! @method HandleNoteOn */
+	virtual OSStatus			HandleNoteOn(	UInt8 	inChannel,
+												UInt8 	inNoteNumber,
+												UInt8 	inVelocity,
+												UInt32 	inStartFrame);
+																								
+	/*! @method HandleNoteOff */
+	virtual OSStatus			HandleNoteOff(	UInt8 	inChannel,
+												UInt8 	inNoteNumber,
+												UInt8 	inVelocity,
+												UInt32 	inStartFrame);
+
+	/*! @method GetInstrumentCount */
+	virtual OSStatus			GetInstrumentCount (	UInt32 &outInstCount) const;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+	// component dispatcher
+	/*! @method ComponentEntryDispatch */
+	static OSStatus			ComponentEntryDispatch(	ComponentParameters *			params,
+														MusicDeviceBase *				This);
+#endif
+private:
+	OSStatus				HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams);
+};
+
+#endif // __MusicDeviceBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
new file mode 100644
index 0000000..2316807
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
@@ -0,0 +1,125 @@
+/*
+     File: AUBaseHelper.cpp
+ Abstract: AUBaseHelper.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUBaseHelper.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioUnitProperties.h>
+#else
+	#include <AudioUnitProperties.h>
+#endif
+
+OSStatus	GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath)
+{	
+	static CFStringRef kFRString = CFSTR (kAUPresetExternalFileRefs);
+	
+	const void* frVal = CFDictionaryGetValue(parent, kFRString);
+	if (!frVal) return kAudioUnitErr_InvalidPropertyValue;
+
+	const void* frString = CFDictionaryGetValue ((CFDictionaryRef)frVal, frKey);
+	if (!frString) return kAudioUnitErr_InvalidPropertyValue;
+		
+	if (fPath)
+		*fPath = (CFStringRef)frString;
+	
+	return noErr;
+}
+
+CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict)
+{
+	if (!fileRefDict)
+		fileRefDict = CFDictionaryCreateMutable	(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+	CFDictionarySetValue (fileRefDict, fKey, fPath);
+	
+	return fileRefDict;
+}
+
+#if TARGET_OS_MAC
+// check if the URL can be accessed for reading/writing.  Returns 0 if yes, or the error value.
+int AccessURLAsset(const CFURLRef inURL, int mode)
+{
+    char path[PATH_MAX];
+    if (CFURLGetFileSystemRepresentation(inURL, TRUE, (UInt8 *)path, PATH_MAX) == FALSE)
+		return kAudio_FileNotFoundError;
+	// check whether we have access
+	int ret = access(path, mode);
+//	syslog(LOG_CRIT, "access() error is %d for \"%s\".\n", ret, path);
+	if (ret == 0) return 0;
+	switch (errno) {
+		case EACCES:
+		case EPERM:
+			return -54;	/*permission denied error*/
+		case ENOENT:
+		case ENOTDIR:
+		case ELOOP:
+			return kAudio_FileNotFoundError;
+		default:
+			return errno;
+	}
+}
+#endif
+
+#if DEBUG
+//_____________________________________________________________________________
+//
+void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f)
+{
+		bool isRamp = event.eventType == kParameterEvent_Ramped;
+		fprintf (f, "\tParamID=%ld,Scope=%ld,Element=%ld\n", (long)event.parameter, (long)event.scope, (long)event.element);
+		fprintf (f, "\tEvent Type:%s,", (isRamp ? "ramp" : "immediate"));
+		if (isRamp)
+			fprintf (f, "start=%ld,dur=%ld,startValue=%f,endValue=%f\n",
+					(long)event.eventValues.ramp.startBufferOffset, (long)event.eventValues.ramp.durationInFrames, 
+					event.eventValues.ramp.startValue, event.eventValues.ramp.endValue);
+		else
+			fprintf (f, "start=%ld,value=%f\n", 
+					(long)event.eventValues.immediate.bufferOffset, 
+					event.eventValues.immediate.value);
+		fprintf (f, "- - - - - - - - - - - - - - - -\n");
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h
new file mode 100644
index 0000000..310a8df
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h
@@ -0,0 +1,75 @@
+/*
+     File: AUBaseHelper.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUBaseHelper_h__
+#define __AUBaseHelper_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CoreFoundation.h>
+	#include <AudioUnit/AUComponent.h>
+#else
+	#include <CoreFoundation.h>
+	#include <AUComponent.h>
+#endif
+
+#include "AUBase.h"
+
+// helpers for dealing with the file-references dictionary in an AUPreset
+OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath);
+
+// if fileRefDict is NULL, this call creates one
+// if not NULL, then the key value is added to it
+CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict);
+
+int AccessURLAsset(const CFURLRef inURL, int mode);
+
+#if DEBUG
+	void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f);
+#endif
+
+
+
+#endif // __AUBaseHelper_h__
\ No newline at end of file
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp
new file mode 100644
index 0000000..36bb41f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp
@@ -0,0 +1,219 @@
+/*
+     File: AUBuffer.cpp
+ Abstract: AUBuffer.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUBuffer.h"
+#include <stdlib.h>
+
+AUBufferList::~AUBufferList()
+{
+	Deallocate();
+	if (mPtrs)
+		free(mPtrs);
+}
+
+// a * b + c
+static UInt32 SafeMultiplyAddUInt32(UInt32 a, UInt32 b, UInt32 c)
+{
+	if (a == 0 || b == 0) return c;  // prevent zero divide
+	
+	if (a > (0xFFFFFFFF - c) / b)
+		throw std::bad_alloc();
+	
+	return a * b + c;
+}
+
+void				AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+	UInt32 nStreams;
+	if (format.IsInterleaved()) {
+		nStreams = 1;
+	} else {
+		nStreams = format.mChannelsPerFrame;
+	}
+
+	// careful -- the I/O thread could be running!
+	if (nStreams > mAllocatedStreams) {
+		size_t theHeaderSize = sizeof(AudioBufferList) - sizeof(AudioBuffer);
+		mPtrs = (AudioBufferList *)CA_realloc(mPtrs,
+									SafeMultiplyAddUInt32(nStreams, sizeof(AudioBuffer), theHeaderSize));
+		mAllocatedStreams = nStreams;
+	}
+	UInt32 bytesPerStream = SafeMultiplyAddUInt32(nFrames, format.mBytesPerFrame, 0xF) & ~0xF;
+	UInt32 nBytes = SafeMultiplyAddUInt32(nStreams, bytesPerStream, 0);
+	if (nBytes > mAllocatedBytes) {
+		if (mExternalMemory) {
+			mExternalMemory = false;
+			mMemory = NULL;
+		}
+		mMemory = (Byte *)CA_realloc(mMemory, nBytes);
+		mAllocatedBytes = nBytes;
+	}
+	mAllocatedFrames = nFrames;
+	mPtrState = kPtrsInvalid;
+}
+
+void				AUBufferList::Deallocate()
+{
+	mAllocatedStreams = 0;
+	mAllocatedFrames = 0;
+	mAllocatedBytes = 0;
+// this causes a world of hurt if someone upstream disconnects during I/O (SysSoundGraph)
+/*	if (mPtrs) {
+		printf("deallocating bufferlist %08X\n", int(mPtrs));
+		free(mPtrs);
+		mPtrs = NULL;
+	} */
+	if (mMemory) {
+		if (mExternalMemory)
+			mExternalMemory = false;
+		else
+			free(mMemory);
+		mMemory = NULL;
+	}
+	mPtrState = kPtrsInvalid;
+}
+
+AudioBufferList &	AUBufferList::PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+	if (nFrames > mAllocatedFrames)
+		COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
+
+	UInt32 nStreams;
+	UInt32 channelsPerStream;
+	if (format.IsInterleaved()) {
+		nStreams = 1;
+		channelsPerStream = format.mChannelsPerFrame;
+	} else {
+		nStreams = format.mChannelsPerFrame;
+		channelsPerStream = 1;
+		if (nStreams > mAllocatedStreams)
+			COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
+	}
+	
+	AudioBufferList *abl = mPtrs;
+	abl->mNumberBuffers = nStreams;
+	AudioBuffer *buf = abl->mBuffers;
+	Byte *mem = mMemory;
+	UInt32 streamInterval = (mAllocatedFrames * format.mBytesPerFrame + 0xF) & ~0xF;
+	UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
+	for ( ; nStreams--; ++buf) {
+		buf->mNumberChannels = channelsPerStream;
+		buf->mData = mem;
+		buf->mDataByteSize = bytesPerBuffer;
+		mem += streamInterval;
+	}
+	if (UInt32(mem - mMemory) > mAllocatedBytes)
+		COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
+	mPtrState = kPtrsToMyMemory;
+	return *mPtrs;
+}
+
+AudioBufferList &	AUBufferList::PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+	UInt32 nStreams;
+	UInt32 channelsPerStream;
+	if (format.IsInterleaved()) {
+		nStreams = 1;
+		channelsPerStream = format.mChannelsPerFrame;
+	} else {
+		nStreams = format.mChannelsPerFrame;
+		channelsPerStream = 1;
+		if (nStreams > mAllocatedStreams)
+			COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
+	}
+	AudioBufferList *abl = mPtrs;
+	abl->mNumberBuffers = nStreams;
+	AudioBuffer *buf = abl->mBuffers;
+	UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
+	for ( ; nStreams--; ++buf) {
+		buf->mNumberChannels = channelsPerStream;
+		buf->mData = NULL;
+		buf->mDataByteSize = bytesPerBuffer;
+	}
+	mPtrState = kPtrsToExternalMemory;
+	return *mPtrs;
+}
+
+// this should NOT be called while I/O is in process
+void		AUBufferList::UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf)
+{
+	UInt32 alignedSize = buf.size & ~0xF;
+	if (mMemory != NULL && alignedSize >= mAllocatedBytes) {
+		// don't accept the buffer if we already have one and it's big enough
+		// if we don't already have one, we don't need one
+		Byte *oldMemory = mMemory;
+		mMemory = buf.buffer;
+		mAllocatedBytes = alignedSize;
+		// from Allocate(): nBytes = nStreams * nFrames * format.mBytesPerFrame;	
+		// thus: nFrames = nBytes / (nStreams * format.mBytesPerFrame)
+		mAllocatedFrames = mAllocatedBytes / (format.NumberChannelStreams() * format.mBytesPerFrame);
+		mExternalMemory = true;
+		free(oldMemory);
+	}
+}
+
+#if DEBUG
+void	AUBufferList::PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames, bool asFloats)
+{
+	printf("  %s [%d] 0x%08lX:\n", label, subscript, long(&abl));
+	const AudioBuffer *buf = abl.mBuffers;
+	for (UInt32 i = 0; i < abl.mNumberBuffers; ++buf, ++i) {
+		printf("      [%2d] %5dbytes %dch @ %p: ", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+		if (buf->mData != NULL) {
+			UInt32 nSamples = nFrames * buf->mNumberChannels;
+			for (UInt32 j = 0; j < nSamples; ++j) {
+				if (nSamples > 16 && (j % 16) == 0)
+					printf("\n\t");
+				if (asFloats)
+					printf(" %6.3f", ((float *)buf->mData)[j]);
+				else
+					printf(" %08X", (unsigned)((UInt32 *)buf->mData)[j]);
+			}
+		}
+		printf("\n");
+	}
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h
new file mode 100644
index 0000000..64ea4c3
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h
@@ -0,0 +1,267 @@
+/*
+     File: AUBuffer.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUBuffer_h__
+#define __AUBuffer_h__
+
+#include <TargetConditionals.h>
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioUnit.h>
+#else
+	#include <AudioUnit.h>
+#endif
+
+#include <string.h>
+#include "CAStreamBasicDescription.h"
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+
+// make this usable outside the stricter context of AudiUnits
+#ifndef COMPONENT_THROW
+	#define COMPONENT_THROW(err) \
+		do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
+#endif
+
+
+	/*! @class AUBufferList */
+class AUBufferList {
+	enum EPtrState {
+		kPtrsInvalid,
+		kPtrsToMyMemory,
+		kPtrsToExternalMemory
+	};
+public:
+	/*! @ctor AUBufferList */
+	AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL), 
+		mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { }
+	/*! @dtor ~AUBufferList */
+	~AUBufferList();
+
+	/*! @method PrepareBuffer */
+	AudioBufferList &	PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+	/*! @method PrepareNullBuffer */
+	AudioBufferList &	PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+
+	/*! @method SetBufferList */
+	AudioBufferList &	SetBufferList(const AudioBufferList &abl) {
+							if (mAllocatedStreams < abl.mNumberBuffers)
+								COMPONENT_THROW(-1);
+							mPtrState = kPtrsToExternalMemory;
+							memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+							return *mPtrs;
+						}
+	
+	/*! @method SetBuffer */
+	void				SetBuffer(UInt32 index, const AudioBuffer &ab) {
+							if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers)
+								COMPONENT_THROW(-1);
+							mPtrState = kPtrsToExternalMemory;
+							mPtrs->mBuffers[index] = ab;
+						}
+
+	/*! @method InvalidateBufferList */
+	void				InvalidateBufferList() { mPtrState = kPtrsInvalid; }
+
+	/*! @method GetBufferList */
+	AudioBufferList &	GetBufferList() const {
+							if (mPtrState == kPtrsInvalid)
+								COMPONENT_THROW(-1);
+							return *mPtrs;
+						}
+
+	/*! @method CopyBufferListTo */
+	void				CopyBufferListTo(AudioBufferList &abl) const {
+							if (mPtrState == kPtrsInvalid)
+								COMPONENT_THROW(-1);
+							memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+						}
+	
+	/*! @method CopyBufferContentsTo */
+	void				CopyBufferContentsTo(AudioBufferList &abl) const {
+							if (mPtrState == kPtrsInvalid)
+								COMPONENT_THROW(-1);
+							const AudioBuffer *srcbuf = mPtrs->mBuffers;
+							AudioBuffer *destbuf = abl.mBuffers;
+
+							for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) {
+								if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137]
+									--srcbuf;
+								if (destbuf->mData != srcbuf->mData)
+									memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
+								destbuf->mDataByteSize = srcbuf->mDataByteSize;
+							}
+						}
+	
+	/*! @method Allocate */
+	void				Allocate(const CAStreamBasicDescription &format, UInt32 nFrames);
+	/*! @method Deallocate */
+	void				Deallocate();
+	
+	/*! @method UseExternalBuffer */
+	void				UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf);
+
+	// AudioBufferList utilities
+	/*! @method ZeroBuffer */
+	static void			ZeroBuffer(AudioBufferList &abl) {
+							AudioBuffer *buf = abl.mBuffers;
+							for (UInt32 i = abl.mNumberBuffers ; i--; ++buf)
+								memset(buf->mData, 0, buf->mDataByteSize);
+						}
+#if DEBUG
+	/*! @method PrintBuffer */
+	static void			PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true);
+#endif
+
+	/*! @method GetAllocatedFrames */
+	UInt32				GetAllocatedFrames() const { return mAllocatedFrames; }
+	
+private:
+	/*! @ctor AUBufferList */
+	AUBufferList(AUBufferList &) { }	// prohibit copy constructor
+
+	/*! @var mPtrState */
+	EPtrState					mPtrState;
+	/*! @var mExternalMemory */
+	bool						mExternalMemory;
+	/*! @var mPtrs */
+	AudioBufferList *			mPtrs;
+	/*! @var mMemory */
+	Byte *						mMemory;
+	/*! @var mAllocatedStreams */
+	UInt32						mAllocatedStreams;
+	/*! @var mAllocatedFrames */
+	UInt32						mAllocatedFrames;
+	/*! @var mAllocatedBytes */
+	UInt32						mAllocatedBytes;
+};
+
+
+// Allocates an array of samples (type T), to be optimally aligned for the processor
+	/*! @class TAUBuffer */
+template <class T>
+class TAUBuffer {
+public:
+	enum { 
+		kAlignInterval = 0x10,
+		kAlignMask = kAlignInterval - 1
+	};
+	
+	/*! @ctor TAUBuffer.0 */
+	TAUBuffer() :	mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0)
+	{
+	}
+	
+	/*! @ctor TAUBuffer.1 */
+	TAUBuffer(UInt32 numElems, UInt32 numChannels) :	mMemObject(NULL), mAlignedBuffer(NULL),
+														mBufferSizeBytes(0)
+	{
+		Allocate(numElems, numChannels);
+	}
+	
+	/*! @dtor ~TAUBuffer */
+	~TAUBuffer()
+	{
+		Deallocate();
+	}
+		
+	/*! @method Allocate */
+	void	Allocate(UInt32 numElems)			// can also re-allocate
+	{
+		UInt32 reqSize = numElems * sizeof(T);
+		
+		if (mMemObject != NULL && reqSize == mBufferSizeBytes)
+			return;	// already allocated
+
+		mBufferSizeBytes = reqSize;
+		mMemObject = CA_realloc(mMemObject, reqSize);
+		UInt32 misalign = (uintptr_t)mMemObject & kAlignMask;
+		if (misalign) {
+			mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask);
+			mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign);
+		} else
+			mAlignedBuffer = (T *)mMemObject;
+	}
+
+	/*! @method Deallocate */
+	void	Deallocate()
+	{
+		if (mMemObject == NULL) return;			// so this method has no effect if we're using
+												// an external buffer
+		
+		free(mMemObject);
+		mMemObject = NULL;
+		mAlignedBuffer = NULL;
+		mBufferSizeBytes = 0;
+	}
+	
+	/*! @method AllocateClear */
+	void	AllocateClear(UInt32 numElems)		// can also re-allocate
+	{
+		Allocate(numElems);
+		Clear();
+	}
+	
+	/*! @method Clear */
+	void	Clear()
+	{
+		memset(mAlignedBuffer, 0, mBufferSizeBytes);
+	}
+	
+	// accessors
+	
+	/*! @method operator T *()@ */
+	operator T *()				{ return mAlignedBuffer; }
+
+private:
+	/*! @var mMemObject */
+	void *		mMemObject;			// null when using an external buffer
+	/*! @var mAlignedBuffer */
+	T *			mAlignedBuffer;		// always valid once allocated
+	/*! @var mBufferSizeBytes */
+	UInt32		mBufferSizeBytes;
+};
+
+#endif // __AUBuffer_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
new file mode 100644
index 0000000..f628a91
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
@@ -0,0 +1,155 @@
+/*
+     File: AUInputFormatConverter.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUInputFormatConverter_h__
+#define __AUInputFormatConverter_h__
+
+#include "FormatConverterClient.h"
+#include "AUTimestampGenerator.h"
+
+// ____________________________________________________________________________
+// AUInputFormatConverter
+//
+// Subclass of FormatConverterClient that applies a format conversion
+// to an input of an AudioUnit.
+	/*! @class AUInputFormatConverter */
+class AUInputFormatConverter : public FormatConverterClient {
+public:
+	/*! @ctor AUInputFormatConverter */
+	AUInputFormatConverter(AUBase *hostAU, int inputBus) :
+		mHost(hostAU),
+		mHostBus(inputBus),
+		mPreviousSilentFrames(0x1000)
+	{
+#if DEBUG
+		mTimestampGenerator.mVerbosity = 0;
+		strcpy(mTimestampGenerator.mDebugName, "AUConverter");
+#endif
+	}
+	
+	// need to subsequently call Initialize, with the desired formats
+	
+	/*! @dtor ~AUInputFormatConverter */
+	~AUInputFormatConverter()
+	{
+	}
+	
+	virtual OSStatus Initialize(const AudioStreamBasicDescription &src, const AudioStreamBasicDescription &dest)
+	{
+		OSStatus err = FormatConverterClient::Initialize(src, dest);
+		if (err) return err;
+		mIsPCMToPCM = (src.mFormatID == kAudioFormatLinearPCM) && (dest.mFormatID == kAudioFormatLinearPCM);
+		mHasSRC = (fnonzero(src.mSampleRate) && fnonzero(dest.mSampleRate) && fnotequal(src.mSampleRate, dest.mSampleRate));
+		return ca_noErr;
+	}
+
+	virtual OSStatus	Reset()
+	{
+		mPreviousSilentFrames = 0x1000;
+		mTimestampGenerator.Reset();
+		return FormatConverterClient::Reset();
+	}
+	
+	void	SetStartInputTimeAtZero(bool b)
+	{
+		mTimestampGenerator.SetStartInputAtZero(b);
+	}
+
+	/*! @method FillComplexBuffer */
+	OSStatus	AUFillComplexBuffer(const AudioTimeStamp &				inTimeStamp,
+									UInt32 &							ioOutputDataPacketSize,
+									AudioBufferList &					outOutputData,
+									AudioStreamPacketDescription*		outPacketDescription,
+									bool&								outSilence)
+	{
+		mTimestampGenerator.AddOutputTime(inTimeStamp, ioOutputDataPacketSize, mOutputFormat.mSampleRate);
+		mSilentOutput = true;
+		OSStatus err = FillComplexBuffer(ioOutputDataPacketSize, outOutputData, outPacketDescription);
+		if (mSilentOutput) {
+			if (!mIsPCMToPCM || (mHasSRC && mPreviousSilentFrames < 32))
+				mSilentOutput = false;
+			mPreviousSilentFrames += ioOutputDataPacketSize;
+ 		} else
+			mPreviousSilentFrames = 0;
+		outSilence = mSilentOutput;
+		return err;
+	}
+
+	/*! @method FormatConverterInputProc */
+	virtual OSStatus	FormatConverterInputProc(	
+								UInt32 &						ioNumberDataPackets,
+								AudioBufferList &				ioData,
+								AudioStreamPacketDescription**	outDataPacketDescription)
+	{
+		OSStatus err = ca_noErr;
+		
+		AudioUnitRenderActionFlags actionFlags = 0;
+		AUInputElement *input = mHost->GetInput(mHostBus);
+		*ioNumberDataPackets = std::min(*ioNumberDataPackets, This->mHost->GetMaxFramesPerSlice());
+		const AudioTimeStamp &inputTime = mTimestampGenerator.GenerateInputTime(ioNumberDataPackets, mInputFormat.mSampleRate);
+		err = input->PullInput(actionFlags, inputTime, mHostBus, ioNumberDataPackets);
+		if (!err) {
+			input->CopyBufferListTo(ioData);
+			if (!(actionFlags & kAudioUnitRenderAction_OutputIsSilence))
+				mSilentOutput = false;
+		}
+		return err;
+	}
+
+protected:
+	/*! @var mHost */
+	AUBase *				mHost;
+	/*! @var mHostBus */
+	int						mHostBus;
+	
+	AUTimestampGenerator	mTimestampGenerator;
+	bool					mIsPCMToPCM;
+	bool					mHasSRC;
+	bool					mSilentOutput;
+	UInt32					mPreviousSilentFrames;
+};
+
+#endif // __AUInputFormatConverter_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h
new file mode 100644
index 0000000..e83c0e7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h
@@ -0,0 +1,138 @@
+/*
+     File: AUMIDIDefs.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUMIDIDefs_h__
+#define __AUMIDIDefs_h__
+
+#if !defined(__TMidiMessage)	/* DAS HACK */
+enum
+{
+	kMidiMessage_NoteOff 			= 0x80,
+	kMidiMessage_NoteOn 			= 0x90,
+	kMidiMessage_PolyPressure 		= 0xA0,
+	kMidiMessage_ControlChange 		= 0xB0,
+	kMidiMessage_ProgramChange 		= 0xC0,
+	kMidiMessage_ChannelPressure 	= 0xD0,
+	kMidiMessage_PitchWheel 		= 0xE0,
+	kMidiMessage_SysEx				= 0xF0,
+	kMidiMessage_SysEx_End			= 0xF7,
+	kMidiMessage_MetaEvent			= 0xFF
+};
+#endif
+
+enum
+{
+	kMidiController_BankSelect				= 0,
+	kMidiController_ModWheel				= 1,
+	kMidiController_Breath					= 2,
+	kMidiController_Foot					= 4,
+	kMidiController_PortamentoTime			= 5,
+	kMidiController_DataEntry				= 6,
+	kMidiController_Volume					= 7,
+	kMidiController_Balance					= 8,
+	kMidiController_Pan						= 10,
+	kMidiController_Expression				= 11,
+	
+	// these controls have a (0-63) == off, (64-127) == on
+	kMidiController_Sustain					= 64, //hold1
+	kMidiController_Portamento				= 65,
+	kMidiController_Sostenuto				= 66,
+	kMidiController_Soft					= 67,
+	kMidiController_LegatoPedal				= 68,
+	kMidiController_Hold2Pedal				= 69,
+	kMidiController_FilterResonance			= 71,
+	kMidiController_ReleaseTime				= 72,
+	kMidiController_AttackTime				= 73,
+	kMidiController_Brightness				= 74,
+	kMidiController_DecayTime				= 75,
+	kMidiController_VibratoRate				= 76,
+	kMidiController_VibratoDepth			= 77,
+	kMidiController_VibratoDelay			= 78,
+	
+	// these controls have a 0-127 range and in MIDI they have no LSB (so fractional values are lost in MIDI)
+	kMidiController_ReverbLevel				= 91,
+	kMidiController_ChorusLevel				= 93,
+
+	kMidiController_RPN_LSB					= 100,
+	kMidiController_RPN_MSB					= 101,
+
+	kMidiController_AllSoundOff				= 120,
+	kMidiController_ResetAllControllers		= 121,
+	kMidiController_AllNotesOff				= 123,
+	kMidiController_OmniModeOff				= 124,
+	kMidiController_OmniModeOn				= 125,
+    kMidiController_MonoModeOn              = 126,
+    kMidiController_MonoModeOff             = 127
+};
+
+// RPN values
+enum 
+{
+	kMidiControllerValue_RPNPitchBendSensitivity	= 0,
+	kMidiControllerValue_RPNChannelFineTuning		= 1,
+	kMidiControllerValue_RPNChannelCoarseTuning		= 2,
+	kMidiControllerValue_RPNModDepthRange			= 5,
+	kMidiControllerValue_RPNNull					= 0x3fff	//! 0x7f/0x7f
+};
+
+// GM2 Sound Bank Constants
+enum 
+{
+	kGM2MelodicBank						= 0x7900,
+	kGM2PercussionBank					= 0x7800,
+	kGSPercussionBank					= 0x7f00,
+	kXGSFXBank							= 0x7E00,
+	kXGPercussionBank					= kGSPercussionBank,
+	kBankMSBMask						= 0xff00
+};
+
+enum 
+{
+	kMSBController_MidPoint			= 0x40
+};
+
+#endif	// __AUMIDIDefs_h__
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
new file mode 100644
index 0000000..9fbd3e1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
@@ -0,0 +1,93 @@
+/*
+     File: AUSilentTimeout.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUSilentTimeout
+#define __AUSilentTimeout
+
+class AUSilentTimeout
+{
+public:
+	AUSilentTimeout()
+		: 	mTimeoutCounter(0),
+			mResetTimer(true)
+				{};
+
+	void				Process(UInt32 inFramesToProcess, UInt32 inTimeoutLimit, bool &ioSilence )
+	{
+		if(ioSilence )
+		{
+			if(mResetTimer )
+			{
+				mTimeoutCounter = inTimeoutLimit;
+				mResetTimer = false;
+			}
+			
+			if(mTimeoutCounter > 0 )
+			{
+				mTimeoutCounter -= inFramesToProcess;
+				ioSilence = false;
+			}
+		}
+		else
+		{
+			// signal to reset the next time we receive silence
+			mResetTimer = true;	
+		}
+	}
+
+	void				Reset()
+	{
+		mResetTimer = true;
+	};
+
+
+
+private:
+	SInt32				mTimeoutCounter;
+	bool				mResetTimer;
+};
+
+#endif // __AUSilentTimeout
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
new file mode 100644
index 0000000..7c57a81
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
@@ -0,0 +1,203 @@
+/*
+     File: AUTimestampGenerator.cpp
+ Abstract: AUTimestampGenerator.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUTimestampGenerator.h"
+#include "CAMath.h"
+
+#if DEBUG
+static double DebugHostTime(const AudioTimeStamp &ts)
+{
+	static UInt64 baseHostTime = 0;
+	if (!(ts.mFlags & kAudioTimeStampHostTimeValid))
+		return -1.;
+	if (baseHostTime == 0)
+		baseHostTime = ts.mHostTime;
+	return double(SInt64(ts.mHostTime) - SInt64(baseHostTime)) * CAHostTimeBase::GetInverseFrequency();
+}
+#endif
+
+void	AUTimestampGenerator::AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj)
+{
+	mState.mRateScalarAdj = rateScalarAdj;
+	mState.mLastOutputTime = mState.mCurrentOutputTime;
+	mState.mInputSampleTimeForOutputPull = mState.mNextInputSampleTime;
+	mState.mCurrentOutputTime = inTimeStamp;
+
+	if (mState.mBypassed)
+		return;
+		
+	if (mState.mHostTimeDiscontinuityCorrection && !(mState.mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) && (mState.mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
+		// no host time here but we had one last time, interpolate one
+		double rateScalar = (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) ? mState.mCurrentOutputTime.mRateScalar : 1.0;
+		Float64 deltaSamples = mState.mCurrentOutputTime.mSampleTime - mState.mLastOutputTime.mSampleTime;
+		mState.mCurrentOutputTime.mHostTime = mState.mLastOutputTime.mHostTime + 
+			UInt64(CAHostTimeBase::GetFrequency() * deltaSamples * rateScalar / outputSampleRate);
+		mState.mCurrentOutputTime.mFlags |= kAudioTimeStampHostTimeValid;
+#if DEBUG
+		if (mVerbosity > 1)
+			printf("synthesized host time: %.3f (%.3f + %.f smp @ %.f Hz, rs %.3f\n", DebugHostTime(mState.mCurrentOutputTime), DebugHostTime(mState.mLastOutputTime), deltaSamples, outputSampleRate, rateScalar);
+#endif
+	}
+	// copy rate scalar
+	if (rateScalarAdj != 1.0) {
+		if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid)
+			mState.mCurrentOutputTime.mRateScalar *= rateScalarAdj;
+		else {
+			mState.mCurrentOutputTime.mRateScalar = rateScalarAdj;
+			mState.mCurrentOutputTime.mFlags |= kAudioTimeStampRateScalarValid;
+		}
+	}
+	
+	if (mFirstTime) {
+		mFirstTime = false;
+		mState.mDiscontinuous = false;
+		mState.mDiscontinuityDeltaSamples = 0.;
+		if (!mState.mStartInputAtZero) {
+			mState.mNextInputSampleTime = mState.mCurrentOutputTime.mSampleTime;
+			mState.mInputSampleTimeForOutputPull = mState.mNextInputSampleTime;
+		}
+	} else {
+		mState.mDiscontinuous = fnotequal(mState.mCurrentOutputTime.mSampleTime, mState.mNextOutputSampleTime);
+		mState.mDiscontinuityDeltaSamples = mState.mCurrentOutputTime.mSampleTime - mState.mNextOutputSampleTime;
+		// time should never go backwards...
+		if (mState.mDiscontinuityDeltaSamples < 0.)
+			mState.mDiscontinuityDeltaSamples = 0.;
+#if DEBUG
+		if (mVerbosity > 1)
+			if (mState.mDiscontinuous)
+				printf("%-20.20s: *** DISCONTINUOUS, got " TSGFMT ", expected " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentOutputTime.mSampleTime, (SInt64)mState.mNextOutputSampleTime);
+#endif
+	}
+	mState.mNextOutputSampleTime = mState.mCurrentOutputTime.mSampleTime + expectedDeltaFrames;
+}
+
+const AudioTimeStamp &	AUTimestampGenerator::GenerateInputTime(Float64 framesToAdvance, double inputSampleRate, bool advanceHostTime)
+{
+	if (mState.mBypassed)
+		return mState.mCurrentOutputTime;
+
+	double inputSampleTime;
+	
+	mState.mCurrentInputTime.mFlags = kAudioTimeStampSampleTimeValid;
+	double rateScalar = 1.0;
+	
+	// propagate rate scalar
+	if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) {
+		mState.mCurrentInputTime.mFlags |= kAudioTimeStampRateScalarValid;
+		mState.mCurrentInputTime.mRateScalar = rateScalar = mState.mCurrentOutputTime.mRateScalar;
+	}
+	
+	// propagate host time and sample time
+	if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) {
+		mState.mCurrentInputTime.mFlags |= kAudioTimeStampHostTimeValid;
+		if (advanceHostTime) {
+			Float64 deltaSamples = mState.mNextInputSampleTime - mState.mInputSampleTimeForOutputPull;
+			Float64 deltaSeconds = (deltaSamples / inputSampleRate) * mState.mRateScalarAdj;
+			UInt64 deltaHostTime = (UInt64)(deltaSeconds * CAHostTimeBase::GetFrequency());
+			mState.mCurrentInputTime.mHostTime = mState.mCurrentOutputTime.mHostTime + deltaHostTime;
+		} else {
+			mState.mCurrentInputTime.mHostTime = mState.mCurrentOutputTime.mHostTime;
+		}
+		if (mState.mHostTimeDiscontinuityCorrection && mState.mDiscontinuous && (mState.mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
+			// we had a discontinuous output time, need to resync by interpolating 
+			// a sample time that is appropriate to the host time
+			UInt64 deltaHostTime = mState.mCurrentOutputTime.mHostTime - mState.mLastOutputTime.mHostTime;
+			double deltaSeconds = double(deltaHostTime) * CAHostTimeBase::GetInverseFrequency();
+			// samples/second * seconds = samples
+			double deltaSamples = floor(inputSampleRate / rateScalar * deltaSeconds + 0.5);
+			double lastInputSampleTime = mState.mCurrentInputTime.mSampleTime;
+			inputSampleTime = lastInputSampleTime + deltaSamples;
+#if DEBUG
+			if (mVerbosity > 1)
+				printf("%-20.20s: adjusted input time: " TSGFMT " -> " TSGFMT " (SR=%.3f, rs=%.3f)\n", mDebugName, (SInt64)lastInputSampleTime, (SInt64)inputSampleTime, inputSampleRate, rateScalar);
+#endif
+			mState.mDiscontinuous = false;
+		} else {
+			inputSampleTime = mState.mNextInputSampleTime;
+		}
+	} else {
+		// we don't know the host time, so we can't do much
+		inputSampleTime = mState.mNextInputSampleTime;
+	}
+
+	if (!mState.mHostTimeDiscontinuityCorrection && fnonzero(mState.mDiscontinuityDeltaSamples))
+	{
+		// we had a discontinuous output time, need to resync by propagating the
+		// detected discontinuity, taking the rate scalar adjustment into account
+		inputSampleTime += floor(mState.mDiscontinuityDeltaSamples / mState.mRateScalarAdj + 0.5);
+		
+#if DEBUG
+		if (mVerbosity > 1)
+			printf("%-20.20s: adjusted input time: %.0f -> %.0f (SR=%.3f, rs=%.3f, delta=%.0f)\n", mDebugName, mState.mNextInputSampleTime, inputSampleTime, inputSampleRate, mState.mRateScalarAdj, mState.mDiscontinuityDeltaSamples);
+#endif
+		
+		mState.mDiscontinuityDeltaSamples = 0.;
+	}
+	
+	
+	// propagate word clock
+	if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampWordClockTimeValid) {
+		mState.mCurrentInputTime.mFlags |= kAudioTimeStampWordClockTimeValid;
+		mState.mCurrentInputTime.mWordClockTime = mState.mCurrentOutputTime.mWordClockTime;
+	}
+	
+	// propagate SMPTE time
+	if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampSMPTETimeValid) {
+		mState.mCurrentInputTime.mFlags |= kAudioTimeStampSMPTETimeValid;
+		mState.mCurrentInputTime.mSMPTETime = mState.mCurrentOutputTime.mSMPTETime;
+	}
+	
+	// store the input sample time and expected next input time
+	mState.mCurrentInputTime.mSampleTime = inputSampleTime;
+	mState.mNextInputSampleTime = inputSampleTime + framesToAdvance;
+
+#if DEBUG
+	if (mVerbosity > 0) {
+		printf("%-20.20s: out = " TSGFMT " (%10.3fs)  in = " TSGFMT "  (%10.3fs)  delta = " TSGFMT "  advance = " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentOutputTime.mSampleTime, DebugHostTime(mState.mCurrentOutputTime), (SInt64)inputSampleTime, DebugHostTime(mState.mCurrentInputTime), (SInt64)(mState.mCurrentOutputTime.mSampleTime - inputSampleTime), (SInt64)framesToAdvance);
+	}
+#endif
+	return mState.mCurrentInputTime;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
new file mode 100644
index 0000000..cfd8456
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
@@ -0,0 +1,163 @@
+/*
+     File: AUTimestampGenerator.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUTimestampGenerator_h__
+#define __AUTimestampGenerator_h__
+
+#include <math.h>
+#include "CAHostTimeBase.h"
+#include <stdio.h>
+
+#define TSGFMT "0x%10qx"
+//#define TSGFMT "%10qd"
+
+// This class generates a continuously increasing series of timestamps based
+// on a series of potentially discontinuous timestamps (as can be delivered from
+// CoreAudio in the event of an overload or major engine change).
+// N.B.: "output" = downstream (source) timestamp
+//		 "input"  = upstream (derived) timestamp
+class AUTimestampGenerator {
+public:
+	AUTimestampGenerator(bool hostTimeDiscontinuityCorrection = false)
+	{
+		mState.mStartInputAtZero = true;
+		mState.mBypassed = false;
+		mState.mHostTimeDiscontinuityCorrection = hostTimeDiscontinuityCorrection;
+#if DEBUG
+		mVerbosity = 0;
+		snprintf(mDebugName, sizeof(mDebugName), "tsg @ %p", this);
+#endif
+		// CAHostTimeBase should be used instead of the calls in <CoreAudio/HostTime.h>
+		// we make this call here to ensure that this is initialized, otherwise the first time
+		// you do actually call CAHostTimeBase to do work, can be on the render thread, and lead to unwanted VM faults
+		CAHostTimeBase::GetFrequency();
+		Reset();
+	}
+	
+	void	SetStartInputAtZero(bool b) { mState.mStartInputAtZero = b; }
+	bool	GetStartInputAtZero() const { return mState.mStartInputAtZero; }
+	
+	// bypassing is intended for a narrow special case. the upstream sample time will always be the same as the downstream time.
+	void	SetBypassed(bool b) { mState.mBypassed = b; }
+	bool	GetBypassed() const { return mState.mBypassed; }
+		
+	// Call this to reset the timeline.
+	void	Reset()
+	{
+		mState.mCurrentInputTime.mSampleTime = 0.;
+		mState.mNextInputSampleTime = 0.;
+		mState.mCurrentOutputTime.mSampleTime = 0.;
+		mState.mNextOutputSampleTime = 0.;
+		mState.mLastOutputTime.mFlags = 0;
+		mState.mRateScalarAdj = 1.;
+		
+		mFirstTime = true;
+#if DEBUG
+		if (mVerbosity)
+			printf("%-20.20s: Reset\n", mDebugName);
+#endif
+	}
+	
+	// Call this once per render cycle with the downstream timestamp.
+	// expectedDeltaFrames is the expected difference between the current and NEXT 
+	//	downstream timestamps.
+	// sampleRate is the OUTPUT sample rate.
+	void	AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj=1.0);
+	
+	// Call this once per render cycle to obtain the upstream timestamp.
+	// framesToAdvance is the number of frames the input timeline is to be
+	//	advanced during this render cycle.
+	// sampleRate is the INPUT sample rate.
+	const AudioTimeStamp &	GenerateInputTime(Float64 framesToAdvance, double inputSampleRate, bool advanceHostTime = false);
+		
+	// this can be called to override the setting of the next input sample time in GenerateInputTime
+	void					Advance(Float64 framesToAdvance)
+	{
+#if DEBUG
+		if (mVerbosity > 1)
+			printf("%-20.20s:	ADVANCE         in = " TSGFMT "                    advance = " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentInputTime.mSampleTime, (SInt64)framesToAdvance);
+#endif
+		mState.mNextInputSampleTime = mState.mCurrentInputTime.mSampleTime + framesToAdvance;
+	}
+
+	struct State {
+		AudioTimeStamp		mCurrentInputTime;
+		Float64				mNextInputSampleTime;
+		Float64				mNextOutputSampleTime;
+		Float64				mInputSampleTimeForOutputPull;
+		
+		AudioTimeStamp		mLastOutputTime;
+		AudioTimeStamp		mCurrentOutputTime;
+
+		bool				mStartInputAtZero;  // if true, input timeline starts at 0, else it starts
+												// synced with the output timeline
+		bool				mDiscontinuous;
+		bool				mBypassed;
+		Float64				mDiscontinuityDeltaSamples;
+		
+		double				mRateScalarAdj;
+		
+		bool				mHostTimeDiscontinuityCorrection; // If true, propagate timestamp discontinuities using host time.
+	};
+	
+	void GetState(State& outState) const { outState = mState; }
+	void SetState(State const& inState) { mState = inState; mFirstTime = false; }
+	
+private:
+	
+	struct State		mState;
+
+	bool				mFirstTime;	
+	
+#if DEBUG
+public:
+	int					mVerbosity;
+	char				mDebugName[64];
+#endif
+};
+
+
+#endif // __AUTimestampGenerator_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp
new file mode 100644
index 0000000..c2c8468
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp
@@ -0,0 +1,169 @@
+/*
+     File: AUOutputBL.cpp
+ Abstract: AUOutputBL.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUOutputBL.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AUComponent.h>
+#else
+	#include <AUComponent.h>
+#endif
+/*
+struct AudioBufferList
+{
+	UInt32		mNumberBuffers;
+	AudioBuffer	mBuffers[1];
+};
+struct AudioBuffer
+{
+	UInt32	mNumberChannels;	//	number of interleaved channels in the buffer
+	UInt32	mDataByteSize;		//	the size of the buffer pointed to by mData
+	void*	mData;				//	the pointer to the buffer
+};
+*/
+
+AUOutputBL::AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames) 
+		: mFormat (inDesc),
+		  mBufferMemory(NULL),
+		  mBufferList (NULL),
+		  mNumberBuffers (0), // keep this here, so can ensure integrity of ABL
+		  mBufferSize (0),
+		  mFrames(inDefaultNumFrames)
+{
+	mNumberBuffers = mFormat.IsInterleaved() ? 1 : mFormat.NumberChannels();
+	mBufferList = reinterpret_cast<AudioBufferList*>(new Byte[offsetof(AudioBufferList, mBuffers) + (mNumberBuffers * sizeof(AudioBuffer))]);
+}
+
+AUOutputBL::~AUOutputBL()
+{
+	if (mBufferMemory)
+		delete[] mBufferMemory;
+
+	if (mBufferList)
+		delete [] (Byte *)mBufferList;
+}
+
+void 	AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated) 
+{
+	UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1;
+	
+	if (mBufferMemory == NULL || inWantNullBufferIfAllocated)
+	{
+		mBufferList->mNumberBuffers = mNumberBuffers;
+		AudioBuffer *buf = &mBufferList->mBuffers[0];
+		for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+			buf->mNumberChannels = channelsPerBuffer;
+			buf->mDataByteSize = mFormat.FramesToBytes (inNumFrames);
+			buf->mData = NULL;
+		}
+	}
+	else
+	{
+		UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+		if ((nBytes * mNumberBuffers) > AllocatedBytes())
+			throw OSStatus(kAudioUnitErr_TooManyFramesToProcess);
+			
+		mBufferList->mNumberBuffers = mNumberBuffers;
+		AudioBuffer *buf = &mBufferList->mBuffers[0];
+		Byte* p = mBufferMemory;
+		for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+			buf->mNumberChannels = channelsPerBuffer;
+			buf->mDataByteSize = nBytes;
+			buf->mData = p;
+			p += mBufferSize;
+		}
+	}
+}
+
+
+void	AUOutputBL::Allocate (UInt32 inNumFrames)
+{
+	if (inNumFrames) 
+	{
+		UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+		
+		if (nBytes <= AllocatedBytes()) 
+			return;
+		
+			// align successive buffers for Altivec and to take alternating
+			// cache line hits by spacing them by odd multiples of 16
+		if (mNumberBuffers > 1)
+			nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
+		
+		mBufferSize = nBytes;
+		
+		UInt32 memorySize = mBufferSize * mNumberBuffers;
+		Byte *newMemory = new Byte[memorySize];
+		memset(newMemory, 0, memorySize);	// make buffer "hot"
+		
+		Byte *oldMemory = mBufferMemory;
+		mBufferMemory = newMemory;
+		delete[] oldMemory;
+		
+		mFrames = inNumFrames;
+	} 
+	else 
+	{
+		if (mBufferMemory) {
+			delete [] mBufferMemory;
+			mBufferMemory = NULL;
+		}
+		mBufferSize = 0;
+		mFrames = 0;
+	}
+}
+
+#if DEBUG
+void			AUOutputBL::Print()
+{
+	printf ("AUOutputBL::Print\n");
+	mFormat.Print();
+	printf ("Num Buffers:%d, mFrames:%d, allocatedMemory:%c\n", (int)mBufferList->mNumberBuffers, (int)mFrames, (mBufferMemory != NULL ? 'T' : 'F'));
+	AudioBuffer *buf = &mBufferList->mBuffers[0];
+	for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf)
+		printf ("\tBuffer:%d, Size:%d, Chans:%d, Buffer:%p\n", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h
new file mode 100644
index 0000000..0baad3a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h
@@ -0,0 +1,118 @@
+/*
+     File: AUOutputBL.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __AUOutputBL_h__
+#define __AUOutputBL_h__
+
+#include "CAStreamBasicDescription.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#else
+#endif
+
+// ____________________________________________________________________________
+//
+//	AUOutputBL - Simple Buffer List wrapper targetted to use with retrieving AU output
+// Works in one of two ways (both adjustable)... Can use it with NULL pointers, or allocate
+// memory to receive the data in.
+
+// Before using this with any call to AudioUnitRender, it needs to be Prepared
+// as some calls to AudioUnitRender can reset the ABL
+
+class AUOutputBL {
+public:
+											
+											// you CANNOT use one of these - it will crash!
+//										AUOutputBL ();
+										
+											// this is the constructor that you use
+											// it can't be reset once you've constructed it
+										AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames = 512);
+										~AUOutputBL();
+
+	void 								Prepare ()
+										{
+											Prepare (mFrames);
+										}
+									
+								// this version can throw if this is an allocted ABL and inNumFrames is > AllocatedFrames()
+								// you can set the bool to true if you want a NULL buffer list even if allocated
+								// inNumFrames must be a valid number (will throw if inNumFrames is 0)
+	void 								Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated = false);
+	
+	AudioBufferList*					ABL() { return mBufferList; }
+								
+								// You only need to call this if you want to allocate a buffer list
+								// if you want an empty buffer list, just call Prepare()
+								// if you want to dispose previously allocted memory, pass in 0
+								// then you either have an empty buffer list, or you can re-allocate
+								// Memory is kept around if an Allocation request is less than what is currently allocated
+	void								Allocate (UInt32 inNumberFrames);
+	
+	UInt32								AllocatedFrames() const { return mFrames; }
+	
+	const CAStreamBasicDescription&		GetFormat() const { return mFormat; }
+
+#if DEBUG
+	void								Print();
+#endif
+	
+private:
+	UInt32						AllocatedBytes () const { return (mBufferSize * mNumberBuffers); }
+
+	CAStreamBasicDescription	mFormat;
+	Byte*						mBufferMemory;
+	AudioBufferList* 			mBufferList;
+	UInt32						mNumberBuffers;
+	UInt32						mBufferSize;
+	UInt32						mFrames;
+
+// don't want to copy these.. can if you want, but more code to write!
+	AUOutputBL () {}
+	AUOutputBL (const AUOutputBL &c);
+	AUOutputBL& operator= (const AUOutputBL& c);
+};
+
+#endif // __AUOutputBL_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp
new file mode 100644
index 0000000..87d7848
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp
@@ -0,0 +1,139 @@
+/*
+     File: AUParamInfo.cpp
+ Abstract: AUParamInfo.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "AUParamInfo.h"
+#include "CAXException.h"
+
+AUParamInfo::AUParamInfo (AudioUnit				inAU, 
+							bool				inIncludeExpert, 
+							bool				inIncludeReadOnly,
+							AudioUnitScope		inScope,
+							AudioUnitElement	inElement)
+	: mAU (inAU),
+	  mNumParams (0),
+	  mParamListID(NULL),
+	  mScope (inScope),
+	  mElement (inElement)
+{
+	UInt32 size;
+	OSStatus result = AudioUnitGetPropertyInfo(mAU, kAudioUnitProperty_ParameterList, inScope, mElement, &size, NULL);
+		if (size == 0 || result) return;
+	
+	int nparams = size / sizeof(AudioUnitPropertyID);
+	mParamListID = new AudioUnitParameterID[nparams];
+
+	memset (mParamListID, 0xFF, size);
+
+	AudioUnitParameterID *paramList = new AudioUnitParameterID[nparams];
+	
+	result = AudioUnitGetProperty(mAU, kAudioUnitProperty_ParameterList, mScope, mElement, paramList, &size);
+	if (result) {
+		delete [] mParamListID;
+		delete [] paramList;
+		mParamListID = NULL;
+		return;
+	}
+	
+	ParameterMap params;
+	for (int i = 0; i < nparams; ++i) 
+	{
+		CAAUParameter auvp (mAU, paramList[i], mScope, mElement); // took out only using global scope in CAAUParameter creation
+		const AudioUnitParameterInfo &paramInfo = auvp.ParamInfo();
+			
+		//	don't include if parameter can't be read or written
+		if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable) 
+			&& !(paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
+			continue;
+
+		// only include if expert params wanted
+		if (!inIncludeExpert && auvp.IsExpert())
+			continue;
+		
+		// only include if read only params are wanted
+		if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable) 
+			&& (paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
+		{	
+			if (!inIncludeReadOnly)
+				continue;
+		}
+		
+		mParamListID[mNumParams] = paramList[i];
+		mNumParams++;
+		
+		// ok - if we're here, then we have a parameter we are going to display.
+		UInt32 clump = 0;
+		auvp.GetClumpID (clump);
+		mParams[clump].push_back (auvp);
+	}
+
+	delete [] paramList;
+}
+
+AUParamInfo::~AUParamInfo()
+{
+	delete [] mParamListID;
+}
+
+UInt32			AUParamInfo::NumParamsForClump (UInt32 inClump) const
+{ 
+	ParameterMap::const_iterator it = mParams.find(inClump);
+	if (it != mParams.end()) 
+		return static_cast<UInt32>((*it).second.size());
+	return 0;
+}
+
+const CAAUParameter*	AUParamInfo::GetParamInfo (AudioUnitParameterID inParamID) const
+{
+	for (ParameterMap::const_iterator it = mParams.begin(); it != mParams.end(); ++it) {
+		const ParameterList &list = (*it).second;
+		for (ParameterList::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
+			if (inParamID == (*iter).mParameterID) {
+				return &(*iter);
+			}
+		}
+	}
+	return NULL;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h
new file mode 100644
index 0000000..d15fbfe
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h
@@ -0,0 +1,112 @@
+/*
+     File: AUParamInfo.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include <map>
+#include <vector>
+#include <AudioUnit/AudioUnit.h>
+#include "CAAUParameter.h"
+
+/*
+	The ParameterMap returned by the Map() method is a map where 
+		- the key is the clumpID
+		- the value is a ParameterList (vector<CAAUParameter>)
+		
+	If you have parameters on multiple scopes (or elements within a scope), then you should create one of these 
+	for each scope-element pair
+*/
+
+class AUParamInfo {
+
+public:
+	typedef std::vector <CAAUParameter> ParameterList;
+	typedef std::map <UInt32, ParameterList, std::less<UInt32> > ParameterMap;
+
+
+
+							AUParamInfo (AudioUnit		inAU, 
+									bool				inIncludeExpert, 
+									bool				inIncludeReadOnly, 
+									AudioUnitScope		inScope = kAudioUnitScope_Global,
+									AudioUnitElement	inElement = 0);
+									
+							~AUParamInfo();
+							
+	const ParameterMap&		Map () const { return mParams; }
+	
+	// some convenience methods
+	UInt32					NumParams () const { return mNumParams; }
+	
+	AudioUnitParameterID	ParamID (UInt32 inIndex) const 
+							{ 
+								if (inIndex < mNumParams) return mParamListID[inIndex]; 
+								return 0xFFFFFFFF; 
+							}
+							 
+	UInt32					NumClumps () const { return static_cast<UInt32>(mParams.size()); }
+
+	UInt32					NumParamsForClump (UInt32 inClump) const;
+	
+			// returns NULL if there's no info for the parameter
+	const CAAUParameter*	GetParamInfo (AudioUnitParameterID inParamID) const;
+	
+	AudioUnitScope			GetScope () const { return mScope; }
+	AudioUnitElement		GetElement () const { return mElement; }
+	
+private:
+
+	AudioUnit				mAU;
+	UInt32					mNumParams;
+	AudioUnitParameterID *	mParamListID;
+	
+	ParameterMap			mParams;
+	AudioUnitScope			mScope;
+	AudioUnitElement		mElement;
+		
+		// disallow
+	AUParamInfo () {}
+	AUParamInfo (const AUParamInfo &c) {}
+	AUParamInfo& operator= (const AUParamInfo& c) { return *this; }
+};
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp
new file mode 100644
index 0000000..4e72b22
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp
@@ -0,0 +1,227 @@
+/*
+     File: CAAUMIDIMap.cpp
+ Abstract: CAAUMIDIMap.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAAUMIDIMap.h"
+#include <pthread.h>
+
+struct AllMidiTransformers
+{
+	MIDILinearTransformer linearTrans; 
+	MIDILogTransformer logTrans;
+	MIDIExpTransformer expTrans;
+	MIDISqrtTransformer sqrtTrans;
+	MIDISquareTransformer squareTrans;
+	MIDICubeRtTransformer cubeRtTrans;
+	MIDICubeTransformer cubeTrans;
+};
+
+AllMidiTransformers* gAllMidiTransformers = NULL;
+
+#if TARGET_OS_MAC
+static pthread_once_t sOnce = PTHREAD_ONCE_INIT;
+
+static void InitAllMidiTransformers()
+{
+	gAllMidiTransformers = new AllMidiTransformers();
+}
+
+static void CheckInitAllMidiTransformers()
+{
+	pthread_once(&sOnce, InitAllMidiTransformers);
+}
+#endif
+
+MIDIValueTransformer *	CAAUMIDIMap::GetTransformer (UInt32 inFlags)
+{
+#if TARGET_OS_MAC
+	if (gAllMidiTransformers == NULL) 
+		CheckInitAllMidiTransformers();
+#else
+	if (gAllMidiTransformers == NULL) 
+		gAllMidiTransformers = new AllMidiTransformers();
+#endif
+	
+	if (AudioUnitDisplayTypeIsLogarithmic(inFlags))
+		return &gAllMidiTransformers->logTrans;
+	else if (AudioUnitDisplayTypeIsExponential(inFlags))
+		return &gAllMidiTransformers->expTrans;
+	else if (AudioUnitDisplayTypeIsSquareRoot(inFlags))
+		return &gAllMidiTransformers->sqrtTrans;
+	else if (AudioUnitDisplayTypeIsSquared(inFlags))
+		return &gAllMidiTransformers->squareTrans;
+	else if (AudioUnitDisplayTypeIsCubed(inFlags))
+		return &gAllMidiTransformers->cubeTrans;
+	else if (AudioUnitDisplayTypeIsCubeRoot(inFlags))
+		return &gAllMidiTransformers->cubeRtTrans;
+	else
+		return &gAllMidiTransformers->linearTrans;
+}
+
+// The CALLER of this method must ensure that the status byte's MIDI Command matches!!!
+bool	CAAUMIDIMap::MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const
+{
+	// see if the channels match first
+	SInt8 chan = Channel();
+	// channel matches (if chan is less than zero, "Any Channel" flag is set)
+	if (chan >= 0 && chan != inChannel)
+		return false;
+
+	// match the special cases first
+	if (IsKeyEvent()) {
+		// we're using this key event as an on/off type switch
+		if (IsBipolar()) {
+			if (IsKeyPressure()){
+				if (IsBipolar_OnValue()) {
+					if (inData2 > 63) {
+						outLinear = 1;
+						return true;
+					}
+				} else {
+					if (inData2 < 64) {
+						outLinear = 0;
+						return true;
+					}
+				}
+				return false;
+			}
+			else {
+				if (IsBipolar_OnValue()) {
+					if (inData1 > 63) {
+						outLinear = 1;
+						return true;
+					}
+				} else {
+					if (inData1 < 64) {
+						outLinear = 0;
+						return true;
+					}
+				}
+				return false;
+			}
+		}
+		if (IsAnyNote()) {
+// not quite sure how to interpret this...
+			if (IsKeyPressure())
+				outLinear = inData2 / 127.0;
+			else
+				outLinear = inData1 / 127.0;
+			return true;
+		}
+		if (mData1 == inData1) {
+			if (IsKeyPressure())
+				outLinear = inData2 / 127.0;
+			else
+				outLinear = 1;
+			return true;
+		}
+		return false;
+	}
+	else if (IsControlChange()) {
+		// controller ID matches
+		if (mData1 == inData1) {
+			if (IsBipolar()) {
+				if (IsBipolar_OnValue()) {
+					if (inData2 > 63) {
+						outLinear = 1;
+						return true;
+					}
+				} else {
+					if (inData2 < 64) {
+						outLinear = 0;
+						return true;
+					}
+				}
+				return false;
+			}
+			//printf("this in midi matches %X with ", this); 
+			outLinear = inData2 / 127.; 
+			return true;
+		}
+		return false;
+	}
+	
+		// this just matches on the patch change value itself...
+	if (IsPatchChange()) {
+		if (mData1 == inData1) {
+			outLinear = 1;
+			return true;
+		}
+		return false;
+	}
+
+	// finally, for the other two, just check the bi-polar matching conditions
+	// pitch bend and after touch
+	if (IsBipolar()) {
+		if (IsBipolar_OnValue()) {
+			if (inData1 > 63) {
+				outLinear = 1;
+				return true;
+			}
+		} else {
+			if (inData1 < 64) {
+				outLinear = 0;
+				return true;
+			}
+		}
+		return false;
+	}
+
+	if (IsPitchBend()) {
+		UInt16 value = (inData2 << 7) | inData1;
+		outLinear = value / 16383.;
+	}
+	else if (IsChannelPressure()) {
+		outLinear = inData1 / 127.0;
+	}
+
+	return true;
+}
+
+
+void		CAAUMIDIMap::Print () const
+{
+	printf ("CAAUMIDIMap:%p, (%u/%u), mParamID %d, IsValid:%c, Status:0x%X, mData1 %d, Flags:0x%X\n", this, (unsigned int)mScope, (unsigned int)mElement, (int)mParameterID, (IsValid() ? 'T' : 'F'), mStatus, mData1, (int)mFlags);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h
new file mode 100644
index 0000000..a53fdf7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h
@@ -0,0 +1,541 @@
+/*
+     File: CAAUMIDIMap.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAAUMIDIMap_h_
+#define __CAAUMIDIMap_h_
+
+#include <AudioUnit/AudioUnitProperties.h>
+#include <algorithm>
+
+/*
+enum {
+	kAUParameterMIDIMapping_AnyChannelFlag		= (1L << 0),
+		// If this flag is set and mStatus is a MIDI channel message, then the MIDI channel number 
+		// in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
+
+	kAUParameterMIDIMapping_AnyNoteFlag			= (1L << 1),
+		// If this flag is set and mStatus is a Note On, Note Off, or Polyphonic Pressure message,
+		// the message's note number is ignored; the mapping is from ANY note number.
+
+	kAUParameterMIDIMapping_SubRange			= (1L << 2),
+		// set this flag if the midi control should map only to a sub-range of the parameter's value
+		// then specify that range in the mSubRangeMin and mSubRangeMax members
+
+	kAUParameterMIDIMapping_Toggle				= (1L << 3),
+		// this is only useful for boolean typed parameters. When set, it means that the parameter's
+		// value should be toggled (if true, become false and vice versa) when the represented MIDI message
+		// is received
+	
+	kAUParameterMIDIMapping_Bipolar				= (1L << 4),
+		// this can be set to when mapping a MIDI Controller to indicate that the parameter (typically a boolean
+		// style parameter) will only have its value changed to either the on or off state of a MIDI controller message
+		// (0 < 64 is off, 64 < 127 is on) such as the sustain pedal. The seeting of the next flag
+		// (kAUParameterMIDIMapping_Bipolar_On) determine whether the parameter is mapped to the on or off
+		// state of the controller
+	kAUParameterMIDIMapping_Bipolar_On			= (1L << 5)
+		// only a valid flag if kAUParameterMIDIMapping_Bipolar is set
+};
+
+// The reserved fields here are being used to reserve space (as well as align to 64 bit size) for future use
+// When/If these fields are used, the names of the fields will be changed to reflect their functionality
+// so, apps should NOT refer to these reserved fields directly by name
+typedef struct AUParameterMIDIMapping
+{
+	AudioUnitScope			mScope;
+	AudioUnitElement		mElement;
+	AudioUnitParameterID	mParameterID;
+	UInt32					mFlags;
+	Float32					mSubRangeMin;
+	Float32					mSubRangeMax;
+	UInt8					mStatus;
+	UInt8					mData1;
+	UInt8					reserved1; // MUST be set to zero
+	UInt8					reserved2; // MUST be set to zero
+	UInt32					reserved3; // MUST be set to zero
+} AUParameterMIDIMapping;
+*/
+
+/*
+Parameter To MIDI Mapping Properties
+These properties are used to:
+Describe a current set of mappings between MIDI messages and Parameter value setting
+Create a mapping between a parameter and a MIDI message through either:
+- explicitly adding (or removing) the mapping
+- telling the AU to hot-map the next MIDI message to a specified Parameter
+	The same MIDI Message can map to one or more parameters
+	One Parameter can be mapped from multiple MIDI messages
+
+	In general usage, these properties only apply to AU's that implement the MIDI API
+	AU Instruments (type=='aumu') and Music Effects (type == 'aumf')
+
+	These properties are used in the Global scope. The scope and element members of the structure describe
+	the scope and element of the parameter. In all usages, mScope, mElement and mParameterID must be
+	correctly specified.
+
+
+	* The AUParameterMIDIMapping Structure
+
+	Command				mStatus			mData1			
+	Note Off			0x8n			Note Num		
+	Note On				0x9n			Note Num		
+	Key Pressure		0xAn			Note Num		
+	Control Change		0xBn			ControllerID	
+	Patch Change		0xCn			Patch Num		
+	Channel Pressure	DxDn			0 (Unused)		
+	Pitch Bend			0xEn			0 (Unused)		
+
+	(where n is 0-0xF to correspond to MIDI channels 1-16)
+
+		Details:
+
+	In general MIDI Commands can be mapped to either a specific channel as specified in the mStatus bit.
+	If the kAUParameterMIDIMapping_AnyChannelFlag bit is set mStatus is a MIDI channel message, then the 
+	MIDI channel number in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
+
+	For note commands (note on, note off, key pressure), the MIDI message can trigger either with just a specific
+	note number, or any note number if the kAUParameterMIDIMapping_AnyNoteFlag bit is set. In these instances, the
+	note number is used as the trigger value (for instance, a note message could be used to set the 
+											  cut off frequency of a filter).
+
+ The Properties:								
+
+	kAudioUnitProperty_AllParameterMIDIMappings							array of AUParameterMIDIMapping (read/write)
+	This property is used to both retreive and set the current mapping state between (some/many/all of) its parameters
+	and MIDI messages. When set, it should replace any previous mapped settings the AU had.
+
+	If this property is implemented by a non-MIDI capable AU (such as an 'aufx' type), then the property is
+	read only, and recommends a suggested set of mappings for the host to perform. In this case, it is the 
+	host's responsibility to map MIDI message to the AU parameters. As described previously, there are a set
+	of default mappings (see AudioToolbox/AUMIDIController.h) that the host can recommend to the user 
+	in this circumstance.
+
+	This property's size will be very dynamic, depending on the number of mappings currently in affect, so the 
+	caller should always get the size of the property first before retrieving it. The AU should return an error
+	if the caller doesn't provide enough space to return all of the current mappings.
+
+	kAudioUnitProperty_AddParameterMIDIMapping							array of AUParameterMIDIMapping (write only)
+	This property is used to Add mappings to the existing set of mappings the AU possesses. It does NOT replace
+	any existing mappings.
+
+	kAudioUnitProperty_RemoveParameterMIDIMapping						array of AUParameterMIDIMapping (write only)
+	This property is used to remove the specified mappings from the AU. If a mapping is specified that does not
+	currently exist in the AU, then it should just be ignored.
+
+	kAudioUnitProperty_HotMapParameterMIDIMapping								AUParameterMIDIMapping (read/write)
+	This property is used in two ways, determined by the value supplied by the caller.
+	(1) If a mapping struct is provided, then that struct provides *all* of the information that the AU should
+	use to map the parameter, *except* for the MIDI message. The AU should then listen for the next MIDI message
+	and associate that MIDI message with the supplied AUParameter mapping. When this MIDI message is received and
+	the mapping made, the AU should also issue a notification on this property 
+	(kAudioUnitProperty_HotMapParameterMIDIMapping) to indicate to the host that the mapping has been made. The host
+	can then retrieve the mapping that was made by getting the value of this property.
+
+	To avoid possible confusion, it is recommended that once the host has retrieved this mapping (if it is 
+	presenting a UI to describe the mappings for example), that it then clears the mapping state as described next.
+
+	Thus, the only time this property will return a valid value is when the AU has made a mapping. If the AU's mapping
+	state has been cleared (or it has not been asked to make a mapping), then the AU should return 
+	kAudioUnitErr_InvalidPropertyValue if the host tries to read this value.
+
+	(2) If the value passed in is NULL, then if the AU had a parameter that it was in the process of mapping, it
+	should disregard that (stop listening to the MIDI messages to create a mapping) and discard the partially 
+	mapped struct. If the value is NULL and the AU is not in the process of mapping, the AU can ignore the request.
+
+	At all times, the _AllMappings property will completely describe the current known state of the AU's mappings
+	of MIDI messages to parameters.
+*/
+
+
+/*
+	When mapping, it is recommended that LSB controllers are in general not mapped (ie. the controller range of 32 < 64)
+	as many host parsers will map 14 bit control values. If you know (or can present an option) that the host deals with
+	7 bit controllers only, then these controller ID's can be mapped of course.
+*/
+
+
+struct MIDIValueTransformer {
+	virtual double  tolinear(double) = 0;
+	virtual double  fromlinear(double) = 0;
+#if DEBUG
+	// suppress warning
+	virtual ~MIDIValueTransformer() { }
+#endif
+};
+
+struct MIDILinearTransformer : public MIDIValueTransformer {
+	virtual double  tolinear(double x) { return x; }
+	virtual double  fromlinear(double x) { return x; }
+};
+
+struct MIDILogTransformer : public MIDIValueTransformer {
+	virtual double  tolinear(double x) { return log(std::max(x, .00001)); }
+	virtual double  fromlinear(double x) { return exp(x); }
+};
+
+struct MIDIExpTransformer : public MIDIValueTransformer {
+	virtual double  tolinear(double x) { return exp(x); }
+	virtual double  fromlinear(double x) { return log(std::max(x, .00001)); }
+};
+
+struct MIDISqrtTransformer : public MIDIValueTransformer {
+	virtual double  tolinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
+	virtual double  fromlinear(double x) { return x < 0. ? -(x * x) : x * x; }
+};
+
+struct MIDISquareTransformer : public MIDIValueTransformer {
+	virtual double  tolinear(double x) { return x < 0. ? -(x * x) : x * x; }
+	virtual double  fromlinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
+};
+
+struct MIDICubeRtTransformer : public MIDIValueTransformer {
+	virtual double  tolinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
+	virtual double  fromlinear(double x) { return x * x * x; }
+};
+
+struct MIDICubeTransformer : public MIDIValueTransformer {
+	virtual double  tolinear(double x) { return x * x * x; }
+	virtual double  fromlinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
+};
+
+
+class CAAUMIDIMap : public AUParameterMIDIMapping {
+	
+public:
+// variables for more efficient parsing of MIDI to Param value	
+	Float32						mMinValue;
+	Float32						mMaxValue;
+	MIDIValueTransformer		*mTransType;
+
+// methods	
+	static MIDIValueTransformer *GetTransformer (UInt32 inFlags);
+	
+								CAAUMIDIMap() { memset(this, 0, sizeof(CAAUMIDIMap)); }
+								CAAUMIDIMap (const AUParameterMIDIMapping& inMap) 
+								{
+									memset(this, 0, sizeof(CAAUMIDIMap));
+									memcpy (this, &inMap, sizeof(inMap));
+								}
+								CAAUMIDIMap (AudioUnitScope inScope, AudioUnitElement inElement, AudioUnitParameterID inParam) 
+								{ 
+									memset(this, 0, sizeof(CAAUMIDIMap)); 
+									mScope = inScope;
+									mElement = inElement;
+									mParameterID = inParam;
+								}
+
+
+	bool						IsValid () const { return mStatus != 0; }
+
+	// returns -1 if any channel bit is set
+	SInt32						Channel () const { return IsAnyChannel() ? -1 : (mStatus & 0xF); }
+	bool						IsAnyChannel () const { 
+									return mFlags & kAUParameterMIDIMapping_AnyChannelFlag; 
+								}
+									// preserves the existing channel info in the status byte
+									// preserves any previously set mFlags value
+	void						SetAnyChannel (bool inFlag) 
+								{ 
+									if (inFlag) 
+										mFlags |= kAUParameterMIDIMapping_AnyChannelFlag; 
+									else
+										mFlags &= ~kAUParameterMIDIMapping_AnyChannelFlag;
+								}
+
+	bool						IsAnyNote () const { 		
+									return (mFlags & kAUParameterMIDIMapping_AnyNoteFlag) != 0;
+								}
+									// preserves the existing key num in the mData1 byte
+									// preserves any previously set mFlags value
+	void						SetAnyNote (bool inFlag)
+								{ 
+									if (inFlag) 
+										mFlags |= kAUParameterMIDIMapping_AnyNoteFlag; 
+									else
+										mFlags &= ~kAUParameterMIDIMapping_AnyNoteFlag;
+								}
+									
+	bool						IsToggle() const { return (mFlags & kAUParameterMIDIMapping_Toggle) != 0; }
+	void						SetToggle (bool inFlag)
+								{
+									if (inFlag) 
+										mFlags |= kAUParameterMIDIMapping_Toggle; 
+									else
+										mFlags &= ~kAUParameterMIDIMapping_Toggle;
+								}
+	
+	bool						IsBipolar() const { return (mFlags & kAUParameterMIDIMapping_Bipolar) != 0; }
+									// inUseOnValue is valid ONLY if inFlag is true
+	void						SetBipolar (bool inFlag, bool inUseOnValue = false)
+								{
+									if (inFlag) {
+										mFlags |= kAUParameterMIDIMapping_Bipolar;
+										if (inUseOnValue)
+											mFlags |= kAUParameterMIDIMapping_Bipolar_On;
+										else
+											mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
+									} else {
+										mFlags &= ~kAUParameterMIDIMapping_Bipolar;
+										mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
+									}
+								}
+	bool						IsBipolar_OnValue () const { return (mFlags & kAUParameterMIDIMapping_Bipolar_On) != 0; }
+
+	bool						IsSubRange () const { return (mFlags & kAUParameterMIDIMapping_SubRange) != 0; }
+	void						SetSubRange (Float32 inStartValue, Float32 inStopValue)
+								{
+									mFlags |= kAUParameterMIDIMapping_SubRange; 
+									
+									mSubRangeMin = inStartValue;
+									mSubRangeMax = inStopValue;
+								}
+	
+	void						SetParamRange(Float32 minValue, Float32 maxValue)
+								{
+									mMinValue = minValue;
+									mMaxValue = maxValue;		
+								}
+									
+								// this will retain the subrange values previously set.
+	void						SetSubRange (bool inFlag) 
+								{ 
+									if (inFlag)
+										mFlags |= kAUParameterMIDIMapping_SubRange; 
+									else
+										mFlags &= ~kAUParameterMIDIMapping_SubRange; 
+								}
+	
+	bool						IsAnyValue() const{return !IsBipolar();}
+	bool						IsOnValue() const{return IsBipolar_OnValue();}
+	bool						IsOffValue() const{return IsBipolar();}
+								
+	bool						IsNoteOff () const { return ((mStatus & 0xF0) == 0x80); }
+	bool						IsNoteOn () const { return ((mStatus & 0xF0) == 0x90); }
+	
+	bool						IsKeyPressure () const { return ((mStatus & 0xF0) == 0xA0); }
+	
+	bool						IsKeyEvent () const { return (mStatus > 0x7F) && (mStatus < 0xB0); }
+	
+	bool						IsPatchChange () const { return ((mStatus & 0xF0) == 0xC0); }
+	bool						IsChannelPressure () const { return ((mStatus & 0xF0) == 0xD0); }
+	bool						IsPitchBend () const { return ((mStatus & 0xF0) == 0xE0); }
+	bool						IsControlChange () const { return ((mStatus & 0xF0) == 0xB0); }
+	
+	
+	void						SetControllerOnValue(){SetBipolar(true,true);}
+	void						SetControllerOffValue(){SetBipolar(true,false);}
+	void						SetControllerAnyValue(){SetBipolar(false,false);}
+								
+	// All of these Set calls will reset the mFlags field based on the 
+	// anyChannel param value
+	void						SetNoteOff (UInt8 key, SInt8 channel, bool anyChannel = false)
+								{
+									mStatus = 0x80 | (channel & 0xF);
+									mData1 = key;
+									mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+									
+								}
+
+	void						SetNoteOn (UInt8 key, SInt8 channel, bool anyChannel = false)
+								{
+									mStatus = 0x90 | (channel & 0xF);
+									mData1 = key;
+									mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+								}
+
+	void						SetPolyKey (UInt8 key, SInt8 channel, bool anyChannel = false)
+								{
+									mStatus = 0xA0 | (channel & 0xF);
+									mData1 = key;
+									mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+								}
+
+	void						SetControlChange (UInt8 controllerID, SInt8 channel, bool anyChannel = false)
+								{
+									mStatus = 0xB0 | (channel & 0xF);
+									mData1 = controllerID;
+									mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+								}
+	
+	void						SetPatchChange (UInt8 patchChange, SInt8 channel, bool anyChannel = false)
+								{
+									mStatus = 0xC0 | (channel & 0xF);
+									mData1 = patchChange;
+									mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+								}
+
+	void						SetChannelPressure (SInt8 channel, bool anyChannel = false)
+								{
+									mStatus = 0xD0 | (channel & 0xF);
+									mData1 = 0;
+									mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+								}
+
+	void						SetPitchBend (SInt8 channel, bool anyChannel = false)
+								{
+									mStatus = 0xE0 | (channel & 0xF);
+									mData1 = 0;
+									mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+								}
+	
+	
+	Float32						ParamValueFromMIDILinear (Float32		inLinearValue) const
+	{
+								Float32 low, high;
+								if (IsSubRange()){
+									low = mSubRangeMin;
+									high = mSubRangeMax;
+								}
+								else {
+									low = mMinValue;
+									high = mMaxValue;
+								}
+								
+								
+								// WE ARE ASSUMING YOU HAVE SET THIS UP PROPERLY!!!!! (or this will crash cause it will be NULL)
+								return (Float32)mTransType->fromlinear((inLinearValue * (high - low)) + low);
+	}
+		
+
+		// The CALLER of this method must ensure that the status byte's MIDI Command (ignoring the channel) matches!!!
+	bool						MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const;
+	
+	void						Print () const;
+	
+	void						Save (CFPropertyListRef &outData) const;
+	void						Restore (CFDictionaryRef inData);
+	
+	static void					SaveAsMapPList (AudioUnit						inUnit, 
+											const AUParameterMIDIMapping		* inMappings, 
+											UInt32								inNumMappings, 
+											CFPropertyListRef					&outData,
+											CFStringRef							inName = NULL);
+
+									// inNumMappings describes how much memory is allocated in outMappings
+	static void					RestoreFromMapPList (const CFDictionaryRef			inData, 
+														AUParameterMIDIMapping		* outMappings, 
+														UInt32						inNumMappings);
+														
+	static UInt32				NumberOfMaps (const CFDictionaryRef inData);
+};
+
+
+	// these sorting operations sort for run-time efficiency based on the MIDI messages
+inline bool operator== (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
+{
+		// ignore channel first
+	return (((a.mStatus & 0xF0) == (b.mStatus & 0xF0))
+			&& (a.mData1 == b.mData1)
+			&& ((a.mStatus & 0xF) == (b.mStatus & 0xf))  // now compare the channel
+			&&  (a.mParameterID == b.mParameterID)
+			&& (a.mElement == b.mElement)
+			&& (a.mScope == b.mScope));
+	
+	// reserved field comparisons - ignored until/if they are used
+}
+
+inline bool operator< (const CAAUMIDIMap	&a, const CAAUMIDIMap &b)
+{
+	if ((a.mStatus & 0xF0) != (b.mStatus & 0xF0)) 
+		return ((a.mStatus & 0xF0) < (b.mStatus & 0xF0));
+	
+	if (a.mData1 != b.mData1)
+		return (a.mData1 < b.mData1);
+
+	if ((a.mStatus & 0xF) != (b.mStatus & 0xf))  // now compare the channel
+		return ((a.mStatus & 0xF) < (b.mStatus & 0xf));
+
+// reserved field comparisons - ignored until/if they are used
+		
+//		we're sorting this by MIDI, so we don't really care how the rest is sorted
+	return	((a.mParameterID < b.mParameterID)
+				&& (a.mElement < b.mElement)
+				&& (a.mScope < b.mScope));
+}
+
+
+
+class CompareMIDIMap {
+	int compare (const CAAUMIDIMap &a, const CAAUMIDIMap &b) 
+	{
+		if ((a.mStatus & 0xF0) < (b.mStatus & 0xF0))
+			return -1;
+		if ((a.mStatus & 0xF0) > (b.mStatus & 0xF0))
+			return 1;
+
+			// note event
+		if (a.mStatus < 0xB0 || a.mStatus >= 0xD0)
+			return 0;
+		if (a.mData1 > b.mData1) return 1;
+		if (a.mData1 < b.mData1) return -1;
+		return 0;
+	}
+					 
+public:
+	bool operator() (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
+		return compare (a, b) < 0;
+	}
+	bool Finish (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
+		return compare (a, b) != 0;
+	}
+};
+
+
+/*
+	usage: To find potential mapped events for a given status byte, where mMMapEvents is a sorted vec
+	CompareMIDIMap comparObj;
+	sortVecIter lower_iter = std::lower_bound(mMMapEvents.begin(), mMMapEvents.end(), inStatusByte, compareObj);
+	for (;lower_iter < mMMapEvents.end(); ++lower_iter) {
+		// then, see if we go out of the status byte range, using the Finish method
+		if (compareObj.Finish(map, tempMap)) // tempMap is a CAAUMIDIMap object with the status/dataByte 1 set
+			break;
+	// ...
+	}
+	
+	in the for loop you call the MIDI_Matches call, to see if the MIDI event matches a given AUMIDIParam mapping
+	special note: you HAVE to transform note on (with vel zero) events to the note off status byte
+*/
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp
new file mode 100644
index 0000000..b24ff99
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp
@@ -0,0 +1,233 @@
+/*
+     File: CAAUMIDIMapManager.cpp
+ Abstract: CAAUMIDIMapManager.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAAUMIDIMapManager.h"
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+CAAUMIDIMapManager::CAAUMIDIMapManager()
+{	
+	hotMapping = false;	
+}
+
+static void FillInMap (CAAUMIDIMap &map, AUBase &That)
+{
+	AudioUnitParameterInfo info;
+	That.GetParameterInfo (map.mScope, map.mParameterID, info);
+	
+	if (map.IsSubRange()) {
+		map.mMinValue = map.mSubRangeMin;
+		map.mMaxValue = map.mSubRangeMax;
+	} else {
+		map.mMinValue = info.minValue;			
+		map.mMaxValue = info.maxValue;		
+	}
+	
+	map.mTransType = CAAUMIDIMap::GetTransformer(info.flags);
+}
+
+OSStatus	CAAUMIDIMapManager::SortedInsertToParamaterMaps	(AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That)
+{	
+	for (unsigned int i = 0; i < inNumMaps; ++i) 
+	{
+		CAAUMIDIMap map(maps[i]);
+
+		FillInMap (map, That);
+		
+		int idx = FindParameterIndex (maps[i]);
+		if (idx > -1)
+			mParameterMaps.erase(mParameterMaps.begin() + idx);
+
+			// least disruptive place to put this is at the end
+		mParameterMaps.push_back(map);
+	}
+	
+	std::sort(mParameterMaps.begin(), mParameterMaps.end(), CompareMIDIMap());	
+	
+	return noErr;
+}
+
+void CAAUMIDIMapManager::GetHotParameterMap(AUParameterMIDIMapping &outMap )
+{
+	outMap = mHotMap;
+}
+
+void CAAUMIDIMapManager::SortedRemoveFromParameterMaps(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange)
+{	
+	if (hotMapping) {
+		hotMapping = false;
+	}
+
+	outMapDidChange = false;
+	for (unsigned int i = 0; i < inNumMaps; ++i) {
+		int idx = FindParameterIndex (maps[i]);
+		if (idx > -1) {
+			//mParameterMaps[idx].Print();
+			mParameterMaps.erase(mParameterMaps.begin() + idx);
+			outMapDidChange = true;
+		}
+	}
+}
+
+void	CAAUMIDIMapManager::ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That)
+{
+	mParameterMaps.clear();
+
+	for (unsigned int i = 0; i < inNumMaps; ++i) {
+		CAAUMIDIMap mapping(inMappings[i]);
+
+		FillInMap (mapping, That);
+		mParameterMaps.push_back (mapping);
+	}
+
+	std::sort(mParameterMaps.begin(),mParameterMaps.end(), CompareMIDIMap());	
+}
+
+bool CAAUMIDIMapManager::HandleHotMapping(UInt8 	inStatus,
+										  UInt8 	inChannel,
+										  UInt8 	inData1,
+										  AUBase	&That)
+{ //used to set the hot map info
+
+	if (inStatus == 0xf0) return false;
+	
+	if (!hotMapping) return false;
+	hotMapping = false;
+
+	mHotMap.mStatus = inStatus | inChannel;  
+	mHotMap.mData1 = inData1; 
+		
+	SortedInsertToParamaterMaps (&mHotMap, 1, That);
+	return true;
+}
+
+#if DEBUG
+
+void CAAUMIDIMapManager::Print()
+{
+	for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) { 
+		CAAUMIDIMap* listmap =  &(*i);		
+		listmap->Print();		
+	}		
+}
+
+#endif // DEBUG
+
+void CAAUMIDIMapManager::GetMaps(AUParameterMIDIMapping* maps)
+{
+	int i = 0;
+	for ( ParameterMaps::iterator iter = mParameterMaps.begin(); iter < mParameterMaps.end(); ++iter, ++i) { 
+		AUParameterMIDIMapping &listmap =  (*iter);	
+		maps[i] = listmap;	
+	}
+}
+
+int CAAUMIDIMapManager::FindParameterIndex (AUParameterMIDIMapping &inMap)
+{ 
+	//used to get back hot mapping and one at a time maps, for ui
+	
+	int idx = 0;
+	for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) { 
+		CAAUMIDIMap & listmap =  (*i);
+		if ( (listmap.mParameterID == inMap.mParameterID) && 
+			 (listmap.mScope == inMap.mScope) && 
+			 (listmap.mElement == inMap.mElement) )
+		{ 
+				return idx; 
+		}
+		idx++;
+	}
+	return -1;
+}
+
+bool CAAUMIDIMapManager::FindParameterMapEventMatch(	UInt8			inStatus,
+														UInt8			inChannel,
+														UInt8			inData1,
+														UInt8			inData2,
+														UInt32			inBufferOffset,
+														AUBase&			inAUBase)
+{
+	bool ret_value = false;
+
+	if (inStatus == 0x90 && !inData2)
+		inStatus = 0x80 | inChannel;
+	
+	//used to test for midi matches once map is made
+	CAAUMIDIMap tempMap;
+	tempMap.mStatus = inStatus | inChannel;
+	tempMap.mData1 = inData1;
+	
+	CompareMIDIMap compareObj;
+
+	AudioUnitEvent event;
+	event.mEventType = kAudioUnitEvent_ParameterValueChange;
+	event.mArgument.mParameter.mAudioUnit = inAUBase.GetComponentInstance();
+	
+	ParameterMaps::iterator lower_iter = 
+	std::lower_bound(mParameterMaps.begin(), mParameterMaps.end(), tempMap, compareObj);
+	
+	while (lower_iter < mParameterMaps.end()) 
+	{
+		CAAUMIDIMap & map = (*lower_iter);
+		if (compareObj.Finish(map, tempMap)) 
+			break;
+		
+		Float32 value;
+		if (map.MIDI_Matches(inChannel, inData1, inData2, value))
+		{	
+			inAUBase.SetParameter ( map.mParameterID, map.mScope, map.mElement, 
+									map.ParamValueFromMIDILinear(value), inBufferOffset);
+
+			event.mArgument.mParameter.mParameterID = map.mParameterID;
+			event.mArgument.mParameter.mScope = map.mScope;
+			event.mArgument.mParameter.mElement = map.mElement;
+			
+			AUEventListenerNotify(NULL, NULL, &event);
+			ret_value = true;
+		}
+		++lower_iter;
+	}
+	return ret_value;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h
new file mode 100644
index 0000000..8926d8f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h
@@ -0,0 +1,102 @@
+/*
+     File: CAAUMIDIMapManager.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAAUMIDIMapManager_h_
+#define __CAAUMIDIMapManager_h_
+
+#include "AUBase.h"
+#include "CAAUMIDIMap.h"
+#include <vector>
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+class CAAUMIDIMapManager {
+		
+protected:
+	
+	typedef std::vector<CAAUMIDIMap>	ParameterMaps;
+	ParameterMaps						mParameterMaps;
+	
+	bool								hotMapping;
+	AUParameterMIDIMapping				mHotMap;
+	
+public:
+					
+							CAAUMIDIMapManager();
+	
+	UInt32					NumMaps(){return static_cast<UInt32>(mParameterMaps.size());}
+	void					GetMaps(AUParameterMIDIMapping* maps);
+	
+	int						FindParameterIndex(AUParameterMIDIMapping &map);
+	
+	void					GetHotParameterMap(AUParameterMIDIMapping &outMap);
+		
+	void					SortedRemoveFromParameterMaps	(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange);
+	OSStatus				SortedInsertToParamaterMaps	(AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That);
+	
+	void					ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That);
+	
+	bool					IsHotMapping(){return hotMapping;}
+	void					SetHotMapping (AUParameterMIDIMapping &inMap){hotMapping = true; mHotMap = inMap; }
+	
+	bool					HandleHotMapping(	UInt8 	inStatus,
+												UInt8 	inChannel,
+												UInt8 	inData1,
+												AUBase	&That);
+	
+		
+	bool					FindParameterMapEventMatch(UInt8 	inStatus,
+													   UInt8 	inChannel,
+													   UInt8 	inData1,
+													   UInt8 	inData2,
+													   UInt32	inBufferOffset,
+													   AUBase&	inAUBase);	
+#if DEBUG
+	void					Print();
+#endif
+};
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp
new file mode 100644
index 0000000..2d8fe18
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp
@@ -0,0 +1,400 @@
+/*
+     File: CAAUParameter.cpp
+ Abstract: CAAUParameter.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAAUParameter.h"
+
+CAAUParameter::CAAUParameter() 
+{
+	memset(this, 0, sizeof(CAAUParameter));
+}
+
+CAAUParameter::CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
+{
+	memset(this, 0, sizeof(CAAUParameter));
+	Init (au, param, scope, element);
+}
+
+CAAUParameter::CAAUParameter (AudioUnitParameter &inParam)
+{
+	memset(this, 0, sizeof(CAAUParameter));
+	Init (inParam.mAudioUnit, inParam.mParameterID, inParam.mScope, inParam.mElement);
+}
+
+CAAUParameter::CAAUParameter(const CAAUParameter &a) 
+{
+	memset(this, 0, sizeof(CAAUParameter));
+	*this = a;
+}
+
+CAAUParameter &	CAAUParameter::operator = (const CAAUParameter &a)
+{
+	if (mParamName) CFRelease(mParamName);
+	if (mParamTag) CFRelease(mParamTag);
+	if (mNamedParams) CFRelease(mNamedParams);
+	
+	memcpy(this, &a, sizeof(CAAUParameter));
+
+	if (mParamName) CFRetain(mParamName);
+	if (mParamTag) CFRetain(mParamTag);
+	if (mNamedParams) CFRetain(mNamedParams);
+	
+	return *this;
+}
+
+CAAUParameter::~CAAUParameter()
+{
+	if (mParamName) CFRelease(mParamName);
+	if (mParamTag) CFRelease(mParamTag);
+	if (mNamedParams) CFRelease (mNamedParams);
+}
+
+void		CAAUParameter::Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
+{
+	mAudioUnit = au;
+	mParameterID = param;
+	mScope = scope;
+	mElement = element;
+	
+	UInt32 propertySize = sizeof(mParamInfo);
+	OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo,
+			scope, param, &mParamInfo, &propertySize);
+	if (err)
+		memset(&mParamInfo, 0, sizeof(mParamInfo));
+	if (mParamInfo.flags & kAudioUnitParameterFlag_HasCFNameString) {
+		mParamName = mParamInfo.cfNameString;
+		if (!(mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)) 
+			CFRetain (mParamName);
+	} else
+		mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8);
+	
+	const char* str = 0;
+	switch (mParamInfo.unit)
+	{
+		case kAudioUnitParameterUnit_Boolean:
+			str = "T/F";
+			break;
+		case kAudioUnitParameterUnit_Percent:
+		case kAudioUnitParameterUnit_EqualPowerCrossfade:
+			str = "%";
+			break;
+		case kAudioUnitParameterUnit_Seconds:
+			str = "Secs";
+			break;
+		case kAudioUnitParameterUnit_SampleFrames:
+			str = "Samps";
+			break;
+		case kAudioUnitParameterUnit_Phase:
+		case kAudioUnitParameterUnit_Degrees:
+			str = "Degr.";
+			break;
+		case kAudioUnitParameterUnit_Hertz:
+			str = "Hz";
+			break;
+		case kAudioUnitParameterUnit_Cents:
+		case kAudioUnitParameterUnit_AbsoluteCents:
+			str = "Cents";
+			break;
+		case kAudioUnitParameterUnit_RelativeSemiTones:
+			str = "S-T";
+			break;
+		case kAudioUnitParameterUnit_MIDINoteNumber:
+		case kAudioUnitParameterUnit_MIDIController:
+			str = "MIDI";
+				//these are inclusive, so add one value here
+			mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
+			break;
+		case kAudioUnitParameterUnit_Decibels:
+			str = "dB";
+			break;
+		case kAudioUnitParameterUnit_MixerFaderCurve1:
+		case kAudioUnitParameterUnit_LinearGain:
+			str = "Gain";
+			break;
+		case kAudioUnitParameterUnit_Pan:
+			str = "L/R";
+			break;
+		case kAudioUnitParameterUnit_Meters:
+			str = "Mtrs";
+			break;
+		case kAudioUnitParameterUnit_Octaves:
+			str = "8ve";
+			break;
+		case kAudioUnitParameterUnit_BPM:
+			str = "BPM";
+			break;
+		case kAudioUnitParameterUnit_Beats:
+			str = "Beats";
+			break;
+		case kAudioUnitParameterUnit_Milliseconds:
+			str = "msecs";
+			break;
+		case kAudioUnitParameterUnit_Ratio:
+			str = "Ratio";
+			break;
+		case kAudioUnitParameterUnit_Indexed:
+			{
+				propertySize = sizeof(mNamedParams);
+				err = AudioUnitGetProperty (au, 
+									kAudioUnitProperty_ParameterValueStrings,
+									scope, 
+									param, 
+									&mNamedParams, 
+									&propertySize);
+				if (!err && mNamedParams) {
+					mNumIndexedParams = CFArrayGetCount(mNamedParams);
+				} else {
+						//these are inclusive, so add one value here
+					mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
+				}
+				str = NULL;
+			}
+			break;
+		case kAudioUnitParameterUnit_CustomUnit:
+		{
+			CFStringRef unitName = mParamInfo.unitName;
+			static char paramStr[256];
+			CFStringGetCString (unitName, paramStr, 256, kCFStringEncodingUTF8);
+			if (mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)
+				CFRelease (unitName);
+			str = paramStr;
+			break;
+		}
+		case kAudioUnitParameterUnit_Generic:
+		case kAudioUnitParameterUnit_Rate:
+		default:
+			str = NULL;
+			break;
+	}
+	
+	if (str)
+		mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
+	else
+		mParamTag = NULL;
+}
+
+
+Float32		CAAUParameter::GetValue() const
+{
+	Float32 value = 0.;
+	//OSStatus err = 
+	AudioUnitGetParameter(mAudioUnit, mParameterID, mScope, mElement, &value);
+	return value;
+}
+
+CFStringRef CreateLocalizedStringForParameterValue ( double					inParameterValue,
+													 const CAAUParameter *	inParameter,
+													 UInt32					inDigits,
+													 UInt32					minDigits) {	
+	if (!inParameter) return nil;
+
+	AudioUnitParameterInfo info = inParameter->ParamInfo();
+	int pow10;
+
+	switch (info.unit) {
+		case kAudioUnitParameterUnit_Hertz:
+			// number of significant digits based on value
+			pow10 = int(log10(fmax(inParameterValue, .000001)));
+			break;
+		default:
+			// number of significant digits based on parameter range
+			pow10 = int(log10(fmax(double(info.maxValue - info.minValue), .000001)));
+			break;
+	}
+
+	// pow10	range			nDigitsAfterDecimal
+	//	-2		.0100-.0999		4
+	//	-1		.100-.999		3
+	//	0		1.00-9.99		2
+	//	1		10.0-99.9		1
+	//	2		100-999			0
+	//	3		1000-9990		-1
+	//	4		10000-99900		-2
+	
+	int nDigitsAfterDecimal = inDigits - (pow10 + 1);
+	if (nDigitsAfterDecimal < 0)
+		nDigitsAfterDecimal = 0;	// the least number of digits possible is zero
+
+	if (info.flags & kAudioUnitParameterFlag_IsHighResolution)
+		nDigitsAfterDecimal = 4;
+	
+	CFLocaleRef currentLocale = CFLocaleCopyCurrent(); 
+	CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
+	
+	CFNumberRef maxFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
+	
+	if (nDigitsAfterDecimal > 0)
+		nDigitsAfterDecimal = minDigits;
+		
+	CFNumberRef minFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal); 
+
+	CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMinFractionDigits, minFractionDigits); 
+	CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMaxFractionDigits, maxFractionDigits); 
+	CFStringRef formattedNumberString = CFNumberFormatterCreateStringWithValue (NULL, numberFormatter, kCFNumberDoubleType, &inParameterValue); 
+
+	CFRelease(currentLocale); 
+	CFRelease(numberFormatter); 
+	CFRelease(maxFractionDigits);
+	CFRelease(minFractionDigits);
+
+	return formattedNumberString;
+}
+
+CFStringRef CreateLocalizedStringForParameterValue ( double					inParameterValue,
+													 const CAAUParameter *	inParameter,
+													 UInt32					inDigits) {	
+	return CreateLocalizedStringForParameterValue (inParameterValue, inParameter, inDigits, 1);
+}
+
+double ValueForLocalizedParameterString (CFStringRef string, const CAAUParameter * inParameter) {
+	CFLocaleRef currentLocale = CFLocaleCopyCurrent(); 
+	CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
+
+	double value = 0;
+	Boolean worked = CFNumberFormatterGetValueFromString (numberFormatter, string, NULL, kCFNumberDoubleType, &value);
+	
+	CFRelease(currentLocale);
+	CFRelease(numberFormatter);
+	
+	if (worked)
+		return value;
+	else {
+		AudioUnitParameterInfo info = inParameter->ParamInfo();
+		return info.defaultValue;
+	}
+}
+
+CFStringRef CAAUParameter::GetStringFromValueCopy(const Float32 *value) const
+{
+	if (HasNamedParams())
+	{
+		Float32 val = (value == NULL ? GetValue() : *value);
+		int index = int(mParamInfo.minValue) + int(val);
+		CFStringRef str = GetParamName (index);
+		if (str) {
+			CFRetain (str);
+			return str;
+		}
+	}
+	else if (ValuesHaveStrings()) 
+	{
+		AudioUnitParameterStringFromValue stringValue;
+		stringValue.inParamID = mParameterID;
+		stringValue.inValue = value;
+		stringValue.outString = NULL;
+		UInt32 propertySize = sizeof(stringValue);
+		
+		OSStatus err = AudioUnitGetProperty (mAudioUnit, 
+											kAudioUnitProperty_ParameterStringFromValue,
+											mScope, 
+											0, 
+											&stringValue, 
+											&propertySize);
+		
+		if (!err && stringValue.outString != NULL)
+			return stringValue.outString;
+	}
+	
+	Float32 val = (value == NULL ? GetValue() : *value);
+	AudioUnitParameterUnit unit = this->ParamInfo().unit;
+	if (unit ==  kAudioUnitParameterUnit_Cents || unit == kAudioUnitParameterUnit_AbsoluteCents)
+		return CreateLocalizedStringForParameterValue(val, this, 4, 0);
+	else
+		return CreateLocalizedStringForParameterValue(val, this, 4);
+}
+
+Float32 CAAUParameter::GetValueFromString(CFStringRef str) const
+{
+	if (ValuesHaveStrings()) 
+	{
+		AudioUnitParameterValueFromString valueString;
+		valueString.inParamID = mParameterID;
+		valueString.inString = str;
+		UInt32 propertySize = sizeof(valueString);
+		
+		OSStatus err = AudioUnitGetProperty (mAudioUnit, 
+										kAudioUnitProperty_ParameterValueFromString,
+										mScope, 
+										0, 
+										&valueString, 
+										&propertySize);
+										
+		if (!err) {
+			return valueString.outValue;
+		}
+	}
+	
+	return (Float32) ValueForLocalizedParameterString(str, this);
+}
+
+void		CAAUParameter::SetValue(	AUParameterListenerRef		inListener, 
+									void *							inObject,
+									Float32							inValue) const
+{
+    // clip inValue as: maxValue >= inValue >= minValue before setting
+    Float32 valueToSet = inValue;
+    if (valueToSet > mParamInfo.maxValue)
+        valueToSet = mParamInfo.maxValue;
+    if (valueToSet < mParamInfo.minValue)
+        valueToSet = mParamInfo.minValue;
+    
+	AUParameterSet(inListener, inObject, this, valueToSet, 0);
+}
+
+#if DEBUG
+void	CAAUParameter::Print() const
+{
+	UInt32 clump = 0;
+	GetClumpID (clump);
+	
+	UInt32 len = static_cast<UInt32>(CFStringGetLength(mParamName));
+	char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
+	if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8))
+		chars[0] = 0;
+	
+	printf ("ID: %ld, Clump: %u, Name: %s\n", (long unsigned int) mParameterID, (unsigned int) clump, chars);
+	free (chars);
+}
+#endif
diff --git a/libs/appleutility/CAAUParameter.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h
similarity index 52%
copy from libs/appleutility/CAAUParameter.h
copy to libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h
index 82d75e5..f8b5733 100644
--- a/libs/appleutility/CAAUParameter.h
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h
@@ -1,45 +1,49 @@
-/*	Copyright: 	© Copyright 2005 Apple Computer, Inc. All rights reserved.
-
-	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-			("Apple") in consideration of your agreement to the following terms, and your
-			use, installation, modification or redistribution of this Apple software
-			constitutes acceptance of these terms.  If you do not agree with these terms,
-			please do not use, install, modify or redistribute this Apple software.
-
-			In consideration of your agreement to abide by the following terms, and subject
-			to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
-			copyrights in this original Apple software (the "Apple Software"), to use,
-			reproduce, modify and redistribute the Apple Software, with or without
-			modifications, in source and/or binary forms; provided that if you redistribute
-			the Apple Software in its entirety and without modifications, you must retain
-			this notice and the following text and disclaimers in all such redistributions of
-			the Apple Software.  Neither the name, trademarks, service marks or logos of
-			Apple Computer, Inc. may be used to endorse or promote products derived from the
-			Apple Software without specific prior written permission from Apple.  Except as
-			expressly stated in this notice, no other rights or licenses, express or implied,
-			are granted by Apple herein, including but not limited to any patent rights that
-			may be infringed by your derivative works or by other works in which the Apple
-			Software may be incorporated.
-
-			The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-			WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-			WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-			PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-			COMBINATION WITH YOUR PRODUCTS.
-
-			IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-			CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-			GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-			ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-			OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-			(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-			ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/*
+     File: CAAUParameter.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
 */
-/*=============================================================================
-	CAAUParameter.h
-
-=============================================================================*/
-
 #ifndef __CAAUParameter_h__
 #define __CAAUParameter_h__
 
@@ -61,107 +65,107 @@ public:
 								CAAUParameter(const CAAUParameter &a);
 								/*! @dtor ~CAAUParameter */
 								~CAAUParameter();
-
+		
 	/*! @method operator <@ */
-	bool						operator < (const CAAUParameter &a) const
-								{
-									return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0;
+	bool						operator < (const CAAUParameter &a) const 
+								{ 
+									return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0; 
 								}
 
 	/*! @method operator ==@ */
-	bool						operator == (const CAAUParameter &a) const
-								{
-									return !memcmp(this, &a, sizeof(AudioUnitParameter));
+	bool						operator == (const CAAUParameter &a) const 
+								{ 
+									return !memcmp(this, &a, sizeof(AudioUnitParameter)); 
 								}
-
+	
 	/*! @method operator =@ */
 	CAAUParameter &				operator = (const CAAUParameter &a);
-
+	
 	/*! @method GetValue */
 	Float32						GetValue() const;
 	/*! @method SetValue */
-	void						SetValue(	AUParameterListenerRef			inListener,
+	void						SetValue(	AUParameterListenerRef			inListener, 
 											void *							inObject,
 											Float32							inValue) const;
-
+	
 	/*! @method GetName */
-	CFStringRef					GetName() const { return mParamName; }
+	CFStringRef					GetName() const { return mParamName; }  
 										// borrowed reference!
 
 	/*! @method GetStringFromValueCopy */
-	CFStringRef					GetStringFromValueCopy(const Float32 *value = NULL) const;
+	CFStringRef					GetStringFromValueCopy(const Float32 *value = NULL) const;	
 										// returns a copy of the name of the current parameter value
 										// or null if there is no name associated
 										// caller must release
 	/*! @method ValuesHaveStrings */
-	bool						ValuesHaveStrings () const
-								{
-									return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0;
+	bool						ValuesHaveStrings () const 
+								{ 
+									return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0; 
 								}
-
+	
 	/*! @method GetValueFromString */
-	Float32						GetValueFromString (CFStringRef str) const;
+	Float32						GetValueFromString (CFStringRef str) const;					
 									// caller must release
 
 	/*! @method ParamInfo */
-	const AudioUnitParameterInfo &
+	const AudioUnitParameterInfo &		
 								ParamInfo()	const { return mParamInfo; }
 
 	/*! @method GetParamTag */
 	CFStringRef					GetParamTag() const	{ return mParamTag; }
-									// this may return null! -
+									// this may return null! - 
 									// in which case there is no descriptive tag for the parameter
 
 	/*! @method GetParamName */
 	CFStringRef					GetParamName (int inIndex) const
 									// this can return null if there is no name for the parameter
-								{
-									return (mNamedParams && inIndex < mNumIndexedParams)
+								{ 
+									return (mNamedParams && inIndex < mNumIndexedParams) 
 												? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex)
-												: 0;
+												: 0; 
 								}
-
+	
 	/*! @method GetNumIndexedParams */
 	int							GetNumIndexedParams () const { return mNumIndexedParams; }
-
+	
 	/*! @method IsIndexedParam */
 	bool						IsIndexedParam () const { return mNumIndexedParams != 0; }
-
+	
 	/*! @method HasNamedParams */
 	bool						HasNamedParams () const { return IsIndexedParam() && mNamedParams; }
-
+	
 	/*! @method GetClumpID */
-	bool						GetClumpID (UInt32 &outClumpID) const
-								{
+	bool						GetClumpID (UInt32 &outClumpID) const 
+								{ 
 									if (mParamInfo.flags & kAudioUnitParameterFlag_HasClump) {
 										outClumpID = mParamInfo.clumpID;
 										return true;
 									}
 									return false;
 								}
-
+								
 	/*! @method HasDisplayTransformation */
-	bool						HasDisplayTransformation () const
-								{
-									return GetAudioUnitParameterDisplayType (mParamInfo.flags);
+	bool						HasDisplayTransformation () const 
+								{ 
+									return GetAudioUnitParameterDisplayType (mParamInfo.flags); 
 								}
 
 	/*! @method IsExpert */
-	bool						IsExpert () const
-								{
-									return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode;
+	bool						IsExpert () const 
+								{ 
+									return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode; 
 								}
 #if DEBUG
 	void						Print () const;
 #endif
-
+	
 		// these methods are defined in CAPersistence.cpp
 		// they will persist and restore only the scope, element and param ID's of the AudioUnitParameter
 		// however, this is sufficient to be able to save/restore a CAAUParameter object
 	void						Save (CFPropertyListRef &outData) const;
-
+	
 	static void					Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData);
-
+	
 	static OSStatus				Restore	(const CFPropertyListRef inData, AudioUnitParameter &outParam);
 
 protected:
@@ -176,7 +180,7 @@ protected:
 	short						mNumIndexedParams;
 	/*! @var mNamedParams */
 	CFArrayRef					mNamedParams;
-
+	
 private:
 	void						Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
 
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp
new file mode 100644
index 0000000..1cda39c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp
@@ -0,0 +1,707 @@
+/*
+     File: CAAUProcessor.cpp
+ Abstract: CAAUProcessor.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAAUProcessor.h"						
+#include "CAXException.h"
+
+static OSStatus SilenceInputCallback (void 		*inRefCon, 
+					AudioUnitRenderActionFlags *ioActionFlags, 
+					const AudioTimeStamp 		*inTimeStamp, 
+					UInt32 						inBusNumber, 
+					UInt32 						inNumberFrames, 
+					AudioBufferList 			*ioData)
+{
+	AudioBuffer *buf = ioData->mBuffers;
+	for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
+		memset((Byte *)buf->mData, 0, buf->mDataByteSize);
+		
+		//provide a hint that our input data is silent.
+	*ioActionFlags &= kAudioUnitRenderAction_OutputIsSilence;
+	return noErr;
+}
+
+static AURenderCallbackStruct sSilentCallback = { SilenceInputCallback, NULL };
+
+
+CAAUProcessor::CAAUProcessor (const CAComponent& inComp)
+	: mPreflightABL(NULL)
+{
+	OSStatus result = CAAudioUnit::Open (inComp, mUnit);
+	if (result)
+		throw result;
+	memset (&mUserCallback, 0, sizeof (AURenderCallbackStruct));
+	mMaxTailTime = 10.;
+}
+
+CAAUProcessor::~CAAUProcessor ()
+{
+	if (mPreflightABL)
+		delete mPreflightABL;
+}
+
+inline OSStatus		SetInputCallback (CAAudioUnit &inUnit, AURenderCallbackStruct &inInputCallback)
+{
+	return inUnit.SetProperty (kAudioUnitProperty_SetRenderCallback, 
+											kAudioUnitScope_Input, 
+											0,
+											&inInputCallback, 
+											sizeof(inInputCallback));
+}
+
+static AURenderCallbackStruct sRenderCallback;
+static OSStatus PrerollRenderProc (	void 						* /*inRefCon*/, 
+								AudioUnitRenderActionFlags		* /*inActionFlags*/,
+								const AudioTimeStamp 			* /*inTimeStamp*/, 
+								UInt32 							/*inBusNumber*/,
+								UInt32							/*inNumFrames*/, 
+								AudioBufferList 				*ioData)
+{
+	AudioBuffer *buf = ioData->mBuffers;
+	for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
+		memset((Byte *)buf->mData, 0, buf->mDataByteSize);
+
+	return noErr;
+}
+
+OSStatus 	Preroll (CAAudioUnit & inAU, UInt32 inFrameSize)
+{
+	CAStreamBasicDescription desc;
+	OSStatus result = inAU.GetFormat (kAudioUnitScope_Input, 0, desc);
+	bool hasInput = false;
+			//we have input	
+	if (result == noErr) 
+	{
+		sRenderCallback.inputProc = PrerollRenderProc;
+		sRenderCallback.inputProcRefCon = 0;
+		
+		result = inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 
+								0, &sRenderCallback, sizeof(sRenderCallback));
+		if (result) return result;
+		hasInput = true;
+	}
+	
+	AudioUnitRenderActionFlags flags = 0;
+	AudioTimeStamp time;
+	memset (&time, 0, sizeof(time));
+	time.mFlags = kAudioTimeStampSampleTimeValid;
+
+	CAStreamBasicDescription outputFormat;
+	ca_require_noerr (result = inAU.GetFormat (kAudioUnitScope_Output, 0, outputFormat), home);
+	{
+		AUOutputBL list (outputFormat, inFrameSize);
+		list.Prepare ();
+		
+		result = inAU.Render (&flags, &time, 0, inFrameSize, list.ABL());
+		if (result) { printf("A result %d\n", (int)result); goto home; }
+	}
+
+home:
+	if (hasInput) {
+            // remove our installed callback
+		sRenderCallback.inputProc = 0;
+		sRenderCallback.inputProcRefCon = 0;
+		
+		inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 
+								0, &sRenderCallback, sizeof(sRenderCallback));
+	}
+	return result;
+}
+
+
+OSStatus		CAAUProcessor::EstablishInputCallback (AURenderCallbackStruct &inInputCallback)
+{
+	OSStatus result = SetInputCallback (mUnit, inInputCallback);
+	if (!result)
+		memcpy (&mUserCallback, &inInputCallback, sizeof(AURenderCallbackStruct));
+	else
+		memset (&mUserCallback, 0, sizeof (AURenderCallbackStruct));
+	return result;
+}
+
+OSStatus		CAAUProcessor::SetAUPreset (CFPropertyListRef 			inPreset)
+{
+	return mUnit.SetProperty (kAudioUnitProperty_ClassInfo, 
+									kAudioUnitScope_Global, 
+									0, 
+									&inPreset, 
+									sizeof(inPreset));
+}
+
+OSStatus		CAAUProcessor::SetAUPresetIndex (SInt32				inPresetIndex)
+{
+	AUPreset aup;
+	aup.presetName = NULL;
+	aup.presetNumber = inPresetIndex;
+	return mUnit.SetPresentPreset(aup);
+}
+
+
+OSStatus		CAAUProcessor::SetParameter (AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+											Float32 value, UInt32 bufferOffsetFrames)
+{
+	return mUnit.SetParameter(inID, scope, element, value, bufferOffsetFrames);
+}
+
+
+UInt32			CAAUProcessor::MaxFramesPerRender () const
+{
+	UInt32 maxFrames;
+	UInt32 propSize = sizeof (maxFrames);
+	if (mUnit.GetProperty (kAudioUnitProperty_MaximumFramesPerSlice,
+							kAudioUnitScope_Global, 0, &maxFrames, &propSize))
+	{
+		return 0;
+	}
+	return maxFrames;
+}
+
+OSStatus		CAAUProcessor::SetMaxFramesPerRender (UInt32 inMaxFrames)
+{
+	return mUnit.SetProperty (kAudioUnitProperty_MaximumFramesPerSlice,
+							kAudioUnitScope_Global, 0, &inMaxFrames, sizeof(inMaxFrames));
+}
+
+OSStatus		CAAUProcessor::Initialize (const CAStreamBasicDescription 	&inInputDesc,
+											const CAStreamBasicDescription 	&inOutputDesc,
+												UInt64 						inNumInputSamples)
+{
+	return DoInitialisation (inInputDesc, inOutputDesc, inNumInputSamples, MaxFramesPerRender());
+}
+
+OSStatus		CAAUProcessor::Reinitialize (UInt32 inNewMaxFrames)
+{
+	OSStatus result;
+	CAStreamBasicDescription inputDesc, outputDesc;
+	
+	ca_require_noerr (result = mUnit.GetFormat (kAudioUnitScope_Input, 0, inputDesc), home);
+	ca_require_noerr (result = mUnit.GetFormat (kAudioUnitScope_Output, 0, outputDesc), home);
+	
+	ca_require_noerr (result = DoInitialisation (inputDesc, outputDesc, mNumInputSamples, inNewMaxFrames), home);
+	
+home:
+	return result;
+}
+
+
+OSStatus		CAAUProcessor::DoInitialisation (const CAStreamBasicDescription 	&inInputFormat,
+												const CAStreamBasicDescription 		&inOutputFormat,
+												UInt64								inNumInputSamples,
+												UInt32 								inMaxFrames)
+{
+	OSStatus result;
+	
+	if (inNumInputSamples == 0 && IsOfflineAU())
+		return kAudioUnitErr_InvalidOfflineRender;
+		
+	mNumInputSamples = inNumInputSamples;
+	
+		// first check that we can do this number of channels
+	if (mUnit.CanDo (inInputFormat.NumberChannels(), inOutputFormat.NumberChannels()) == false)
+		ca_require_noerr (result = kAudioUnitErr_FailedInitialization, home);
+	
+	// just uninitialise the AU as a matter of course
+	ca_require_noerr (result = mUnit.Uninitialize(), home);
+
+	ca_require_noerr (result = mUnit.SetFormat (kAudioUnitScope_Input, 0, inInputFormat), home); 
+	ca_require_noerr (result = mUnit.SetFormat (kAudioUnitScope_Output, 0, inOutputFormat), home); 
+	ca_require_noerr (result = SetMaxFramesPerRender (inMaxFrames), home);
+	
+#if !TARGET_OS_IPHONE
+		// if we're any AU but an offline AU, we should tell it that we've processing offline
+	if (!IsOfflineAU()) {
+		UInt32 isOffline = (IsOfflineContext() ? 1 : 0);
+			// don't care whether this succeeds of fails as many AU's don't care about this
+			// but the ones that do its important that they are told their render context
+		mUnit.SetProperty (kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &isOffline, sizeof(isOffline));
+	} else {
+			// tell the offline unit how many input samples we wish to process...
+		mUnit.SetProperty (kAudioUnitOfflineProperty_InputSize,
+												kAudioUnitScope_Global, 0,
+												&mNumInputSamples, sizeof(mNumInputSamples));
+	}
+#endif
+	
+	ca_require_noerr (result = mUnit.Initialize(), home);
+
+	ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+	
+	// finally reset our time stamp
+	// the time stamp we use with the AU Render - only sample count is valid
+	memset (&mRenderTimeStamp, 0, sizeof(mRenderTimeStamp));
+	mRenderTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+
+	// now, if we're NOT an offline AU, preflighting is not required
+	// if we are an offline AU, we should preflight.. an offline AU will tell us when its preflighting is done
+	mPreflightDone = false;
+
+	if (mPreflightABL) {
+		delete mPreflightABL;
+		mPreflightABL = NULL;
+	}
+	
+	mPreflightABL = new AUOutputBL (inOutputFormat);
+
+	mLastPercentReported = 0;
+	
+home:
+	return result;
+}
+
+void		CAAUProcessor::CalculateRemainderSamples (Float64 inSampleRate)
+{
+	mLatencySamples = 0;
+	mTailSamplesToProcess = 0;
+	mTailSamples = 0;
+	mTailSamplesRemaining = 0;
+	return;
+	
+		// nothing to do because we're not processing offline
+	if (IsOfflineContext() == false) return;
+		
+		// because an offline unit has some indeterminancy about what it does with the input samples
+		// it is *required* to deal internally with both latency and tail
+	if (!IsOfflineAU()) 
+	{
+			// when offline we need to deal with both latency and tail
+			
+		// if the AU has latency - how many samples at the start will be zero?
+		// we'll end up chucking these away.
+		Float64 renderTimeProps;
+		UInt32 propSize = sizeof (renderTimeProps);
+		OSStatus result = mUnit.GetProperty (kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0,
+													&renderTimeProps, &propSize);
+		
+		Float64 latencySamples = 0;
+		if (result == noErr) // we have latency to deal with - its reported in seconds
+			latencySamples = renderTimeProps * inSampleRate;
+			
+			// AU tail
+			// if the AU has a tail - we'll pull that many zeroes through at the end to flush
+			// out this tail - think of a decaying digital delay or reverb...
+		result = mUnit.GetProperty (kAudioUnitProperty_TailTime, kAudioUnitScope_Global, 0,
+													&renderTimeProps, &propSize);
+		if (renderTimeProps > mMaxTailTime)
+			renderTimeProps = mMaxTailTime;
+		Float64 tailSamples = 0;
+		if (result == noErr)
+			tailSamples = renderTimeProps * inSampleRate;
+		
+		// this dictates how many samples at the end we need to pull through...
+		// we add latency to tail because we throw the latency samples away from the start of the rendering
+		// and we have to pull that many samples after the end of course to get the last of the original data
+		// then to that is added the tail of the effect...
+		mTailSamplesToProcess = UInt32(tailSamples + latencySamples);
+		mTailSamples = UInt32(tailSamples);
+		mLatencySamples = UInt32(latencySamples);
+	}
+}
+
+#if !TARGET_OS_IPHONE
+CFStringRef		CAAUProcessor::GetOLPreflightName () const
+{
+	if (OfflineAUNeedsPreflight()) 
+	{
+		CFStringRef str;
+		UInt32 size = sizeof(str);
+		OSStatus result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightName,
+												kAudioUnitScope_Global, 0,
+												&str, &size);
+		return result ? NULL : str;
+	}
+	return NULL; // says NO to preflighting
+}
+
+bool		CAAUProcessor::OfflineAUNeedsPreflight () const
+{
+	if (IsOfflineAU()) {
+		UInt32 preflightRequirements;
+		UInt32 size = sizeof(preflightRequirements);
+		OSStatus result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements,
+												kAudioUnitScope_Global, 0,
+												&preflightRequirements, &size);
+		if (result)
+			return false;
+		return preflightRequirements;
+	}
+	return false;
+}
+#endif
+
+OSStatus	CAAUProcessor::Preflight (bool inProcessPreceedingTail)
+{
+	printf(">>>>CAAUProcessor::Preflight\n");
+		//we're preflighting again, so reset ourselves
+	if (mPreflightDone) {
+		mPreflightDone = false;
+		// the time stamp we use with the AU Render - only sample count is valid
+		memset (&mRenderTimeStamp, 0, sizeof(mRenderTimeStamp));
+		mRenderTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+		mUnit.GlobalReset();
+	}
+
+	Float64 sampleRate;
+	OSStatus result = mUnit.GetSampleRate (kAudioUnitScope_Output, 0, sampleRate);
+	CalculateRemainderSamples (sampleRate);
+
+	UInt32 numFrames = MaxFramesPerRender();
+	if (numFrames == 0)
+		return kAudioUnitErr_InvalidProperty;
+	
+	if (!IsOfflineAU()) 
+	{
+		if ((IsOfflineContext() == false && inProcessPreceedingTail) || IsOfflineContext())
+		{
+			// re-establish the user's input callback
+			ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+
+			// Consume the number of input samples indicated by the AU's latency or tail
+			// based on whether the AU is being used in an offline context or not.
+			
+			UInt32 latSamps = IsOfflineContext() ? mLatencySamples : mTailSamples;	
+			printf("latSamps %d\n", (int)latSamps);
+			latSamps = 0;
+			while (latSamps > 0)
+			{
+				if (latSamps < numFrames)
+					numFrames = latSamps;
+					
+					// process the samples (the unit's input callback will read the samples
+					// from the file and convert them to float for processing
+				AudioUnitRenderActionFlags renderFlags = 0;
+				mPreflightABL->Prepare();
+				result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, numFrames, mPreflightABL->ABL());
+				if (result) { printf("B result %d\n", (int)result); goto home; }
+		
+				mRenderTimeStamp.mSampleTime += numFrames;
+				latSamps -= numFrames;
+			}
+			if (IsOfflineContext())
+				mRenderTimeStamp.mSampleTime = mLatencySamples;
+		}
+		else
+		{
+			// processing real-time but not processing preceeding tail, so we should preroll the AU
+			ca_require_noerr (result = Preroll(mUnit, numFrames), home);
+			
+			// re-establish the user's input callback
+			ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+			
+			mRenderTimeStamp.mSampleTime = 0;
+		}
+	}
+#if !TARGET_OS_IPHONE
+	else
+	{
+			// re-establish the user's input callback
+		ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+		
+		UInt32 preflightRequirements;
+		UInt32 size; size = sizeof(preflightRequirements);
+		ca_require_noerr (result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements,
+												kAudioUnitScope_Global, 0,
+												&preflightRequirements, &size), home);
+												
+			// 0 indicates none, otherwise optional or required -> we do it for either
+		if (preflightRequirements) 
+		{
+			for (;;) {
+				// here we need to do the preflight loop - we don't expect any data back, but have to 
+				// give the offline unit all of its input data to allow it to prepare its processing
+				AudioUnitRenderActionFlags renderFlags = kAudioOfflineUnitRenderAction_Preflight;
+				mPreflightABL->Prepare();
+				result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, numFrames, mPreflightABL->ABL());
+				if (result) { printf("C result %d\n", (int)result); goto home; }
+				mRenderTimeStamp.mSampleTime += numFrames;
+		
+				if (renderFlags & kAudioOfflineUnitRenderAction_Complete)
+					break;
+			}
+		}
+		// the time stamp we use with the AU Render - only sample count is valid
+		mRenderTimeStamp.mSampleTime = 0;
+	}
+#endif
+
+	if (result == noErr) {
+		mPreflightDone = true;
+	}
+	
+home:
+	printf("<<<<CAAUProcessor::Preflight\n");
+	return result;
+}
+
+#if !TARGET_OS_IPHONE
+OSStatus 	CAAUProcessor::OfflineAUPreflight (UInt32 inNumFrames, bool &outIsDone)
+{
+	if (!IsOfflineAU())
+		return -50/*paramErr*/;
+	if (mNumInputSamples == 0)
+		return -50/*paramErr*/;
+
+	UInt32 preflightRequirements;
+	UInt32 size = sizeof(preflightRequirements);
+	OSStatus result;
+	ca_require_noerr (result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements,
+												kAudioUnitScope_Global, 0,
+												&preflightRequirements, &size), home);
+												
+		// 0 indicates none, otherwise optional or required -> we do it for either
+	if (preflightRequirements) 
+	{
+		AudioUnitRenderActionFlags renderFlags = kAudioOfflineUnitRenderAction_Preflight;
+		mPreflightABL->Prepare();
+		result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, inNumFrames, mPreflightABL->ABL());
+		if (result) { printf("D result %d\n", (int)result); goto home; }
+		mRenderTimeStamp.mSampleTime += inNumFrames;
+		
+		if (renderFlags & kAudioOfflineUnitRenderAction_Complete) {
+			outIsDone = true;
+			mRenderTimeStamp.mSampleTime = 0;
+			mPreflightDone = true;
+			mLastPercentReported = 0;
+		}
+	}
+	else
+	{
+		outIsDone = true;
+		mRenderTimeStamp.mSampleTime = 0;
+		mPreflightDone = true;
+		mLastPercentReported = 0;
+	}
+	
+home:
+	return result;
+}
+#endif
+
+void SetBufferListToNumFrames (AudioBufferList &list, UInt32 inNumFrames)
+{
+	for (unsigned int i = 0; i < list.mNumberBuffers; ++i) {
+		AudioBuffer &buf = list.mBuffers[i];
+		if (buf.mDataByteSize > 0)
+			buf.mDataByteSize = inNumFrames * sizeof (Float32);
+	}
+}
+
+OSStatus	CAAUProcessor::Render (AudioBufferList 		*ioData, 
+									UInt32 				&ioNumFrames, 
+									bool				&outIsSilence,
+									bool 				*outOLCompleted, 
+									bool 				*outOLRequiresPostProcess)
+{
+	if (IsOfflineContext())
+	{
+		if (!mPreflightDone)
+			return kAudioUnitErr_InvalidOfflineRender;
+	
+			// YES - this is correct!!! you have to provide both if rendering in an offline Context
+		*outOLCompleted = false;
+		*outOLRequiresPostProcess = false;
+
+		if (!IsOfflineAU() && !mUnit.Comp().Desc().IsFConv()) 
+		{
+				// have we processed the input we expect too?
+				// in an offline case, we want to create output that matches the input
+				// for an OfflineAU type, it manages this internally, so we don't have to do anything
+				// for a FormatConverter AU, we don't know and can't tell, so we can't do anything here
+				// for any other AU type (effect, instrument) the Prime assumption is that it will 
+				// ask for the same number of frames of input as it is asked to output
+				// so we can ask what it is doing, and get a sample accurate output (which is input + tail time)
+			if (mRenderTimeStamp.mSampleTime + ioNumFrames >= InputSampleCount()) 
+			{
+					// if we fall into here, we have just a partial number of input samples left 
+					// (less input less than what we've been asked to produce output for.
+				*outOLCompleted = true;
+					// we require post processing if we've got some tail (or latency) samples to flush through
+				*outOLRequiresPostProcess = mTailSamplesToProcess > 0;
+				if (InputSampleCount() > mRenderTimeStamp.mSampleTime) {
+					ioNumFrames = (UInt32)(InputSampleCount() - mRenderTimeStamp.mSampleTime);
+				} else {
+					ioNumFrames = 0;
+				}
+				mTailSamplesRemaining = mTailSamplesToProcess;
+					// we've got no input samples to process this time.
+				SetBufferListToNumFrames (*ioData, ioNumFrames);
+				if (ioNumFrames == 0) {
+					if (*outOLRequiresPostProcess)
+						SetInputCallback (mUnit, sSilentCallback);
+					else
+						mUnit.GlobalReset (); //flush this out, as we're done with this phase
+					return noErr;
+				}
+			}
+		}
+		AudioUnitRenderActionFlags renderFlags = IsOfflineAU() ? kAudioOfflineUnitRenderAction_Render : 0;
+		OSStatus result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData);
+		if (result) { printf("E result %d\n", (int)result); }
+		if (result) {
+			if (mUnit.Comp().Desc().IsFConv()) { 
+				// this is the only way we can tell we're done with a FormatConverter AU 
+				// - ie. client returns an error from input
+				result = noErr;
+				*outOLCompleted = true;
+				*outOLRequiresPostProcess = mTailSamplesToProcess > 0;
+				ioNumFrames = 0;
+				SetBufferListToNumFrames (*ioData, ioNumFrames);
+			} else
+				return result;
+		}
+//	for (UInt32 i = 0; i < ioNumFrames; ++i) {
+//		union {
+//			float f;
+//			unsigned char c[4];
+//		} u;
+//		u.f = ((float*)(ioData->mBuffers[0].mData))[i];
+//		printf("aup out %4d  %14.10f  %02X %02X %02X %02X\n", (int)i, u.f, u.c[0], u.c[1], u.c[2], u.c[3]);
+//	}
+		mRenderTimeStamp.mSampleTime += ioNumFrames;
+		outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence);
+		
+			// if we're an Offline AU type, it will set this flag on completion of its processing
+		if (renderFlags & kAudioOfflineUnitRenderAction_Complete) {
+			// we now need to calculate how many frames we rendered.
+				// as we're dealing with PCM non-interleaved buffers, we can calculate the numFrames simply
+			ioNumFrames = ioData->mBuffers[0].mDataByteSize / sizeof(Float32);
+			*outOLCompleted = true;
+			*outOLRequiresPostProcess = false;
+			mUnit.GlobalReset (); //flush this out, as we're done with this phase
+		} else {
+			if (*outOLCompleted) {
+				if (*outOLRequiresPostProcess)
+					result = SetInputCallback (mUnit, sSilentCallback);
+				else
+					mUnit.GlobalReset (); //flush this out, as we're done with this phase
+			}
+		}
+	
+		return result;
+	}
+
+// rendering in a RT context:
+	AudioUnitRenderActionFlags renderFlags = 0;
+	OSStatus result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData);
+		if (result) { printf("F result %d\n", (int)result); }
+	if (!result) {
+		mRenderTimeStamp.mSampleTime += ioNumFrames;
+		outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence);
+	}
+//	for (UInt32 i = 0; i < ioNumFrames; ++i) {
+//		union {
+//			float f;
+//			unsigned char c[4];
+//		} u;
+//		u.f = ((float*)(ioData->mBuffers[0].mData))[i];
+//		printf("aup out %4d  %14.10f  %02X %02X %02X %02X\n", (int)i, u.f, u.c[0], u.c[1], u.c[2], u.c[3]);
+//	}
+	
+	return result;	
+}
+	
+OSStatus	CAAUProcessor::PostProcess (AudioBufferList 	*ioData, 
+										UInt32 				&ioNumFrames, 
+										bool				&outIsSilence,
+										bool 				&outDone)
+{
+	if (IsOfflineAU() || !IsOfflineContext()) 
+		return kAudioUnitErr_CannotDoInCurrentContext;
+	
+	outDone = false;
+	
+		// we've got less samples to process than we've been asked to process
+	if (mTailSamplesRemaining <= SInt32(ioNumFrames)) {
+		outDone = true;
+		ioNumFrames = mTailSamplesRemaining > 0 ? mTailSamplesRemaining : 0;
+		SetBufferListToNumFrames (*ioData, ioNumFrames);
+		if (ioNumFrames == 0)
+			return noErr;
+	}
+	
+	AudioUnitRenderActionFlags renderFlags = 0;
+	OSStatus result;
+	result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData);
+		if (result) { printf("G result %d\n", (int)result); goto home; }
+	mRenderTimeStamp.mSampleTime += ioNumFrames;
+	mTailSamplesRemaining -= ioNumFrames;
+	outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence);
+			
+	if (outDone) {
+		ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+		mUnit.GlobalReset (); //flush this out, as we're done with this phase
+	}
+home:
+	return result;
+}		
+
+#if !TARGET_OS_IPHONE
+Float32		CAAUProcessor::GetOLPercentComplete ()
+{
+	if (!IsOfflineContext())
+		return 0;
+
+	Float32 percentDone = mLastPercentReported;
+		
+	if (IsOfflineAU()) 
+	{
+		// we get the output size every time, as this can change as parameters are changed
+		UInt64 numOutputSamples = mNumInputSamples;
+		UInt32 propSize = sizeof(numOutputSamples);
+		mUnit.GetProperty (kAudioUnitOfflineProperty_OutputSize,
+							kAudioUnitScope_Global, 0, &numOutputSamples, &propSize);
+		
+		percentDone = (mRenderTimeStamp.mSampleTime / Float64(numOutputSamples)) * 100.;
+	}
+	else
+	{
+		percentDone = (mRenderTimeStamp.mSampleTime / Float64(mNumInputSamples + mTailSamples)) * 100.;
+	}
+	
+	if (percentDone > mLastPercentReported)
+		mLastPercentReported = percentDone;
+
+	return mLastPercentReported;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h
new file mode 100644
index 0000000..f0fb345
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h
@@ -0,0 +1,293 @@
+/*
+     File: CAAUProcessor.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAAUProcessor_h__
+#define __CAAUProcessor_h__
+
+#include <AudioToolbox/AudioToolbox.h>
+#include "CAStreamBasicDescription.h"
+#include "CAAudioUnit.h"
+#include "AUOutputBL.h"
+
+#if TARGET_OS_IPHONE
+	#include <AssertMacros.h>
+#endif
+/*
+	This class wraps an AU (using the CAAudioUnit helper class) to use that AU for processing data
+	It can be used in a RealTime context (rendering data with RT constraints) or in an OffLine context
+	such as using an AU to process data that is stored in a file, and on which there are no
+	RT constraints to be imposed.
+	
+	Order of operations:
+	Create an instance
+	Establish an Input Callback
+	Initialize the AU to the audio formats and whether it is going to process in an offline or RT context
+	Preflight
+	
+	while (...)
+		Render  // based on your calling context
+	
+	PostProcess if needed (only in OL case)
+	
+	After any initialization, preflighting is required.
+	
+	Parameter Values on the AU should be set just before each call to Render. The sampleFrameOffsets
+	supplied when setting those values are an offset into that next render buffer's numFrames.
+	
+	RT vs OT is determined by whether the inputSampleCount is set during Initialization, thus
+	this class can move the AU between RT and OL contexts. If you are using an AU of type 'auol'
+	(Offline), then it cannot be used in a RT context.
+
+	The CAAUProcessor will only call your Input Callback for input when it needs valid input.
+	This input callback will contain a sample time that indicates where within your input
+	you should read data from, where after preflighting, the first output data produces is for 
+	the output sample count of zero.
+	
+	MaxFrames should be set before initialisation (or is also passed in to the Reinitialize API)
+		
+	If RT, then PostProcessing will *never* be required, nor will Render ever return an isDone value
+	If OL, then Render will at some point return isDone==true, and then also indicate if PostProcessing is required
+	
+	If using a Format Converter AU in offline context, then the only way for it to determine that you've finished
+	is for the Input callback to return an error. This means ultimately, that you'll have potentially longer output
+	than you should have. The only way to manage this is for the caller to know the relationship between 
+	input to output samples that will be required, and to call Render for just that amount of output samples
+	then return an error, so the tail and latency can be processed.
+	
+	Tail and Latency are *only* calculated at initialisation.. Some AU's may change these properties based on
+	either different presets or parameter settings... Ideally, this class should listen to those properties
+	and recalculate its values based on those changes.
+*/	
+	
+class CAAUProcessor {
+public:
+									// by default this is set to process offline
+							CAAUProcessor (const CAComponent& inComp);
+							~CAAUProcessor ();
+		
+	CAAudioUnit&			AU() { return mUnit; }
+	const CAAudioUnit&		AU() const { return mUnit; }
+		
+#pragma mark __Setup APIs			
+	bool					IsOfflineContext () const { return mNumInputSamples != 0; }
+								
+								// this contains the callback and client data that the AU 
+								// uses to call when it needs input
+	OSStatus				EstablishInputCallback (AURenderCallbackStruct &inInputCallback);
+	
+	OSStatus				SetAUPreset (CFPropertyListRef 			inPreset);
+	OSStatus				SetAUPresetIndex (SInt32				inPresetIndex);
+	
+	OSStatus				SetParameter (AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+											Float32 value, UInt32 bufferOffsetFrames = 0);
+	
+		// a result of zero here signifies an error
+	UInt32					MaxFramesPerRender () const;
+		
+		// this call can return an error if the AU is initialized - see Reinitialize
+	OSStatus				SetMaxFramesPerRender (UInt32 inMaxFrames);
+		
+	// Prepares the AU for processing at the specified format
+	// only doing n-n channel processing here.. could extend this for n-m channel processing easily enough
+	// if you are processing using an Offline AU, you HAVE to specify the numInputSamples to process
+	// if you are processing real-time, then inNumInputSamples should be zero
+	OSStatus				Initialize (const CAStreamBasicDescription &inIODesc, UInt64 inNumInputSamples = 0)
+							{
+								return Initialize (inIODesc, inIODesc, inNumInputSamples);
+							}
+	OSStatus				Initialize (const CAStreamBasicDescription 		&inInputDesc, 
+										const CAStreamBasicDescription 		&inOutputDesc, 
+										UInt64 								inNumInputSamples = 0);
+	
+		// takes the existing format state of the AU, but resets the AUProcessor so that:
+		// applies an optional new number of max frames
+		// the AUProcessor will have to be Preflighted again after this call
+		// Use this when you want to keep the same formats, same input sample count,
+		// but want to re-initialize the AU to use a new num max frames and prepare it 
+		// appropriately...
+	OSStatus				Reinitialize (UInt32 inNewMaxFrames);
+
+
+
+#pragma mark __Render APIs
+	// Preflighting - you HAVE to preflight
+	// returns noErr when preflighting is done
+	
+	// Offline Context:
+	// Offline AU's require preflighting, even if they will end up doing no work.
+	// In the case where the AU is offline the latency samples are trimmed and not returned 
+	// from the consequent Render calls
+	
+	// If you are NOT an offline AU then the first time Render is called, 
+	// there will need to be some consumption of the input before you will get any valid output data.
+	// This is determined by the value of the AU's reported latency. So, in this case preflight
+	// will consume those initial samples and then return.
+	// Your InputCallback MUST provide the initial data that is to be processed.
+	
+	// RealTime Context:
+	// (1 No priming. In this case inProcessPreceedingTail is false (the default) and no
+	// processing is done on the AU. However, because preflight is the first time that Rendering
+	// is called on an AU we can presume that this is outside the context of the processing that
+	// is occuring in the host application. To avoid taking page faults, priming cold memory, etc.
+	// when the AU *is* consequently used to render real data, the AU is prerolled and reset if this is the case.
+
+	// (2) Prime the AU's buffers with input data that preceeds the portion of audio you
+	// want to process. This amount of input data is equivalent to the tail time of the AU
+	// which expresses how long it takes for an sample on input to disappear from the output
+	// (Think of a delay or a reverb)
+	// So, by setting inProcessPreceedingTail to true, the preflight call will consume
+	// the tail time samples of input (which should be valid input BEFORE the data to be processed)
+	// So, your input proc here will HAVE to read samples from the preceeding input. The time
+	// stamps to your input proc in this case can be interpreted as 0 is the start of the preceeding data
+	// and you'll need to read up to the numSamples of tail time of the preceeding data.
+	// It discards the output results of the preflighting. If you don't have any previous data
+	// with which to prepare the AU, then you do NOT need to take this path and can do the step below.
+	
+	// In both of these cases the inital latency frames are *not* trimmed from
+	// the output that will be generated by a consequent call to render.
+	OSStatus				Preflight (bool inProcessPreceedingTail = false);
+
+	// this can be used with an OfflineAU to do a gradual preflight (so you could for instance, 
+	// present a progress indicator. The Preflight call will do it all at once.
+	// If you break out of the preflight before you are done, then you HAVE to reinitialise the AU
+	// before you can either do another preflight or do a render, otherwise the Render call will produce
+	// invalid results.
+	OSStatus 				OfflineAUPreflight (UInt32 inNumFrames, bool &outIsDone);
+
+	// Here's the major stage that produces output.
+	// You pass in two bool flags and an ioNumFrames....
+	
+	// So ioNumFrames will be *untouched* if outOLCompleted == false
+	// if outOLCompleted is true, ioNumFrames contains the number of valid frames within the ioData data that are valid data
+	// (ioData's pointers and sizes will also have been resized to match these number of frames)
+	// outOLRequiresPostProcess should also be checked when outOLCompleted is true, 
+	// to see if any post-processing is required
+	// if rendering in a RT context, then neither outOLCompleted or outOLRequiresPostProcess is required
+	// if rendering in an OL context, both must be specified.
+	// Caller MUST provide an ABL that is set up in the previously specified output format
+	
+	// If you receive kAudioUnitErr_InvalidOfflineRender when dealing with an OfflineAU Type, then you have either not
+	// preflighted it (and the AU requires it) or you have changed some state (its num input samples, its start offest)
+	// and it needs to be re-preflighted. In that case, preflight the AU again first.
+	OSStatus				Render (AudioBufferList 			*ioData, 
+									UInt32 						&ioNumFrames, 
+									bool						&outIsSilence,
+									bool 						*outOLCompleted = NULL, 
+									bool 						*outOLRequiresPostProcess = NULL);
+	
+	// call this method if outOLRequiresPostProcess returned true upon rendering completion
+	OSStatus				PostProcess (AudioBufferList *ioData, UInt32 &ioNumFrames, bool &outIsSilence, bool &outDone);
+	
+	// This method returns how many input samples will need to be provided before
+	// valid output data is produced.
+	UInt32					LatencySampleCount () const { return mLatencySamples; }
+	
+	UInt32					TailSampleCount () const { return mTailSamples; }
+	
+	UInt64					InputSampleCount () const { return mNumInputSamples; }
+		
+	// the class maintains the TimeStamp from render call to render call
+	// this value is the sample count that will be used in the *next* render call
+	Float64					SampleTime () const { return mRenderTimeStamp.mSampleTime; }
+	
+		// in some settings (for instance a delay with 100% feedback) tail time is essentially infinite
+		// so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through
+		// default is 10 seconds
+	Float64					GetMaxTailTime () const { return mMaxTailTime; }
+	
+	// this ONLY takes affect when you initialise the processor, it doesn't change that AU's tail time,
+	// but just the max amount of time that this object will allow the AU to post-process data
+	// set this to 0, to use the AU's tail time with no adjustment
+	void					SetMaxTailTime (Float64 inTailTimeSecs) { mMaxTailTime = inTailTimeSecs; }
+
+#if !TARGET_OS_IPHONE
+	// if this is NULL, then there is no explicit (optional or required) preflight requirement of the AU
+	// if this is valid, then the AU either requires or optionally requires preflighting. The default
+	// behaviour in this case is that the processor will preflight. This name can be used to preset
+	// to the user. If the AU doesn't present a name, but preflighting is optional/required, then the 
+	// processor return "Preflight" as its string.
+	// the String should be released by the caller.
+	CFStringRef				GetOLPreflightName () const;
+
+	// Returns true if this is processor is an offline AU, and that AU (whether optional or required) 
+	// needs preflighting
+	bool					OfflineAUNeedsPreflight () const;
+	
+	// this provides a rough approximation of the progress of an Offline Processing operation (both for the
+	// preflight and the render phases)
+	Float32					GetOLPercentComplete ();
+#endif
+	
+private:
+	CAAudioUnit 			mUnit;
+	UInt32					mLatencySamples;
+	UInt32					mTailSamples;
+	UInt32					mTailSamplesToProcess;
+	UInt64					mNumInputSamples;
+	AudioTimeStamp			mRenderTimeStamp;
+	bool					mPreflightDone;
+	AUOutputBL *			mPreflightABL;
+	SInt32					mTailSamplesRemaining;
+	AURenderCallbackStruct	mUserCallback;
+	Float64					mMaxTailTime;
+	Float32					mLastPercentReported;
+	
+	bool			IsOfflineAU () const { return mUnit.Comp().Desc().IsOffline(); }
+
+	void			CalculateRemainderSamples (Float64 inSampleRate);
+	
+	OSStatus		DoInitialisation (const CAStreamBasicDescription 	&inInputFormat,
+									const CAStreamBasicDescription 		&inOutputFormat,
+									UInt64								inNumInputSamples,
+									UInt32 								inMaxFrames);
+
+		// stop automatic copying of this object
+	CAAUProcessor () {}
+	CAAUProcessor (const CAAUProcessor &c) {}
+	CAAUProcessor& operator= (const CAAUProcessor& c) { return *this; }
+};
+
+#endif //__CAAUProcessor_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h b/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h
new file mode 100644
index 0000000..c9a611b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h
@@ -0,0 +1,305 @@
+/*
+     File: CAAtomic.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+/*
+	This file implements all Atomic operations using Interlocked functions specified in
+	Winbase.h
+NOTE: According to Microsoft documentation, all Interlocked functions generates a
+full barrier. 
+	On Windows:
+	As the Interlocked functions returns the Old value, Extra checks and operations 
+	are made after the atomic operation to return value consistent with OSX counterparts.
+*/
+#ifndef __CAAtomic_h__
+#define __CAAtomic_h__
+
+#if TARGET_OS_WIN32
+	#include <windows.h>
+	#include <intrin.h>
+	#pragma intrinsic(_InterlockedOr)
+	#pragma intrinsic(_InterlockedAnd)
+#else
+	#include <CoreFoundation/CFBase.h>
+	#include <libkern/OSAtomic.h>
+#endif
+
+inline void CAMemoryBarrier() 
+{
+#if TARGET_OS_WIN32
+	MemoryBarrier();
+#else
+	OSMemoryBarrier();
+#endif
+}
+
+inline SInt32 CAAtomicAdd32Barrier(SInt32 theAmt, volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+	long lRetVal = InterlockedExchangeAdd((volatile long*)theValue, theAmt);
+	// InterlockedExchangeAdd returns the original value which differs from OSX version. 
+	// At this point the addition would have occured and hence returning the new value
+	// to keep it sync with OSX.
+	return lRetVal + theAmt;
+#else
+	return OSAtomicAdd32Barrier(theAmt, (volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicOr32Barrier(UInt32 theMask, volatile UInt32* theValue)
+{
+#if TARGET_OS_WIN32
+	// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
+	// function instead.
+	long j = _InterlockedOr((volatile long*)theValue, theMask);
+	// _InterlockedOr returns the original value which differs from OSX version.
+	// Returning the new value similar to OSX
+	return (SInt32)(j | theMask);
+#else
+	return OSAtomicOr32Barrier(theMask, (volatile uint32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicAnd32Barrier(UInt32 theMask, volatile UInt32* theValue)
+{
+#if TARGET_OS_WIN32
+// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
+// function instead.
+	long j = _InterlockedAnd((volatile long*)theValue, theMask);
+	// _InterlockedAnd returns the original value which differs from OSX version.
+	// Returning the new value similar to OSX
+	return (SInt32)(j & theMask);
+#else
+	return OSAtomicAnd32Barrier(theMask, (volatile uint32_t *)theValue);
+#endif
+}
+
+inline bool CAAtomicCompareAndSwap32Barrier(SInt32 oldValue, SInt32 newValue, volatile SInt32 *theValue)
+{
+#if TARGET_OS_WIN32
+	// InterlockedCompareExchange returns the old value. But we need to return bool value.
+	long lRetVal = InterlockedCompareExchange((volatile long*)theValue, newValue, oldValue);
+// Hence we check if the new value is set and if it is we return true else false.
+// If theValue is equal to oldValue then the swap happens. Otherwise swap doesn't happen.
+	return (oldValue == lRetVal);
+#else
+	return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *)theValue);
+#endif
+}
+
+
+inline SInt32 CAAtomicIncrement32(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+	return (SInt32)InterlockedIncrement((volatile long*)theValue);
+#else
+	return OSAtomicIncrement32((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicDecrement32(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+	return (SInt32)InterlockedDecrement((volatile long*)theValue);
+#else
+	return OSAtomicDecrement32((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicIncrement32Barrier(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+	return CAAtomicIncrement32(theValue);
+#else
+	return OSAtomicIncrement32Barrier((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicDecrement32Barrier(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+	return CAAtomicDecrement32(theValue);
+#else
+	return OSAtomicDecrement32Barrier((volatile int32_t *)theValue);
+#endif
+}
+
+inline bool CAAtomicTestAndClearBarrier(int bitToClear, void* theAddress)
+{
+#if TARGET_OS_WIN32
+	BOOL bOldVal = InterlockedBitTestAndReset((long*)theAddress, bitToClear);
+	return (bOldVal ? true : false);
+#else
+	return OSAtomicTestAndClearBarrier(bitToClear, (volatile void *)theAddress);
+#endif
+}
+
+inline bool CAAtomicTestAndClear(int bitToClear, void* theAddress)
+{
+#if TARGET_OS_WIN32
+	BOOL bOldVal = CAAtomicTestAndClearBarrier(bitToClear, (long*)theAddress);
+	return (bOldVal ? true : false);
+#else
+	return OSAtomicTestAndClear(bitToClear, (volatile void *)theAddress);
+#endif
+}
+
+inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
+{
+#if TARGET_OS_WIN32
+	BOOL bOldVal = InterlockedBitTestAndSet((long*)theAddress, bitToSet);
+	return (bOldVal ? true : false);
+#else
+	return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress);
+#endif
+}
+
+// int32_t flavors -- for C++ only since we can't overload in C
+// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
+// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where
+// SInt32 is defined as signed long so this would work there.
+// So in order to fix the redefinition errors, we define these functions only if MacTypes.h is included.
+#if defined(__cplusplus) && defined(__MACTYPES__) && !__LP64__
+inline int32_t CAAtomicAdd32Barrier(int32_t theAmt, volatile int32_t* theValue)
+{
+	return CAAtomicAdd32Barrier(theAmt, (volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicOr32Barrier(uint32_t theMask, volatile uint32_t* theValue)
+{
+	return CAAtomicOr32Barrier(theMask, (volatile UInt32 *)theValue);
+}
+
+inline int32_t CAAtomicAnd32Barrier(uint32_t theMask, volatile uint32_t* theValue)
+{
+	return CAAtomicAnd32Barrier(theMask, (volatile UInt32 *)theValue);
+}
+
+inline bool CAAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue)
+{
+	return CAAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicIncrement32(volatile int32_t* theValue)
+{
+	return CAAtomicIncrement32((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicDecrement32(volatile int32_t* theValue)
+{
+	return CAAtomicDecrement32((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicIncrement32Barrier(volatile int32_t* theValue)
+{
+	return CAAtomicIncrement32Barrier((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
+{
+	return CAAtomicDecrement32Barrier((volatile SInt32 *)theValue);
+}
+#endif // __cplusplus && !__LP64__
+
+#if __LP64__
+inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
+{
+	return OSAtomicCompareAndSwap64Barrier(__oldValue, __newValue, __theValue);
+}
+#endif
+
+inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue, volatile void ** __theValue)
+{
+#if __LP64__
+	return CAAtomicCompareAndSwap64Barrier((int64_t)__oldValue, (int64_t)__newValue, (int64_t *)__theValue);
+#else
+	return CAAtomicCompareAndSwap32Barrier((int32_t)__oldValue, (int32_t)__newValue, (int32_t *)__theValue);
+#endif
+}
+
+/* Spinlocks.  These use memory barriers as required to synchronize access to shared
+ * memory protected by the lock.  The lock operation spins, but employs various strategies
+ * to back off if the lock is held, making it immune to most priority-inversion livelocks.
+ * The try operation immediately returns false if the lock was held, true if it took the
+ * lock.  The convention is that unlocked is zero, locked is nonzero.
+ */
+#define	CA_SPINLOCK_INIT    0
+
+typedef int32_t CASpinLock;
+
+bool    CASpinLockTry( volatile CASpinLock *__lock );
+void    CASpinLockLock( volatile CASpinLock *__lock );
+void    CASpinLockUnlock( volatile CASpinLock *__lock );
+
+inline void    CASpinLockLock( volatile CASpinLock *__lock )
+{
+#if TARGET_OS_MAC
+	OSSpinLockLock(__lock);
+#else
+	while (CAAtomicTestAndSetBarrier(0, (void*)__lock))
+		usleep(1000); // ???
+#endif
+}
+
+inline void    CASpinLockUnlock( volatile CASpinLock *__lock )
+{
+#if TARGET_OS_MAC
+	OSSpinLockUnlock(__lock);
+#else
+	CAAtomicTestAndClearBarrier(0, (void*)__lock);
+#endif
+}
+
+inline bool    CASpinLockTry( volatile CASpinLock *__lock )
+{
+#if TARGET_OS_MAC
+	return OSSpinLockTry(__lock);
+#else
+	return (CAAtomicTestAndSetBarrier(0, (void*)__lock) == 0);
+#endif
+}
+
+
+#endif // __CAAtomic_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h b/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h
new file mode 100644
index 0000000..8d40fc5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h
@@ -0,0 +1,239 @@
+/*
+     File: CAAtomicStack.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAAtomicStack_h__
+#define __CAAtomicStack_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <libkern/OSAtomic.h>
+#else
+	#include <CAAtomic.h>
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
+	#include <CoreServices/CoreServices.h>
+#endif
+
+//  linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically
+//  class T must implement T *& next().
+template <class T>
+class TAtomicStack {
+public:
+	TAtomicStack() : mHead(NULL) { }
+	
+	// non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
+	void	push_NA(T *item)
+	{
+		item->next() = mHead;
+		mHead = item;
+	}
+	
+	T *		pop_NA()
+	{
+		T *result = mHead;
+		if (result)
+			mHead = result->next();
+		return result;
+	}
+	
+	bool	empty() const { return mHead == NULL; }
+	
+	T *		head() { return mHead; }
+	
+	// atomic routines
+	void	push_atomic(T *item)
+	{
+		T *head_;
+		do {
+			head_ = mHead;
+			item->next() = head_;
+		} while (!compare_and_swap(head_, item, &mHead));
+	}
+	
+	void	push_multiple_atomic(T *item)
+		// pushes entire linked list headed by item
+	{
+		T *head_, *p = item, *tail;
+		// find the last one -- when done, it will be linked to head
+		do {
+			tail = p;
+			p = p->next();
+		} while (p);
+		do {
+			head_ = mHead;
+			tail->next() = head_;
+		} while (!compare_and_swap(head_, item, &mHead));
+	}
+	
+	T *		pop_atomic_single_reader()
+		// this may only be used when only one thread may potentially pop from the stack.
+		// if multiple threads may pop, this suffers from the ABA problem.
+		// <rdar://problem/4606346> TAtomicStack suffers from the ABA problem
+	{
+		T *result;
+		do {
+			if ((result = mHead) == NULL)
+				break;
+		} while (!compare_and_swap(result, result->next(), &mHead));
+		return result;
+	}
+	
+	T *		pop_atomic()
+		// This is inefficient for large linked lists.
+		// prefer pop_all() to a series of calls to pop_atomic.
+		// push_multiple_atomic has to traverse the entire list.
+	{
+		T *result = pop_all();
+		if (result) {
+			T *next = result->next();
+			if (next)
+				// push all the remaining items back onto the stack
+				push_multiple_atomic(next);
+		}
+		return result;
+	}
+	
+	T *		pop_all()
+	{
+		T *result;
+		do {
+			if ((result = mHead) == NULL)
+				break;
+		} while (!compare_and_swap(result, NULL, &mHead));
+		return result;
+	}
+	
+	T*		pop_all_reversed()
+	{
+		TAtomicStack<T> reversed;
+		T *p = pop_all(), *next;
+		while (p != NULL) {
+			next = p->next();
+			reversed.push_NA(p);
+			p = next;
+		}
+		return reversed.mHead;
+	}
+	
+	static bool	compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
+	{
+#if TARGET_OS_MAC
+	#if __LP64__
+			return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
+	#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+			return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue);
+	#else
+			return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+	#endif
+#else
+			//return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+			return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
+#endif
+	}
+	
+protected:
+	T *		mHead;
+};
+
+#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32)
+#include <libkern/OSAtomic.h>
+
+class CAAtomicStack {
+public:
+	CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) {
+		/*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
+		mHead.opaque1 = 0; mHead.opaque2 = 0;
+	}
+	// a subset of the above
+	void	push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); }
+	void	push_NA(void *p) { push_atomic(p); }
+
+	void *	pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); }
+	void *	pop_atomic_single_reader() { return pop_atomic(); }
+	void *	pop_NA() { return pop_atomic(); }
+	
+private:
+	OSQueueHead		mHead;
+	size_t			mNextPtrOffset;
+};
+
+// a more efficient subset of TAtomicStack using OSQueue.
+template <class T>
+class TAtomicStack2 {
+public:
+	TAtomicStack2() {
+		/*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
+		mHead.opaque1 = 0; mHead.opaque2 = 0;
+		mNextPtrOffset = -1;
+	}
+	void	push_atomic(T *item) {
+		if (mNextPtrOffset < 0) {
+			T **pnext = &item->next();	// hack around offsetof not working with C++
+			mNextPtrOffset = (Byte *)pnext - (Byte *)item;
+		}
+		OSAtomicEnqueue(&mHead, item, mNextPtrOffset);
+	}
+	void	push_NA(T *item) { push_atomic(item); }
+
+	T *		pop_atomic() { return (T *)OSAtomicDequeue(&mHead, mNextPtrOffset); }
+	T *		pop_atomic_single_reader() { return pop_atomic(); }
+	T *		pop_NA() { return pop_atomic(); }
+	
+	// caution: do not try to implement pop_all_reversed here. the writer could add new elements
+	// while the reader is trying to pop old ones!
+	
+private:
+	OSQueueHead		mHead;
+	ssize_t			mNextPtrOffset;
+};
+
+#else
+
+#define TAtomicStack2 TAtomicStack
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32
+
+#endif // __CAAtomicStack_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp
new file mode 100644
index 0000000..d3644ed
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp
@@ -0,0 +1,239 @@
+/*
+     File: CAAudioBufferList.cpp
+ Abstract: CAAudioBufferList.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CAAudioBufferList.h"
+#include "CADebugMacros.h"
+#include "CALogMacros.h"
+#include <stdlib.h>
+#include <string.h>
+
+//=============================================================================
+//	CAAudioBufferList
+//=============================================================================
+
+AudioBufferList*	CAAudioBufferList::Create(UInt32 inNumberBuffers)
+{
+	UInt32 theSize = CalculateByteSize(inNumberBuffers);
+	AudioBufferList* theAnswer = static_cast<AudioBufferList*>(calloc(1, theSize));
+	if(theAnswer != NULL)
+	{
+		theAnswer->mNumberBuffers = inNumberBuffers;
+	}
+	return theAnswer;
+}
+
+void	CAAudioBufferList::Destroy(AudioBufferList* inBufferList)
+{
+	free(inBufferList);
+}
+
+UInt32	CAAudioBufferList::CalculateByteSize(UInt32 inNumberBuffers)
+{
+	UInt32 theSize = SizeOf32(AudioBufferList) - SizeOf32(AudioBuffer);
+	theSize += inNumberBuffers * SizeOf32(AudioBuffer);
+	return theSize;
+}
+
+UInt32	CAAudioBufferList::GetTotalNumberChannels(const AudioBufferList& inBufferList)
+{
+	UInt32 theAnswer = 0;
+	
+	for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+	{
+		theAnswer += inBufferList.mBuffers[theIndex].mNumberChannels;
+	}
+	
+	return theAnswer;
+}
+
+bool	CAAudioBufferList::GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel)
+{
+	bool theAnswer = false;
+	UInt32 theIndex = 0;
+	
+	while((theIndex < inBufferList.mNumberBuffers) && (inChannel >= inBufferList.mBuffers[theIndex].mNumberChannels))
+	{
+		inChannel -= inBufferList.mBuffers[theIndex].mNumberChannels;
+		++theIndex;
+	}
+	
+	if(theIndex < inBufferList.mNumberBuffers)
+	{
+		outBufferNumber = theIndex;
+		outBufferChannel = inChannel;
+		theAnswer = true;
+	}
+	
+	return theAnswer;
+}
+
+void	CAAudioBufferList::Clear(AudioBufferList& outBufferList)
+{
+	//	assumes that "0" is actually the 0 value for this stream format
+	for(UInt32 theBufferIndex = 0; theBufferIndex < outBufferList.mNumberBuffers; ++theBufferIndex)
+	{
+		if(outBufferList.mBuffers[theBufferIndex].mData != NULL)
+		{
+			memset(outBufferList.mBuffers[theBufferIndex].mData, 0, outBufferList.mBuffers[theBufferIndex].mDataByteSize);
+		}
+	}
+}
+
+void	CAAudioBufferList::Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel)
+{
+	//  This is a brute force copy method that can handle ABL's that have different buffer layouts
+	//  This means that this method is probably not the fastest way to do this for all cases.
+	//  This method also assumes that both the source and destination sample formats are Float32
+
+	UInt32 theInputChannel = inStartingSourceChannel;
+	UInt32 theNumberInputChannels = GetTotalNumberChannels(inSource);
+	UInt32 theOutputChannel = inStartingDestinationChannel;
+	UInt32 theNumberOutputChannels = GetTotalNumberChannels(outDestination);
+	
+	UInt32 theInputBufferIndex = 0;
+	UInt32 theInputBufferChannel = 0;
+	UInt32 theOutputBufferIndex = 0;
+	UInt32 theOutputBufferChannel = 0;
+	while((theInputChannel < theNumberInputChannels) && (theOutputChannel < theNumberOutputChannels))
+	{
+		GetBufferForChannel(inSource, theInputChannel, theInputBufferIndex, theInputBufferChannel);
+		
+		GetBufferForChannel(inSource, theOutputChannel, theOutputBufferIndex, theOutputBufferChannel);
+		
+		CopyChannel(inSource.mBuffers[theInputBufferIndex], theInputBufferChannel, outDestination.mBuffers[theOutputBufferIndex], theOutputBufferChannel);
+		
+		++theInputChannel;
+		++theOutputChannel;
+	}
+}
+
+void	CAAudioBufferList::CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel)
+{
+	//  set up the stuff for the loop
+	UInt32 theNumberFramesToCopy = outDestination.mDataByteSize / (outDestination.mNumberChannels * SizeOf32(Float32));
+	const Float32* theSource = static_cast<const Float32*>(inSource.mData);
+	Float32* theDestination = static_cast<Float32*>(outDestination.mData);
+	
+	//  loop through the data and copy the samples
+	while(theNumberFramesToCopy > 0)
+	{
+		//  copy the data
+		theDestination[inDestinationChannel] = theSource[inSourceChannel];
+		
+		//  adjust the pointers
+		--theNumberFramesToCopy;
+		theSource += inSource.mNumberChannels;
+		theDestination += outDestination.mNumberChannels;
+	}
+}
+
+void	CAAudioBufferList::Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList)
+{
+	//	assumes that the buffers are Float32 samples and the listst have the same layout
+	//	this is a lame algorithm, by the way. it could at least be unrolled a couple of times
+	for(UInt32 theBufferIndex = 0; theBufferIndex < ioSummedBufferList.mNumberBuffers; ++theBufferIndex)
+	{
+		Float32* theSourceBuffer = static_cast<Float32*>(inSourceBufferList.mBuffers[theBufferIndex].mData);
+		Float32* theSummedBuffer = static_cast<Float32*>(ioSummedBufferList.mBuffers[theBufferIndex].mData);
+		UInt32 theNumberSamplesToMix = ioSummedBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(Float32);
+		if((theSourceBuffer != NULL) && (theSummedBuffer != NULL) && (theNumberSamplesToMix > 0))
+		{
+			while(theNumberSamplesToMix > 0)
+			{
+				*theSummedBuffer += *theSourceBuffer;
+				++theSummedBuffer;
+				++theSourceBuffer;
+				--theNumberSamplesToMix;
+			}
+		}
+	}
+}
+
+bool	CAAudioBufferList::HasData(AudioBufferList& inBufferList)
+{
+	bool hasData = false;
+	for(UInt32 theBufferIndex = 0; !hasData && (theBufferIndex < inBufferList.mNumberBuffers); ++theBufferIndex)
+	{
+		if(inBufferList.mBuffers[theBufferIndex].mData != NULL)
+		{
+			UInt32* theBuffer = (UInt32*)inBufferList.mBuffers[theBufferIndex].mData;
+			UInt32 theNumberSamples = inBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(UInt32);
+			for(UInt32 theSampleIndex = 0; !hasData && (theSampleIndex < theNumberSamples); ++theSampleIndex)
+			{
+				hasData = theBuffer[theSampleIndex] != 0;
+			}
+		}
+	}
+	return hasData;
+}
+
+#if CoreAudio_Debug
+void	CAAudioBufferList::PrintToLog(const AudioBufferList& inBufferList)
+{
+	PrintInt("  Number streams: ", inBufferList.mNumberBuffers);
+	
+	for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+	{
+		PrintIndexedInt("  Channels in stream", theIndex + 1, inBufferList.mBuffers[theIndex].mNumberChannels);
+		PrintIndexedInt("  Buffer size of stream", theIndex + 1, inBufferList.mBuffers[theIndex].mDataByteSize);
+	}
+}
+#endif
+
+const AudioBufferList*	CAAudioBufferList::GetEmptyBufferList()
+{
+	static bool	sInitializer = false;
+	static AudioBufferList	sEmptyABL;
+	if(!sInitializer)
+	{
+		memset(&sEmptyABL, 0, sizeof(AudioBufferList));
+	}
+	return &sEmptyABL;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h
new file mode 100644
index 0000000..70614f3
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h
@@ -0,0 +1,108 @@
+/*
+     File: CAAudioBufferList.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAAudioBufferList_h__)
+#define __CAAudioBufferList_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+#include "CAException.h"
+#include "CADebugMacros.h"
+
+//=============================================================================
+//	Types
+//=============================================================================
+
+typedef AudioBufferList*	AudioBufferListPtr;
+
+//=============================================================================
+//	CAAudioBufferList
+//=============================================================================
+
+struct	CAAudioBufferList
+{
+
+//	Construction/Destruction
+public:
+	static AudioBufferList*	Create(UInt32 inNumberBuffers);
+	static void				Destroy(AudioBufferList* inBufferList);
+	static UInt32			CalculateByteSize(UInt32 inNumberBuffers);
+
+//	Operations
+public:
+	static UInt32			GetTotalNumberChannels(const AudioBufferList& inBufferList);
+	static bool				GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel);
+	static void				Clear(AudioBufferList& outBufferList);
+	static void				Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel);
+	static void				CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel);
+	static void				Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList);
+	static bool				HasData(AudioBufferList& inBufferList);
+#if	CoreAudio_Debug
+	static void				PrintToLog(const AudioBufferList& inBufferList);
+#endif
+
+	static const AudioBufferList*	GetEmptyBufferList();
+
+};
+
+// Declare a variably-sized AudioBufferList on the stack
+#define STACK_ABL(name, nbufs) \
+	ThrowIf(nbufs < 1 || nbufs > 64, CAException(kAudio_ParamError), "STACK_ABL: invalid number of buffers") \
+	const size_t name##_ByteSize = sizeof(AudioBufferList) + (nbufs - 1) * sizeof(AudioBuffer); \
+	AudioBufferList &name = *(AudioBufferList *)alloca(name##_ByteSize); \
+	name.mNumberBuffers = nbufs;
+
+
+#endif
diff --git a/libs/appleutility/CAAudioChannelLayout.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp
similarity index 52%
copy from libs/appleutility/CAAudioChannelLayout.cpp
copy to libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp
index 5ca0b76..7475359 100644
--- a/libs/appleutility/CAAudioChannelLayout.cpp
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp
@@ -1,51 +1,56 @@
-/*	Copyright: 	© Copyright 2005 Apple Computer, Inc. All rights reserved.
-
-	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-			("Apple") in consideration of your agreement to the following terms, and your
-			use, installation, modification or redistribution of this Apple software
-			constitutes acceptance of these terms.  If you do not agree with these terms,
-			please do not use, install, modify or redistribute this Apple software.
-
-			In consideration of your agreement to abide by the following terms, and subject
-			to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
-			copyrights in this original Apple software (the "Apple Software"), to use,
-			reproduce, modify and redistribute the Apple Software, with or without
-			modifications, in source and/or binary forms; provided that if you redistribute
-			the Apple Software in its entirety and without modifications, you must retain
-			this notice and the following text and disclaimers in all such redistributions of
-			the Apple Software.  Neither the name, trademarks, service marks or logos of
-			Apple Computer, Inc. may be used to endorse or promote products derived from the
-			Apple Software without specific prior written permission from Apple.  Except as
-			expressly stated in this notice, no other rights or licenses, express or implied,
-			are granted by Apple herein, including but not limited to any patent rights that
-			may be infringed by your derivative works or by other works in which the Apple
-			Software may be incorporated.
-
-			The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-			WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-			WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-			PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-			COMBINATION WITH YOUR PRODUCTS.
-
-			IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-			CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-			GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-			ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-			OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-			(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-			ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/*
+     File: CAAudioChannelLayout.cpp
+ Abstract: CAAudioChannelLayout.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
 */
-/*=============================================================================
-	CAAudioChannelLayout.cpp
-
-=============================================================================*/
-
 //=============================================================================
 //	Includes
 //=============================================================================
 
 //	Self Include
 #include "CAAudioChannelLayout.h"
+#include "CAAutoDisposer.h"
 #include <stdlib.h>
 #include <string.h>
 
@@ -56,7 +61,7 @@
 AudioChannelLayout*	CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions)
 {
 	UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions);
-	AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(calloc(1, theSize));
+	AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(CA_calloc(1, theSize));
 	if(theAnswer != NULL)
 	{
 		SetAllToUnknown(*theAnswer, inNumberChannelDescriptions);
@@ -90,13 +95,18 @@ bool	operator== (const AudioChannelLayout &x, const AudioChannelLayout &y)
 	// (this may be too strict a comparison if all you care about are matching layout tags)
 	UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
 	UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
-
+	
 	if (theSize1 != theSize2)
 		return false;
-
+		
 	return !memcmp (&x, &y, theSize1);
 }
 
+bool	operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y)
+{
+	return !(x == y);
+}
+
 // counting the one bits in a word
 inline UInt32 CountOnes(UInt32 x)
 {
@@ -115,7 +125,7 @@ UInt32	CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout)
 {
 	if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
 		return inLayout.mNumberChannelDescriptions;
-
+	
 	if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
 		return CountOnes (inLayout.mChannelBitmap);
 
@@ -124,14 +134,19 @@ UInt32	CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout)
 
 void 	CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout)
 {
-	fprintf (file, "\tTag=0x%lX, ", layout->mChannelLayoutTag);
+	if (layout == NULL) 
+	{
+		fprintf (file, "\tNULL layout\n");
+		return;
+	}
+	fprintf (file, "\tTag=0x%X, ", (int)layout->mChannelLayoutTag);
 	if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
-		fprintf (file, "Using Bitmap:0x%lX\n", layout->mChannelBitmap);
+		fprintf (file, "Using Bitmap:0x%X\n", (int)layout->mChannelBitmap);
 	else {
-		fprintf (file, "Num Chan Descs=%ld\n", layout->mNumberChannelDescriptions);
+		fprintf (file, "Num Chan Descs=%d\n", (int)layout->mNumberChannelDescriptions);
 		const AudioChannelDescription *desc = layout->mChannelDescriptions;
 		for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) {
-			fprintf (file, "\t\tLabel=%ld, Flags=0x%lX, ", desc->mChannelLabel, desc->mChannelFlags);
+			fprintf (file, "\t\tLabel=%d, Flags=0x%X, ", (int)desc->mChannelLabel, (int)desc->mChannelFlags);
 			fprintf (file, "[az=%f,el=%f,dist=%f]\n", desc->mCoordinates[0], desc->mCoordinates[1], desc->mCoordinates[2]);
 		}
 	}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h
new file mode 100644
index 0000000..4307054
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h
@@ -0,0 +1,199 @@
+/*
+     File: CAAudioChannelLayout.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAAudioChannelLayout_h__)
+#define __CAAudioChannelLayout_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include <CoreAudioTypes.h>
+	#include <CoreFoundation.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "CADebugMacros.h"
+#include "CAAutoDisposer.h"
+
+#if !HAL_Build
+	#include "CAReferenceCounted.h"
+#endif
+
+//=============================================================================
+//	CAAudioChannelLayout
+//=============================================================================
+
+bool	operator== (const AudioChannelLayout &x, const AudioChannelLayout &y);
+bool	operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y);
+
+extern "C" void 	CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout);
+
+class CAAudioChannelLayout
+{
+//	static Construction/Destruction
+public:
+	static AudioChannelLayout*	Create(UInt32 inNumberChannelDescriptions);
+	static void					Destroy(AudioChannelLayout* inChannelLayout);
+	static UInt32				CalculateByteSize(UInt32 inNumberChannelDescriptions) { 
+									return SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription) + (inNumberChannelDescriptions * SizeOf32(AudioChannelDescription));
+								}
+	static void					SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions);
+	static UInt32				NumberChannels(const AudioChannelLayout& inLayout);
+	
+#if !HAL_Build
+// object methods	
+public:
+								CAAudioChannelLayout ();
+
+								CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
+									// if inChooseSurround is false, then symmetrical speaker arrangements
+									// are chosen in place of surround layouts if there is a choice
+									// This call chooses layouts based on the expected defaults in 
+									// AudioUnit usage
+								CAAudioChannelLayout (AudioChannelLayoutTag inTag);
+								CAAudioChannelLayout (const CAAudioChannelLayout &c);
+								CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout);
+								~CAAudioChannelLayout();
+	
+	CAAudioChannelLayout&		operator= (const AudioChannelLayout* inChannelLayout);
+	CAAudioChannelLayout&		operator= (const CAAudioChannelLayout& c);
+	bool						operator== (const CAAudioChannelLayout &c) const;
+	bool						operator!= (const CAAudioChannelLayout &c) const;
+
+	void						SetWithTag(AudioChannelLayoutTag inTag);
+
+	bool						IsValid() const { return NumberChannels() > 0; }
+	UInt32						Size() const { return mLayout ? mLayout->Size() : 0; }
+	
+	UInt32						NumberChannels() const { return mLayout ? mLayout->NumberChannels() : 0; }
+	
+	AudioChannelLayoutTag		Tag() const { return Layout().mChannelLayoutTag; }
+	const AudioChannelLayout&	Layout() const { return mLayout->Layout(); }
+	operator const AudioChannelLayout *() const { return &Layout(); }
+	
+	void						Print () const { Print (stdout); }
+	void						Print (FILE* file) const;
+
+	OSStatus					Save (CFPropertyListRef *outData) const;
+	OSStatus					Restore (CFPropertyListRef &inData);
+	
+private:
+	class RefCountedLayout : public CAReferenceCounted {
+		void *	operator new(size_t /* size */, size_t aclSize)
+		{
+			return CA_malloc(sizeof(RefCountedLayout) - sizeof(AudioChannelLayout) + aclSize);
+		}
+		
+		void	operator delete(void *mem)
+		{
+			free(mem);
+		}
+		
+		
+		RefCountedLayout(UInt32 inDataSize) :
+			mByteSize(inDataSize)
+		{ 
+			memset(&mACL, 0, inDataSize);
+		}
+		
+	public:
+		static RefCountedLayout *CreateWithNumberChannelDescriptions(unsigned nChannels) {
+								size_t size = CAAudioChannelLayout::CalculateByteSize(nChannels);
+								return new(size) RefCountedLayout((UInt32)size);
+							}
+
+		static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) {
+								size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions);
+								RefCountedLayout *acl = new(size) RefCountedLayout((UInt32)size);
+								memcpy(&acl->mACL, layout, size);
+								return acl;
+							}
+		static RefCountedLayout *CreateWithLayoutTag(AudioChannelLayoutTag layoutTag) {
+								RefCountedLayout *acl = CreateWithNumberChannelDescriptions(0);
+								acl->mACL.mChannelLayoutTag = layoutTag;
+								return acl;
+							}
+	
+		const AudioChannelLayout & 	Layout() const { return mACL; }
+		
+		UInt32						Size () const { return mByteSize; }
+		
+		UInt32						NumberChannels() { return CAAudioChannelLayout::NumberChannels(Layout()); }
+		
+	private:
+		const UInt32		mByteSize;
+		AudioChannelLayout 	mACL;
+		// * * * mACL is variable length and thus must be last * * *
+		
+			// only the constructors can change the actual state of the layout
+		friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
+		friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData);
+		friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout);
+		friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag);
+		
+		AudioChannelLayout * 	GetLayout() { return &mACL; }
+	
+	private:
+		// prohibited methods: private and unimplemented.
+		RefCountedLayout();
+		RefCountedLayout(const RefCountedLayout& c);
+		RefCountedLayout& operator=(const RefCountedLayout& c);
+	};
+	
+	RefCountedLayout		*mLayout;
+#endif	//	HAL_Build
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp
new file mode 100644
index 0000000..009d4b3
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp
@@ -0,0 +1,210 @@
+/*
+     File: CAAudioChannelLayoutObject.cpp
+ Abstract: CAAudioChannelLayoutObject.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAAudioChannelLayout.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioToolbox/AudioFormat.h>
+#else
+	#include <AudioFormat.h>
+#endif
+
+CAAudioChannelLayout::CAAudioChannelLayout ()
+{
+	mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround)
+{		
+		// this chooses default layouts based on the number of channels...
+	AudioChannelLayoutTag tag;
+	
+	switch (inNumberChannels) 
+	{
+		default:
+			// here we have a "broken" layout, in the sense that we haven't any idea how to lay this out
+			mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(inNumberChannels);
+			SetAllToUnknown(*mLayout->GetLayout(), inNumberChannels);
+			return; // don't fall into the tag case
+		case 1:
+			tag = kAudioChannelLayoutTag_Mono;
+			break;
+		case 2:
+			tag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo;
+			break;
+		case 4:
+			tag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4;
+			break;
+		case 5:
+			tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5;
+			break;
+		case 6:
+			tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6;
+			break;
+		case 7:
+			tag = kAudioChannelLayoutTag_AudioUnit_7_0;
+			break;
+		case 8:
+			tag = kAudioChannelLayoutTag_AudioUnit_8;
+			break;
+	}
+	
+	mLayout = RefCountedLayout::CreateWithLayoutTag(tag);
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag)
+	: mLayout(NULL)
+{
+	SetWithTag(inLayoutTag);
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c)
+	: mLayout(NULL)
+{
+	*this = c;
+}
+
+
+//=============================================================================
+//	CAAudioChannelLayout::AudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout)
+	: mLayout(NULL)
+{
+	*this = inChannelLayout;
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::~CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::~CAAudioChannelLayout ()
+{
+	if (mLayout) {
+		mLayout->release();
+		mLayout = NULL;
+	}
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c)
+{
+	if (mLayout != c.mLayout) {
+		if (mLayout)
+			mLayout->release();
+	
+		if ((mLayout = c.mLayout) != NULL)
+			mLayout->retain();
+	}
+	
+	return *this;
+}
+
+CAAudioChannelLayout&	CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout)
+{
+	if (mLayout && &mLayout->Layout() == inChannelLayout)
+		return *this;
+		
+	if (mLayout)
+		mLayout->release();
+
+	if (inChannelLayout == NULL) 
+	{
+		mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
+	}
+	else
+	{
+		mLayout = RefCountedLayout::CreateWithLayout(inChannelLayout);
+	}
+	return *this;
+}
+
+void	CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag)
+{
+	if (mLayout)
+		mLayout->release();
+	
+	mLayout = RefCountedLayout::CreateWithLayoutTag(inTag);
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::operator==
+//=============================================================================
+bool		CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const
+{
+	if (mLayout == c.mLayout)
+		return true;
+	return Layout() == c.Layout();
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::operator!=
+//=============================================================================
+bool		CAAudioChannelLayout::operator!= (const CAAudioChannelLayout &c) const
+{
+	if (mLayout == c.mLayout)
+		return false;
+
+	return !(Layout() == c.Layout());
+}
+
+//=============================================================================
+//	CAAudioChannelLayout::Print
+//=============================================================================
+void		CAAudioChannelLayout::Print (FILE* file) const
+{
+	CAShowAudioChannelLayout (file, &Layout());
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp
new file mode 100644
index 0000000..ce2efea
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp
@@ -0,0 +1,424 @@
+/*
+     File: CAAudioFileFormats.cpp
+ Abstract: CAAudioFileFormats.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAAudioFileFormats.h"
+#include <algorithm>
+#include <ctype.h>
+
+CAAudioFileFormats *CAAudioFileFormats::sInstance = NULL;
+
+CAAudioFileFormats *CAAudioFileFormats::Instance(bool loadDataFormats)
+{
+	if (sInstance == NULL)
+		sInstance = new CAAudioFileFormats(loadDataFormats);
+	return sInstance;
+}
+
+/*
+class CompareFileFormatNames {
+public:
+	bool	operator() (const CAAudioFileFormats::FileFormatInfo &a, const CAAudioFileFormats::FileFormatInfo &b)
+	{
+		return CFStringCompare(a.mFileTypeName, b.mFileTypeName, 
+			kCFCompareCaseInsensitive | kCFCompareLocalized) == kCFCompareLessThan;
+	}
+};*/
+
+static int CompareFileFormatNames(const void *va, const void *vb)
+{
+	CAAudioFileFormats::FileFormatInfo  *a = (CAAudioFileFormats::FileFormatInfo *)va, 
+										*b = (CAAudioFileFormats::FileFormatInfo *)vb;
+	return CFStringCompare(a->mFileTypeName, b->mFileTypeName, 
+		kCFCompareCaseInsensitive | kCFCompareLocalized);
+}
+
+CAAudioFileFormats::CAAudioFileFormats(bool loadDataFormats) : 
+	mNumFileFormats(0), mFileFormats(NULL)
+{
+	OSStatus err;
+	UInt32 size;
+	UInt32 *fileTypes = NULL;
+	
+	// get all file types
+	err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size);
+	if (err != noErr) goto bail;
+	mNumFileFormats = size / sizeof(UInt32);
+	mFileFormats = new FileFormatInfo[mNumFileFormats];
+	fileTypes = new UInt32[mNumFileFormats];
+	err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size, fileTypes);
+	if (err != noErr) goto bail;
+	
+	// get info for each file type
+	for (int i = 0; i < mNumFileFormats; ++i) {
+		FileFormatInfo *ffi = &mFileFormats[i];
+		OSType filetype = fileTypes[i];
+
+		ffi->mFileTypeID = filetype;
+		
+		// file type name
+		ffi->mFileTypeName = NULL;
+		size = sizeof(CFStringRef);
+		err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_FileTypeName, sizeof(UInt32), &filetype, &size, &ffi->mFileTypeName);
+		if (err == noErr && ffi->mFileTypeName)
+			CFRetain(ffi->mFileTypeName);
+		
+		// file extensions
+		size = sizeof(CFArrayRef);
+		err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_ExtensionsForType,
+			sizeof(OSType), &filetype, &size, &ffi->mExtensions);
+		if (err)
+			ffi->mExtensions = NULL;
+		
+		// file data formats
+		ffi->mNumDataFormats = 0;
+		ffi->mDataFormats = NULL;
+		
+		if (loadDataFormats)
+			ffi->LoadDataFormats();
+	}
+
+	// sort file formats by name
+	qsort(mFileFormats, mNumFileFormats, sizeof(FileFormatInfo), CompareFileFormatNames);
+bail:
+	delete[] fileTypes;
+}
+
+void	CAAudioFileFormats::FileFormatInfo::LoadDataFormats()
+{
+	if (mDataFormats != NULL) return;
+	
+	UInt32 *writableFormats = NULL, *readableFormats = NULL;
+	int nWritableFormats, nReadableFormats;
+	// get all writable formats
+	UInt32 size;
+	OSStatus err = AudioFormatGetPropertyInfo(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size);
+	if (err != noErr) goto bail;
+	nWritableFormats = size / sizeof(UInt32);
+	writableFormats = new UInt32[nWritableFormats];
+	err = AudioFormatGetProperty(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size, writableFormats);
+	if (err != noErr) goto bail;
+	
+	// get all readable formats
+	err = AudioFormatGetPropertyInfo(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size);
+	if (err != noErr) goto bail;
+	nReadableFormats = size / sizeof(UInt32);
+	readableFormats = new UInt32[nReadableFormats];
+	err = AudioFormatGetProperty(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size, readableFormats);
+	if (err != noErr) goto bail;
+	
+	err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableFormatIDs, sizeof(UInt32), &mFileTypeID, &size);
+	if (err == noErr) {
+		mNumDataFormats = size / sizeof(OSType);
+		OSType *formatIDs = new OSType[mNumDataFormats];
+		err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableFormatIDs,
+			sizeof(UInt32), &mFileTypeID, &size, formatIDs);
+		if (err == noErr) {
+			mDataFormats = new DataFormatInfo[mNumDataFormats];
+			for (int j = 0; j < mNumDataFormats; ++j) {
+				int k;
+				bool anyBigEndian = false, anyLittleEndian = false;
+				DataFormatInfo *dfi = &mDataFormats[j];
+				dfi->mFormatID = formatIDs[j];
+				dfi->mReadable = (dfi->mFormatID == kAudioFormatLinearPCM);
+				dfi->mWritable = (dfi->mFormatID == kAudioFormatLinearPCM);
+				for (k = 0; k < nReadableFormats; ++k)
+					if (readableFormats[k] == dfi->mFormatID) {
+						dfi->mReadable = true;
+						break;
+					}
+				for (k = 0; k < nWritableFormats; ++k)
+					if (writableFormats[k] == dfi->mFormatID) {
+						dfi->mWritable = true;
+						break;
+					}
+				
+				dfi->mNumVariants = 0;
+				AudioFileTypeAndFormatID tf = { mFileTypeID, dfi->mFormatID };
+				err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat,
+					sizeof(AudioFileTypeAndFormatID), &tf, &size);
+				if (err == noErr) {
+					dfi->mNumVariants = size / sizeof(AudioStreamBasicDescription);
+					dfi->mVariants = new AudioStreamBasicDescription[dfi->mNumVariants];
+					err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat,
+						sizeof(AudioFileTypeAndFormatID), &tf, &size, dfi->mVariants);
+					if (err) {
+						dfi->mNumVariants = 0;
+						delete[] dfi->mVariants;
+						dfi->mVariants = NULL;
+					} else {
+						for (k = 0; k < dfi->mNumVariants; ++k) {
+							AudioStreamBasicDescription *desc = &dfi->mVariants[k];
+							if (desc->mBitsPerChannel > 8) {
+								if (desc->mFormatFlags & kAudioFormatFlagIsBigEndian)
+									anyBigEndian = true;
+								else
+									anyLittleEndian = true;
+							}
+						}
+					}
+				}
+				
+				dfi->mEitherEndianPCM = (anyBigEndian && anyLittleEndian);
+			}
+		}
+		delete[] formatIDs;
+	}
+bail:
+	delete[] readableFormats;
+	delete[] writableFormats;
+}
+
+// note that the outgoing format will have zero for the sample rate, channels per frame, bytesPerPacket, bytesPerFrame
+bool	CAAudioFileFormats::InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt)
+{
+	// if the file format only supports one data format
+	for (int i = 0; i < mNumFileFormats; ++i) {
+		FileFormatInfo *ffi = &mFileFormats[i];
+		ffi->LoadDataFormats();
+		if (ffi->mFileTypeID == filetype && ffi->mNumDataFormats > 0) {
+			DataFormatInfo *dfi = &ffi->mDataFormats[0];
+			if (ffi->mNumDataFormats > 1) {
+				// file can contain multiple data formats. Take PCM if it's there.
+				for (int j = 0; j < ffi->mNumDataFormats; ++j) {
+					if (ffi->mDataFormats[j].mFormatID == kAudioFormatLinearPCM) {
+						dfi = &ffi->mDataFormats[j];
+						break;
+					}
+				}
+			}
+			memset(&fmt, 0, sizeof(fmt));
+			fmt.mFormatID = dfi->mFormatID;
+			if (dfi->mNumVariants > 0) {
+				// take the first variant as a default
+				fmt = dfi->mVariants[0];
+				if (dfi->mNumVariants > 1 && dfi->mFormatID == kAudioFormatLinearPCM) {
+					// look for a 16-bit variant as a better default
+					for (int j = 0; j < dfi->mNumVariants; ++j) {
+						AudioStreamBasicDescription *desc = &dfi->mVariants[j];
+						if (desc->mBitsPerChannel == 16) {
+							fmt = *desc;
+							break;
+						}
+					}
+				}
+			}
+			return true;
+		}
+	}
+	return false;
+}
+
+bool	CAAudioFileFormats::InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype)
+{
+	bool result = false;
+	CFRange range = CFStringFind(filename, CFSTR("."), kCFCompareBackwards);
+	if (range.location == kCFNotFound) return false;
+	range.location += 1;
+	range.length = CFStringGetLength(filename) - range.location;
+	CFStringRef ext = CFStringCreateWithSubstring(NULL, filename, range);
+	for (int i = 0; i < mNumFileFormats; ++i) {
+		FileFormatInfo *ffi = &mFileFormats[i];
+		if (ffi->MatchExtension(ext)) {
+			filetype = ffi->mFileTypeID;
+			result = true;
+			break;
+		}
+	}
+	CFRelease(ext);
+	return result;
+}
+
+bool	CAAudioFileFormats::InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype)
+{
+	if (filename == NULL) return false;
+	CFStringRef cfname = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8);
+	bool result = InferFileFormatFromFilename(cfname, filetype);
+	CFRelease(cfname);
+	return result;
+}
+
+bool	CAAudioFileFormats::InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt, 
+			AudioFileTypeID &filetype)
+{
+	// if there's exactly one file format that supports this data format
+	FileFormatInfo *theFileFormat = NULL;
+	for (int i = 0; i < mNumFileFormats; ++i) {
+		FileFormatInfo *ffi = &mFileFormats[i];
+		ffi->LoadDataFormats();
+		DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats;
+		for ( ; dfi < dfiend; ++dfi)
+			if (dfi->mFormatID == fmt.mFormatID) {
+				if (theFileFormat != NULL)
+					return false;	// ambiguous
+				theFileFormat = ffi;	// got a candidate
+			}
+	}
+	if (theFileFormat == NULL)
+		return false;
+	filetype = theFileFormat->mFileTypeID;
+	return true;
+}
+
+bool	CAAudioFileFormats::IsKnownDataFormat(OSType dataFormat)
+{
+	for (int i = 0; i < mNumFileFormats; ++i) {
+		FileFormatInfo *ffi = &mFileFormats[i];
+		ffi->LoadDataFormats();
+		DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats;
+		for ( ; dfi < dfiend; ++dfi)
+			if (dfi->mFormatID == dataFormat)
+				return true;
+	}
+	return false;
+}
+
+CAAudioFileFormats::FileFormatInfo *	CAAudioFileFormats::FindFileFormat(UInt32 formatID)
+{
+	for (int i = 0; i < mNumFileFormats; ++i) {
+		FileFormatInfo *ffi = &mFileFormats[i];
+		if (ffi->mFileTypeID == formatID)
+			return ffi;
+	}
+	return NULL;
+}
+
+bool	CAAudioFileFormats::FileFormatInfo::AnyWritableFormats()
+{
+	LoadDataFormats();
+	DataFormatInfo *dfi = mDataFormats, *dfiend = dfi + mNumDataFormats;
+	for ( ; dfi < dfiend; ++dfi)
+		if (dfi->mWritable)
+			return true;
+	return false;
+}
+
+char *OSTypeToStr(char *buf, size_t bufsize, OSType t)
+{
+	if (bufsize > 0) {
+		char *p = buf, *pend = buf + bufsize;
+		char str[4] = {0}, *q = str;
+		*(UInt32 *)str = CFSwapInt32HostToBig(t);
+		for (int i = 0; i < 4 && p < pend; ++i) {
+			if (isprint(*q) && *q != '\\')
+				*p++ = *q++;
+			else {
+				snprintf(p, pend - p, "\\x%02x", *q++);
+				p += 4;
+			}
+		}
+		if (p >= pend) p = pend - 1;
+		*p = '\0';
+	}
+	return buf;
+}
+
+int		StrToOSType(const char *str, OSType &t)
+{
+	char buf[4];
+	const char *p = str;
+	int x;
+	for (int i = 0; i < 4; ++i) {
+		if (*p != '\\') {
+			if ((buf[i] = *p++) == '\0') {
+				// special-case for 'aac ': if we only got three characters, assume the last was a space
+				if (i == 3) {
+					--p;
+					buf[i] = ' ';
+					break;
+				}
+				goto fail;
+			}
+		} else {
+			if (*++p != 'x') goto fail;
+			if (sscanf(++p, "%02X", &x) != 1) goto fail;
+			buf[i] = x;
+			p += 2;
+		}
+	}
+	t = CFSwapInt32BigToHost(*(UInt32 *)buf);
+	return static_cast<int>(p - str);
+fail:
+	return 0;
+}
+
+#if DEBUG
+
+void	CAAudioFileFormats::DebugPrint()
+{
+	for (int i = 0; i < mNumFileFormats; ++i)
+		mFileFormats[i].DebugPrint();
+}
+
+void	CAAudioFileFormats::FileFormatInfo::DebugPrint()
+{
+	char ftype[20];
+	char ftypename[64];
+	CFStringGetCString(mFileTypeName, ftypename, sizeof(ftypename), kCFStringEncodingUTF8);
+	printf("File type: '%s' = %s\n  Extensions:", OSTypeToStr(ftype, sizeof(ftype), mFileTypeID), ftypename);
+	int i, n = NumberOfExtensions();
+	for (i = 0; i < n; ++i) {
+		GetExtension(i, ftype, sizeof(ftype));
+		printf(" .%s", ftype);
+	}
+	LoadDataFormats();
+	printf("\n  Formats:\n");
+	for (i = 0; i < mNumDataFormats; ++i)
+		mDataFormats[i].DebugPrint();
+}
+
+void	CAAudioFileFormats::DataFormatInfo::DebugPrint()
+{
+	char buf[20];
+	static const char *ny[] = { "not ", "" };
+	printf("    '%s': %sreadable %swritable\n", OSTypeToStr(buf, sizeof(buf), mFormatID), ny[mReadable], ny[mWritable]);
+	for (int i = 0; i < mNumVariants; ++i) {
+		CAStreamBasicDescription desc(mVariants[i]);
+		desc.PrintFormat(stdout, "      ", "");
+		//printf("        %d bytes/frame\n", desc.mBytesPerFrame);
+	}
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h
new file mode 100644
index 0000000..3d2f90f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h
@@ -0,0 +1,149 @@
+/*
+     File: CAAudioFileFormats.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAAudioFileFormats_h__
+#define __CAAudioFileFormats_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioToolbox/AudioToolbox.h>
+#else
+	#include <AudioToolbox.h>
+#endif
+#include "CAStreamBasicDescription.h"
+
+class CAAudioFileFormats {
+public:
+	enum { noErr = 0 };
+
+	struct DataFormatInfo {
+		DataFormatInfo() : mVariants(NULL) { }
+		~DataFormatInfo() { delete[] mVariants; }
+		
+		UInt32							mFormatID;
+		int								mNumVariants;
+		AudioStreamBasicDescription *	mVariants;
+		bool							mReadable;
+		bool							mWritable;
+		bool							mEitherEndianPCM;
+
+#if DEBUG
+		void	DebugPrint();
+#endif
+	};
+	
+	struct FileFormatInfo {
+		FileFormatInfo() : mFileTypeName(NULL), mExtensions(NULL), mDataFormats(NULL) { }
+		~FileFormatInfo() {
+			delete[] mDataFormats;
+			if (mFileTypeName)
+				CFRelease(mFileTypeName);
+			if (mExtensions)
+				CFRelease(mExtensions);
+		}
+		
+		AudioFileTypeID					mFileTypeID;
+		CFStringRef						mFileTypeName;
+		CFArrayRef						mExtensions;
+		int								mNumDataFormats;
+		DataFormatInfo *				mDataFormats;		// NULL until loaded!
+		
+		int		NumberOfExtensions() { return static_cast<int>(mExtensions ? CFArrayGetCount(mExtensions) : 0); }
+		char *	GetExtension(int index, char *buf, int buflen) {
+					CFStringRef cfext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, index);
+					CFStringGetCString(cfext, buf, buflen, kCFStringEncodingUTF8);
+					return buf;
+				}
+		bool	MatchExtension(CFStringRef testExt) {	// testExt should not include "."
+					CFIndex n = NumberOfExtensions();
+					for (CFIndex i = 0; i < n; ++i) {
+						CFStringRef ext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, i);
+						if (CFStringCompare(ext, testExt, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
+							return true;
+					}
+					return false;
+				}
+		bool	AnyWritableFormats();
+		void	LoadDataFormats();
+		
+#if DEBUG
+		void	DebugPrint();
+#endif
+	};
+	
+private:	// use Instance()
+	CAAudioFileFormats(bool loadDataFormats);
+	~CAAudioFileFormats();
+public:
+	
+	bool	InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt);
+	
+	bool	InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype);
+
+	bool	InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype);
+
+	bool	InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt, AudioFileTypeID &filetype);
+
+	bool	IsKnownDataFormat(UInt32 dataFormat);
+	
+#if DEBUG
+	void	DebugPrint();
+#endif
+
+	int					mNumFileFormats;
+	FileFormatInfo	*	mFileFormats;
+	
+	FileFormatInfo *	FindFileFormat(UInt32 formatID);
+
+	static CAAudioFileFormats *	Instance(bool loadDataFormats=true);
+
+private:	
+	static CAAudioFileFormats *	sInstance;
+};
+
+char *	OSTypeToStr(char *buf, size_t bufsize, UInt32 t);
+int		StrToOSType(const char *str, UInt32 &t);
+
+#endif // __CAAudioFileFormats_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp
new file mode 100644
index 0000000..0200ec9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp
@@ -0,0 +1,135 @@
+/*
+     File: CAAudioTimeStamp.cpp
+ Abstract: CAAudioTimeStamp.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CAAudioTimeStamp.h"
+
+//=============================================================================
+//	CAAudioTimeStamp
+//=============================================================================
+
+const AudioTimeStamp	CAAudioTimeStamp::kZero = { 0.0, 0, 0.0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0 };
+
+bool	operator<(const AudioTimeStamp& x, const AudioTimeStamp& y)
+{
+	bool	isLessThan = false;
+	bool	isDone = false;
+	
+	//	check the sample time
+	if(!isDone)
+	{
+		if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid))
+		{
+			isLessThan = x.mSampleTime < y.mSampleTime;
+			isDone = true;
+		}
+	}
+	
+	//	check the host time
+	if(!isDone)
+	{
+		if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid))
+		{
+			isLessThan = x.mHostTime < y.mHostTime;
+			isDone = true;
+		}
+	}
+	
+	//	check the word clock time
+	if(!isDone)
+	{
+		if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid))
+		{
+			isLessThan = x.mWordClockTime < y.mWordClockTime;
+			//	commented out to prevent this from being flagged as a dead store by the static analyzer
+			//isDone = true;
+		}
+	}
+	
+	return isLessThan;
+}
+
+bool	operator==(const AudioTimeStamp& x, const AudioTimeStamp& y)
+{
+	bool	isEqual = false;
+	bool	isDone = false;
+	
+	//	check the sample time
+	if(!isDone)
+	{
+		if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid))
+		{
+			isEqual = x.mSampleTime == y.mSampleTime;
+			isDone = true;
+		}
+	}
+	
+	//	check the host time
+	if(!isDone)
+	{
+		if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid))
+		{
+			isEqual = x.mHostTime == y.mHostTime;
+			isDone = true;
+		}
+	}
+	
+	//	check the word clock time
+	if(!isDone)
+	{
+		if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid))
+		{
+			isEqual = x.mWordClockTime == y.mWordClockTime;
+			//	commented out to prevent this from being flagged as a dead store by the static analyzer
+			//isDone = true;
+		}
+	}
+	
+	return isEqual;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h
new file mode 100644
index 0000000..9b8d6ab
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h
@@ -0,0 +1,97 @@
+/*
+     File: CAAudioTimeStamp.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAAudioTimeStamp_h__)
+#define __CAAudioTimeStamp_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+#include <string.h>
+
+//=============================================================================
+//	CAAudioTimeStamp
+//=============================================================================
+
+struct CAAudioTimeStamp
+:
+	public AudioTimeStamp
+{
+
+//	Construction/Destruction
+public:
+						CAAudioTimeStamp()																{ memset(this, 0, sizeof(AudioTimeStamp)); }
+						CAAudioTimeStamp(const AudioTimeStamp& v)										{ memcpy(this, &v, sizeof(AudioTimeStamp)); }
+						CAAudioTimeStamp(Float64 inSampleTime)											{ memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mFlags = kAudioTimeStampSampleTimeValid; }
+						CAAudioTimeStamp(UInt64 inHostTime)												{ memset(this, 0, sizeof(AudioTimeStamp)); mHostTime = inHostTime; mFlags = kAudioTimeStampHostTimeValid; }
+						CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime)						{ memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; }
+						CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime, Float64 inRateScalar)	{ memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mRateScalar = inRateScalar; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid | kAudioTimeStampRateScalarValid; }
+
+//	Assignment
+public:
+	CAAudioTimeStamp&	operator=(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); return *this; }
+
+//	Constants
+public:
+	static const AudioTimeStamp	kZero;
+
+};
+
+bool		operator<(const AudioTimeStamp& x, const AudioTimeStamp& y);
+bool		operator==(const AudioTimeStamp& x, const AudioTimeStamp& y);
+inline bool	operator!=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x == y); }
+inline bool	operator<=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return (x < y) || (x == y); }
+inline bool	operator>=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x < y); }
+inline bool	operator>(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !((x < y) || (x == y)); }
+
+#endif
diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp
similarity index 62%
copy from libs/appleutility/CAAudioUnit.cpp
copy to libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp
index f0b0890..53da5a1 100644
--- a/libs/appleutility/CAAudioUnit.cpp
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp
@@ -1,133 +1,153 @@
-/*	Copyright: 	© Copyright 2005 Apple Computer, Inc. All rights reserved.
-
-	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-			("Apple") in consideration of your agreement to the following terms, and your
-			use, installation, modification or redistribution of this Apple software
-			constitutes acceptance of these terms.  If you do not agree with these terms,
-			please do not use, install, modify or redistribute this Apple software.
-
-			In consideration of your agreement to abide by the following terms, and subject
-			to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
-			copyrights in this original Apple software (the "Apple Software"), to use,
-			reproduce, modify and redistribute the Apple Software, with or without
-			modifications, in source and/or binary forms; provided that if you redistribute
-			the Apple Software in its entirety and without modifications, you must retain
-			this notice and the following text and disclaimers in all such redistributions of
-			the Apple Software.  Neither the name, trademarks, service marks or logos of
-			Apple Computer, Inc. may be used to endorse or promote products derived from the
-			Apple Software without specific prior written permission from Apple.  Except as
-			expressly stated in this notice, no other rights or licenses, express or implied,
-			are granted by Apple herein, including but not limited to any patent rights that
-			may be infringed by your derivative works or by other works in which the Apple
-			Software may be incorporated.
-
-			The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-			WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-			WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-			PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-			COMBINATION WITH YOUR PRODUCTS.
-
-			IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-			CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-			GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-			ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-			OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-			(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-			ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/*
+     File: CAAudioUnit.cpp
+ Abstract: CAAudioUnit.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
 */
-/*=============================================================================
-	CAAudioUnit.cpp
-
-=============================================================================*/
-
 #include "CAAudioUnit.h"
 
+#if !TARGET_OS_IPHONE
 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
-	#include <AudioUnit/MusicDevice.h>
+	#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
+	#include <dlfcn.h>
 #else
-	#include <MusicDevice.h>
+	#include <Components.h>
+#endif
 #endif
 
+#include "CAXException.h"
 #include "CAReferenceCounted.h"
 #include "AUOutputBL.h" //this is for the Preroll only
 
-
 struct StackAUChannelInfo {
 		StackAUChannelInfo (UInt32 inSize) : mChanInfo ((AUChannelInfo*)malloc (inSize)) {}
 		~StackAUChannelInfo() { free (mChanInfo); }
-
+		
 	AUChannelInfo* mChanInfo;
 };
 
+// is this symbol is not defined then we use the default setting which is that fast dispatch
+// is supported on a desktop environment
+#ifndef CA_AU_USE_FAST_DISPATCH
+	#define CA_AU_USE_FAST_DISPATCH !TARGET_OS_IPHONE
+#endif
+
+#if CA_AU_USE_FAST_DISPATCH
+static void *LoadGetComponentInstanceStorage (void *inst);
+#endif
 
 
 class CAAudioUnit::AUState : public CAReferenceCounted  {
 public:
-	AUState (Component inComp)
+	AUState (AudioComponent inComp)
 						: mUnit(0), mNode (0)
-						{
-							OSStatus result = ::OpenAComponent (inComp, &mUnit);
+						{ 
+							OSStatus result = ::AudioComponentInstanceNew (inComp, &mUnit); 
 							if (result)
 								throw result;
 							Init();
 						}
 
 	AUState (const AUNode &inNode, const AudioUnit& inUnit)
-						: mUnit (inUnit), mNode (inNode)
+						: mUnit (inUnit), mNode (inNode) 
 						{
 							Init();
 						}
-
+						
 	~AUState();
-
+											
 	AudioUnit			mUnit;
 	AUNode				mNode;
 
 	OSStatus			GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
 											Float32 &outValue) const
 	{
+#if CA_AU_USE_FAST_DISPATCH
 			if (mGetParamProc != NULL) {
-				return reinterpret_cast<AudioUnitGetParameterProc>(mGetParamProc) (mConnInstanceStorage,
-										inID, scope, element, &outValue);
-			}
+				return (mGetParamProc) (mConnInstanceStorage, inID, scope, element, &outValue);
+			}							
+#endif
 		return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue);
 	}
 
 	OSStatus			SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
 											Float32 value, UInt32 bufferOffsetFrames)
 	{
+#if CA_AU_USE_FAST_DISPATCH
 			if (mSetParamProc != NULL) {
-				return reinterpret_cast<AudioUnitSetParameterProc>(mSetParamProc) (mConnInstanceStorage,
-										inID, scope, element, value, bufferOffsetFrames);
-			}
+				return (mSetParamProc) (mConnInstanceStorage, inID, scope, element, value, bufferOffsetFrames);
+			}							
+#endif
 			return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames);
 	}
-
+	
 	OSStatus			Render (AudioUnitRenderActionFlags *  ioActionFlags,
 								const AudioTimeStamp *        inTimeStamp,
 								UInt32                        inOutputBusNumber,
 								UInt32                        inNumberFrames,
 								AudioBufferList *             ioData)
 	{
+#if CA_AU_USE_FAST_DISPATCH
 		if (mRenderProc != NULL) {
-			return reinterpret_cast<AudioUnitRenderProc>(mRenderProc) (mConnInstanceStorage,
-									ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
-		}
+			return (mRenderProc) (mConnInstanceStorage, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
+		}							
+#endif
 		return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
 	}
-
+	
 	OSStatus		MIDIEvent (UInt32					inStatus,
 								UInt32					inData1,
 								UInt32					inData2,
 								UInt32					inOffsetSampleFrame)
 	{
 #if !TARGET_OS_WIN32
+#if CA_AU_USE_FAST_DISPATCH
 		if (mMIDIEventProc != NULL) {
-			return reinterpret_cast<MusicDeviceMIDIEventProc>(mMIDIEventProc) (mConnInstanceStorage,
-									inStatus, inData1, inData2, inOffsetSampleFrame);
+			return (mMIDIEventProc) (mConnInstanceStorage, inStatus, inData1, inData2, inOffsetSampleFrame);
 		}
+#endif
 		return MusicDeviceMIDIEvent (mUnit, inStatus, inData1, inData2, inOffsetSampleFrame);
-#else
+#else	// ON WINDOWS _ NO MIDI EVENT dispatch
 		return paramErr;
 #endif
 	}
@@ -139,6 +159,11 @@ public:
 									const MusicDeviceNoteParams * inParams)
 	{
 #if !TARGET_OS_WIN32
+#if CA_AU_USE_FAST_DISPATCH
+		if (mStartNoteProc != NULL) {
+			return (mStartNoteProc) (mConnInstanceStorage, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams);
+		}
+#endif
 		return MusicDeviceStartNote (mUnit, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams);
 #else
 		return paramErr;
@@ -149,6 +174,11 @@ public:
 									UInt32						inOffsetSampleFrame)
 	{
 #if !TARGET_OS_WIN32
+#if CA_AU_USE_FAST_DISPATCH
+		if (mStopNoteProc != NULL) {
+			return (mStopNoteProc) (mConnInstanceStorage, inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+		}
+#endif
 		return MusicDeviceStopNote (mUnit, inGroupID, inNoteInstanceID, inOffsetSampleFrame);
 #else
 		return paramErr;
@@ -157,49 +187,77 @@ public:
 
 private:
 	// get the fast dispatch pointers
-	void Init()
+	void Init() 
 	{
+#if CA_AU_USE_FAST_DISPATCH
 		UInt32 size = sizeof(AudioUnitRenderProc);
 		if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
 								kAudioUnitScope_Global, kAudioUnitRenderSelect,
 								&mRenderProc, &size) != noErr)
 			mRenderProc = NULL;
+		
+		size = sizeof(AudioUnitGetParameterProc);
 		if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
 								kAudioUnitScope_Global, kAudioUnitGetParameterSelect,
 								&mGetParamProc, &size) != noErr)
 			mGetParamProc = NULL;
+		
+		size = sizeof(AudioUnitSetParameterProc);
 		if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
 								kAudioUnitScope_Global, kAudioUnitSetParameterSelect,
 								&mSetParamProc, &size) != noErr)
 			mSetParamProc = NULL;
 
+		size = sizeof(MusicDeviceMIDIEventProc);
 		if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
 								kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect,
 								&mMIDIEventProc, &size) != noErr)
 			mMIDIEventProc = NULL;
 
-		if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc)
-			mConnInstanceStorage = GetComponentInstanceStorage(mUnit);
-		else
+		size = sizeof(MusicDeviceStartNoteProc);
+		if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+								kAudioUnitScope_Global, kMusicDeviceStartNoteSelect,
+								&mStartNoteProc, &size) != noErr)
+			mStartNoteProc = NULL;
+
+		size = sizeof(MusicDeviceStopNoteProc);
+		if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+								kAudioUnitScope_Global, kMusicDeviceStopNoteSelect,
+								&mStopNoteProc, &size) != noErr)
+			mStopNoteProc = NULL;
+		
+		if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc || mStartNoteProc || mStopNoteProc) {
+			mConnInstanceStorage = LoadGetComponentInstanceStorage ( mUnit );
+		} else
 			mConnInstanceStorage = NULL;
+#else
+		mConnInstanceStorage = NULL;
+#endif
 	}
-
-	ProcPtr						mRenderProc, mGetParamProc, mSetParamProc, mMIDIEventProc;
+	
+#if CA_AU_USE_FAST_DISPATCH
+	AudioUnitRenderProc			mRenderProc;
+	AudioUnitGetParameterProc	mGetParamProc; 
+	AudioUnitSetParameterProc	mSetParamProc;
+	MusicDeviceMIDIEventProc	mMIDIEventProc;
+	MusicDeviceStartNoteProc	mStartNoteProc;
+	MusicDeviceStopNoteProc		mStopNoteProc;
+#endif
 
 	void *						mConnInstanceStorage;
 
 private:
 		// get the compiler to tell us when we do a bad thing!!!
 	AUState () {}
-        AUState (const AUState& other) : CAReferenceCounted (other) {}
-	AUState& operator= (const AUState&) { return *this; }
-};
-
-
+	AUState (const AUState&);
+	AUState& operator= (const AUState&);
+};						
+						
+						
 CAAudioUnit::AUState::~AUState ()
 {
 	if (mUnit && (mNode == 0)) {
-		::CloseComponent (mUnit);
+		::AudioComponentInstanceDispose (mUnit);
 	}
 	mNode = 0;
 	mUnit = 0;
@@ -208,7 +266,7 @@ CAAudioUnit::AUState::~AUState ()
 OSStatus		CAAudioUnit::Open (const CAComponent& inComp, CAAudioUnit &outUnit)
 {
 	try {
-		outUnit = inComp;
+		outUnit = inComp; 
 		return noErr;
 	} catch (OSStatus res) {
 		return res;
@@ -218,23 +276,27 @@ OSStatus		CAAudioUnit::Open (const CAComponent& inComp, CAAudioUnit &outUnit)
 }
 
 CAAudioUnit::CAAudioUnit (const AudioUnit& inUnit)
-	: mComp (inUnit), mDataPtr (new AUState (-1, inUnit))
+	: mComp (inUnit), mDataPtr (new AUState (kCAAU_DoNotKnowIfAUNode, inUnit))
 {
 }
 
 CAAudioUnit::CAAudioUnit (const CAComponent& inComp)
-	: mComp (inComp), mDataPtr (0)
+	: mComp (inComp), mDataPtr (new AUState (mComp.Comp()))
 {
-	mDataPtr = new AUState (mComp.Comp());
 }
 
 CAAudioUnit::CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit)
-	: mComp (inUnit), mDataPtr(new AUState (inNode, inUnit))
+	: mComp (inUnit), mDataPtr(new AUState (inNode, inUnit)) 
 {
 }
 
 CAAudioUnit::~CAAudioUnit ()
 {
+	Close();
+}
+
+void		CAAudioUnit::Close()
+{
 	if (mDataPtr) {
 		mDataPtr->release();
 		mDataPtr = NULL;
@@ -246,13 +308,13 @@ CAAudioUnit&	CAAudioUnit::operator= (const CAAudioUnit &a)
 	if (mDataPtr != a.mDataPtr) {
 		if (mDataPtr)
 			mDataPtr->release();
-
+	
 		if ((mDataPtr = a.mDataPtr) != NULL)
 			mDataPtr->retain();
-
+		
 		mComp = a.mComp;
 	}
-
+	
 	return *this;
 }
 
@@ -270,28 +332,42 @@ bool			CAAudioUnit::operator== (const AudioUnit& y) const
 	return mDataPtr->mUnit == y;
 }
 
-#pragma mark __State Management
-
-bool			CAAudioUnit::IsValid () const
+OSStatus		CAAudioUnit::RemovePropertyListener (AudioUnitPropertyID		inID,
+												AudioUnitPropertyListenerProc	inProc,
+												void *							inProcUserData)
 {
-	return mDataPtr ? mDataPtr->mUnit != 0 : false;
-}
+		// we call this first. If it fails we call the old API as the failure can
+		// mean that the AU doesn't implement that selector.
+	OSStatus result = AudioUnitRemovePropertyListenerWithUserData(AU(), inID, 
+									inProc, inProcUserData);
+	#if !__LP64__ && !TARGET_OS_IPHONE
+		if (result) result = AudioUnitRemovePropertyListener (AU(), inID, inProc);
+	#endif									
+	return result;
+}	
 
-AudioUnit		CAAudioUnit::AU() const
-{
-	return mDataPtr ? mDataPtr->mUnit : 0;
+#pragma mark __State Management	
+
+bool			CAAudioUnit::IsValid () const 
+{ 
+	return mDataPtr ? mDataPtr->mUnit != 0 : false; 
+}
+	
+AudioUnit		CAAudioUnit::AU() const 
+{ 
+	return mDataPtr ? mDataPtr->mUnit : 0; 
 }
 
 AUNode			CAAudioUnit::GetAUNode () const
 {
-	return mDataPtr ? mDataPtr->mNode : 0;
+	return mDataPtr ? mDataPtr->mNode : 0; 
 }
 
 #pragma mark __Format Handling
-
-bool		CAAudioUnit::CanDo (	int 				inChannelsIn,
+	
+bool		CAAudioUnit::CanDo (	int 				inChannelsIn, 
 									int 				inChannelsOut) const
-{
+{		
 	// this is the default assumption of an audio effect unit
 	Boolean* isWritable = 0;
 	UInt32	dataSize = 0;
@@ -300,110 +376,109 @@ bool		CAAudioUnit::CanDo (	int 				inChannelsIn,
 									kAudioUnitProperty_SupportedNumChannels,
 									kAudioUnitScope_Global, 0,
 									&dataSize, isWritable); //don't care if this is writable
-
+		
 		// if this property is NOT implemented an FX unit
 		// is expected to deal with same channel valance in and out
-	if (result)
+	if (result) 
 	{
-		if ((Comp().Desc().IsEffect() && (inChannelsIn == inChannelsOut))
-			|| (Comp().Desc().IsOffline() && (inChannelsIn == inChannelsOut)))
+		if ((Comp().Desc().IsEffect() && inChannelsIn == inChannelsOut)
+			|| (Comp().Desc().IsOffline() && inChannelsIn == inChannelsOut))
 		{
 			return true;
 		}
-		else
+		else 
 		{
 			// the au should either really tell us about this
 			// or we will assume the worst
 			return false;
 		}
 	}
-
+	
 	StackAUChannelInfo info (dataSize);
-
+	
 	result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
 							kAudioUnitScope_Global, 0,
 							info.mChanInfo, &dataSize);
 	if (result) { return false; }
-
+	
 	return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo)));
 }
 
 int    CAAudioUnit::GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt)
 {
-	// this is the default assumption of an audio effect unit
-	Boolean* isWritable = 0;
-	UInt32	dataSize = 0;
-		// lets see if the unit has any channel restrictions
-	OSStatus result = AudioUnitGetPropertyInfo (AU(),
-						    kAudioUnitProperty_SupportedNumChannels,
-						    kAudioUnitScope_Global, 0,
-						    &dataSize, isWritable); //don't care if this is writable
-
-	// if this property is NOT implemented an FX unit
-	// is expected to deal with same channel valance in and out
-
-	if (result)
-	{
-		if (Comp().Desc().IsEffect())
-		{
-			return 1;
-		}
-		else if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
-			// directly query Bus Formats
-			// Note that that these may refer to different subBusses
-			// (eg. Kick, Snare,.. on a Drummachine)
-			// eventually the Bus-Name for each configuration should be exposed
-			// for the User to select..
-
-			UInt32 elCountIn, elCountOut;
-
-			if (GetElementCount (kAudioUnitScope_Input, elCountIn)) return -1;
-			if (GetElementCount (kAudioUnitScope_Output, elCountOut)) return -1;
-
-			cnt = std::max(elCountIn, elCountOut);
-
-			*chaninfo = (AUChannelInfo*) malloc (sizeof (AUChannelInfo) * cnt);
-
-			for (unsigned int i = 0; i < elCountIn; ++i) {
-				UInt32 numChans;
-				if (NumberChannels (kAudioUnitScope_Input, i, numChans)) return -1;
-				(*chaninfo)[i].inChannels = numChans;
-			}
-			for (unsigned int i = elCountIn; i < cnt; ++i) {
-				(*chaninfo)[i].inChannels = 0;
-			}
-
-			for (unsigned int i = 0; i < elCountOut; ++i) {
-				UInt32 numChans;
-				if (NumberChannels (kAudioUnitScope_Output, i, numChans)) return -1;
-				(*chaninfo)[i].outChannels = numChans;
-			}
-			for (unsigned int i = elCountOut; i < cnt; ++i) {
-				(*chaninfo)[i].outChannels = 0;
-			}
-			return 0;
-		}
-		else
-		{
-			// the au should either really tell us about this
-			// or we will assume the worst
-			return -1;
-		}
-	}
-
-	*chaninfo = (AUChannelInfo*) malloc (dataSize);
-	cnt = dataSize / sizeof (AUChannelInfo);
-
-	result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
-			      kAudioUnitScope_Global, 0,
-			      *chaninfo, &dataSize);
-
-	if (result) { return -1; }
-	return 0;
+    // this is the default assumption of an audio effect unit
+    Boolean* isWritable = 0;
+    UInt32	dataSize = 0;
+    // lets see if the unit has any channel restrictions
+    OSStatus result = AudioUnitGetPropertyInfo (AU(),
+                                                kAudioUnitProperty_SupportedNumChannels,
+                                                kAudioUnitScope_Global, 0,
+                                                &dataSize, isWritable); //don't care if this is writable
+    
+    // if this property is NOT implemented an FX unit
+    // is expected to deal with same channel valance in and out
+    
+    if (result)
+    {
+        if (Comp().Desc().IsEffect())
+        {
+            return 1;
+        }
+        else if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
+            // directly query Bus Formats
+            // Note that that these may refer to different subBusses
+            // (eg. Kick, Snare,.. on a Drummachine)
+            // eventually the Bus-Name for each configuration should be exposed
+            // for the User to select..
+            
+            UInt32 elCountIn, elCountOut;
+            
+            if (GetElementCount (kAudioUnitScope_Input, elCountIn)) return -1;
+            if (GetElementCount (kAudioUnitScope_Output, elCountOut)) return -1;
+            
+            cnt = std::max(elCountIn, elCountOut);
+            
+            *chaninfo = (AUChannelInfo*) malloc (sizeof (AUChannelInfo) * cnt);
+            
+            for (unsigned int i = 0; i < elCountIn; ++i) {
+                UInt32 numChans;
+                if (NumberChannels (kAudioUnitScope_Input, i, numChans)) return -1;
+                (*chaninfo)[i].inChannels = numChans;
+            }
+            for (unsigned int i = elCountIn; i < cnt; ++i) {
+                (*chaninfo)[i].inChannels = 0;
+            }
+            
+            for (unsigned int i = 0; i < elCountOut; ++i) {
+                UInt32 numChans;
+                if (NumberChannels (kAudioUnitScope_Output, i, numChans)) return -1;
+                (*chaninfo)[i].outChannels = numChans;
+            }
+            for (unsigned int i = elCountOut; i < cnt; ++i) {
+                (*chaninfo)[i].outChannels = 0;
+            }
+            return 0;
+        }
+        else 
+        {
+            // the au should either really tell us about this
+            // or we will assume the worst
+            return -1;
+        }
+    }
+    
+    *chaninfo = (AUChannelInfo*) malloc (dataSize);
+    cnt = dataSize / sizeof (AUChannelInfo);
+    
+    result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
+                          kAudioUnitScope_Global, 0,
+                          *chaninfo, &dataSize);
+    
+    if (result) { return -1; }
+    return 0;
 }
 
-
-bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn,
+bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn, 
 										int 				inChannelsOut,
 										const AUChannelInfo * info,
 										UInt32				numChanInfo) const
@@ -415,8 +490,8 @@ bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn,
 -1		wild card:
 -1,-1	any num channels as long as same channels on in and out
 -1,-2	any num channels channels on in and out - special meaning
--2+ 	indicates total num channs AU can handle
-			- elements configurable to any num channels,
+-2+ 	indicates total num channs AU can handle 
+			- elements configurable to any num channels, 
 			- element count in scope must be writable
 */
 
@@ -428,12 +503,14 @@ bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn,
 		{
 				// these are our wild card matches
 			if (info[i].inChannels == -1 && info[i].outChannels == -1) {
-				if (inChannelsOut == inChannelsIn) {
-					return true;
-				}
+				if (inChannelsIn && inChannelsOut) {
+					if (inChannelsOut == inChannelsIn)
+						return true;
+				} else
+					return true; // if one of these is zero, then a -1 means any
 			}
 			else if ((info[i].inChannels == -1 && info[i].outChannels == -2)
-					|| (info[i].inChannels == -2 && info[i].outChannels == -1))
+					|| (info[i].inChannels == -2 && info[i].outChannels == -1)) 
 			{
 				return true;
 			}
@@ -445,22 +522,22 @@ bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn,
 				IsElementCountWritable (kAudioUnitScope_Input, inWrite);
 				if (inWrite && outWrite) {
 					if ((inChannelsOut <= abs(info[i].outChannels))
-						&& (inChannelsIn <= abs(info[i].inChannels)))
+						&& (inChannelsIn <= abs(info[i].inChannels))) 
 					{
 						return true;
 					}
 				}
 			}
 		}
-
+			
 			// special meaning on input, specific num on output
 		else if (info[i].inChannels < 0) {
-			if (info[i].outChannels == inChannelsOut)
+			if (info[i].outChannels == inChannelsOut) 
 			{
 					// can do any in channels
 				if (info[i].inChannels == -1) {
 					return true;
-				}
+				} 
 					// total chans on input
 				else {
 					bool inWrite = false;
@@ -471,15 +548,15 @@ bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn,
 				}
 			}
 		}
-
+		
 			// special meaning on output, specific num on input
 		else if (info[i].outChannels < 0) {
-			if (info[i].inChannels == inChannelsIn)
+			if (info[i].inChannels == inChannelsIn) 
 			{
 					// can do any out channels
 				if (info[i].outChannels == -1) {
 					return true;
-				}
+				} 
 					// total chans on output
 				else {
 					bool outWrite = false;
@@ -494,9 +571,9 @@ bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn,
 			// both chans in struct >= 0 - thus has to explicitly match
 		else if ((info[i].inChannels == inChannelsIn) && (info[i].outChannels == inChannelsOut)) {
 			return true;
-		}
-
-			// now check to see if a wild card on the args (inChannelsIn or inChannelsOut chans is zero) is found
+		} 
+		
+			// now check to see if a wild card on the args (inChannelsIn or inChannelsOut chans is zero) is found 
 			// tells us to match just one side of the scopes
 		else if (inChannelsIn == 0) {
 			if (info[i].outChannels == inChannelsOut) {
@@ -509,10 +586,11 @@ bool	CAAudioUnit::ValidateChannelPair (int 				inChannelsIn,
 			}
 		}
 	}
-
+	
 	return false;
 }
 
+static
 bool CheckDynCount (SInt32 inTotalChans, const CAAUChanHelper &inHelper)
 {
 	int totalChans = 0;
@@ -521,9 +599,9 @@ bool CheckDynCount (SInt32 inTotalChans, const CAAUChanHelper &inHelper)
 	return (totalChans <= inTotalChans);
 }
 
-bool	CAAudioUnit::CheckOneSide (const CAAUChanHelper		&inHelper,
-									bool					checkOutput,
-									const AUChannelInfo		*info,
+bool	CAAudioUnit::CheckOneSide (const CAAUChanHelper		&inHelper, 
+									bool					checkOutput, 
+									const AUChannelInfo		*info, 
 									UInt32					numInfo) const
 {
 		// now we can use the wildcard option (see above impl) to see if this matches
@@ -546,25 +624,25 @@ bool	CAAudioUnit::CheckOneSide (const CAAUChanHelper		&inHelper,
 	return true;
 }
 
-bool		CAAudioUnit::CanDo (const CAAUChanHelper		&inputs,
+bool		CAAudioUnit::CanDo (const CAAUChanHelper		&inputs,  
 								const CAAUChanHelper		&outputs) const
 
 {
 // first check our state
 		// huh!
 	if (inputs.mNumEls == 0 && outputs.mNumEls == 0) return false;
-
+	
 	UInt32 elCount;
 	if (GetElementCount (kAudioUnitScope_Input, elCount)) { return false; }
 	if (elCount != inputs.mNumEls) return false;
 
 	if (GetElementCount (kAudioUnitScope_Output, elCount)) { return false; }
 	if (elCount != outputs.mNumEls) return false;
-
+		
 // (1) special cases (effects and sources (generators and instruments) only)
 	UInt32	dataSize = 0;
 	if (GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
-									kAudioUnitScope_Global, 0, &dataSize, NULL) != noErr)
+									kAudioUnitScope_Global, 0, &dataSize, NULL) != noErr) 
 	{
 		if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline()) {
 			UInt32 numChan = outputs.mNumEls > 0 ? outputs.mChans[0] : inputs.mChans[0];
@@ -574,7 +652,7 @@ bool		CAAudioUnit::CanDo (const CAAUChanHelper		&inputs,
 				if (numChan != outputs.mChans[out]) return false;
 			return true;
 		}
-
+		
 			// in this case, all the channels have to match the current config
 		if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
 			for (unsigned int in = 0; in < inputs.mNumEls; ++in) {
@@ -589,22 +667,22 @@ bool		CAAudioUnit::CanDo (const CAAUChanHelper		&inputs,
 			}
 			return true;
 		}
-
+		
 			// if we get here we can't determine anything about channel capabilities
 		return false;
 	}
 
 	StackAUChannelInfo info (dataSize);
-
+	
 	if (GetProperty (kAudioUnitProperty_SupportedNumChannels,
 							kAudioUnitScope_Global, 0,
 							info.mChanInfo, &dataSize) != noErr)
-	{
-		return false;
+	{ 
+		return false; 
 	}
-
+	
 	int numInfo = dataSize / sizeof(AUChannelInfo);
-
+	
 // (2) Test for dynamic capability (or no elements on that scope)
 	SInt32 dynInChans = 0;
 	if (ValidateDynamicScope (kAudioUnitScope_Input, dynInChans, info.mChanInfo, numInfo)) {
@@ -628,7 +706,7 @@ bool		CAAudioUnit::CanDo (const CAAUChanHelper		&inputs,
 	}
 
 // (4) - not a dynamic AU, has ins and outs, and has channel constraints so we test every possible pairing
-	for (unsigned int in = 0; in < inputs.mNumEls; ++in)
+	for (unsigned int in = 0; in < inputs.mNumEls; ++in) 
 	{
 		bool testInAlready = false;
 		for (unsigned int i = 0; i < in; ++i) {
@@ -655,7 +733,7 @@ bool		CAAudioUnit::CanDo (const CAAUChanHelper		&inputs,
 			}
 		}
 	}
-
+	
 	return true;
 }
 
@@ -669,7 +747,7 @@ bool		CAAudioUnit::SupportsNumChannels () const
 									kAudioUnitProperty_SupportedNumChannels,
 									kAudioUnitScope_Global, 0,
 									&dataSize, isWritable); //don't care if this is writable
-
+		
 		// if this property is NOT implemented an FX unit
 		// is expected to deal with same channel valance in and out
 	if (result) {
@@ -679,11 +757,11 @@ bool		CAAudioUnit::SupportsNumChannels () const
 	return result == noErr;
 }
 
-bool		CAAudioUnit::GetChannelLayouts (AudioUnitScope 			inScope,
+OSStatus		CAAudioUnit::GetChannelLayoutTags (AudioUnitScope 	inScope,
 										AudioUnitElement 			inEl,
 										ChannelTagVector			&outChannelVector) const
 {
-	if (HasChannelLayouts (inScope, inEl) == false) return false;
+	if (HasChannelLayouts (inScope, inEl) == false) return kAudioUnitErr_InvalidProperty; 
 
 	UInt32 dataSize;
 	OSStatus result = AudioUnitGetPropertyInfo (AU(),
@@ -691,19 +769,8 @@ bool		CAAudioUnit::GetChannelLayouts (AudioUnitScope 			inScope,
 								inScope, inEl,
 								&dataSize, NULL);
 
-	if (result == kAudioUnitErr_InvalidProperty) {
-		// if we get here we can do layouts but we've got the speaker config property
-		outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
-		outChannelVector.push_back (kAudioChannelLayoutTag_Stereo);
-		outChannelVector.push_back (kAudioChannelLayoutTag_StereoHeadphones);
-		outChannelVector.push_back (kAudioChannelLayoutTag_Quadraphonic);
-		outChannelVector.push_back (kAudioChannelLayoutTag_AudioUnit_5_0);
-		return true;
-	}
-
-	if (result) return false;
-
-	bool canDo = false;
+	if (result) return result;
+	
 		// OK lets get our channel layouts and see if the one we want is present
 	AudioChannelLayoutTag* info = (AudioChannelLayoutTag*)malloc (dataSize);
 	result = AudioUnitGetProperty (AU(),
@@ -711,17 +778,17 @@ bool		CAAudioUnit::GetChannelLayouts (AudioUnitScope 			inScope,
 							inScope, inEl,
 							info, &dataSize);
 	if (result) goto home;
-
+	
 	outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
 	for (unsigned int i = 0; i < (dataSize / sizeof (AudioChannelLayoutTag)); ++i)
 		outChannelVector.push_back (info[i]);
 
 home:
 	free (info);
-	return canDo;
+	return result;
 }
 
-bool		CAAudioUnit::HasChannelLayouts (AudioUnitScope 		inScope,
+bool		CAAudioUnit::HasChannelLayouts (AudioUnitScope 		inScope, 
 										AudioUnitElement 		inEl) const
 {
 	OSStatus result = AudioUnitGetPropertyInfo (AU(),
@@ -731,6 +798,18 @@ bool		CAAudioUnit::HasChannelLayouts (AudioUnitScope 		inScope,
 	return !result;
 }
 
+bool		CAAudioUnit::HasChannelLayout (AudioUnitScope 		inScope, 
+											AudioUnitElement 		inEl) const
+{
+	Boolean writable;
+	UInt32 size;
+	
+	return AudioUnitGetPropertyInfo (AU(),
+									kAudioUnitProperty_AudioChannelLayout,
+									inScope, inEl,
+									&size, &writable) == noErr;
+}	
+
 OSStatus	CAAudioUnit::GetChannelLayout (AudioUnitScope 		inScope,
 										AudioUnitElement 		inEl,
 										CAAudioChannelLayout	&outLayout) const
@@ -739,14 +818,14 @@ OSStatus	CAAudioUnit::GetChannelLayout (AudioUnitScope 		inScope,
 	OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_AudioChannelLayout,
 									inScope, inEl, &size, NULL);
 	if (result) return result;
-
+	
 	AudioChannelLayout *layout = (AudioChannelLayout*)malloc (size);
 
-	require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout,
+	ca_require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout,
 									inScope, inEl, layout, &size), home);
 
 	outLayout = CAAudioChannelLayout (layout);
-
+	
 home:
 	free (layout);
 	return result;
@@ -754,7 +833,7 @@ home:
 
 OSStatus	CAAudioUnit::SetChannelLayout (AudioUnitScope 		inScope,
 									AudioUnitElement 			inEl,
-									CAAudioChannelLayout 		&inLayout)
+									const CAAudioChannelLayout 		&inLayout)
 {
 	OSStatus result = AudioUnitSetProperty (AU(),
 									kAudioUnitProperty_AudioChannelLayout,
@@ -763,9 +842,9 @@ OSStatus	CAAudioUnit::SetChannelLayout (AudioUnitScope 		inScope,
 	return result;
 }
 
-OSStatus	CAAudioUnit::SetChannelLayout (AudioUnitScope 			inScope,
+OSStatus	CAAudioUnit::SetChannelLayout (AudioUnitScope 			inScope, 
 											AudioUnitElement 		inEl,
-											AudioChannelLayout		&inLayout,
+											const AudioChannelLayout		&inLayout,
 											UInt32					inSize)
 {
 	OSStatus result = AudioUnitSetProperty (AU(),
@@ -789,7 +868,7 @@ OSStatus	CAAudioUnit::GetFormat (AudioUnitScope				inScope,
 {
 	UInt32 dataSize = sizeof (AudioStreamBasicDescription);
 	return AudioUnitGetProperty (AU(), kAudioUnitProperty_StreamFormat,
-								inScope, inEl,
+								inScope, inEl, 
 								&outFormat, &dataSize);
 }
 
@@ -799,7 +878,7 @@ OSStatus	CAAudioUnit::SetFormat (AudioUnitScope						inScope,
 {
 	return AudioUnitSetProperty (AU(), kAudioUnitProperty_StreamFormat,
 								inScope, inEl,
-								const_cast<AudioStreamBasicDescription*>(&inFormat),
+								const_cast<AudioStreamBasicDescription*>(&inFormat), 
 								sizeof (AudioStreamBasicDescription));
 }
 
@@ -809,7 +888,7 @@ OSStatus	CAAudioUnit::GetSampleRate (AudioUnitScope		inScope,
 {
 	UInt32 dataSize = sizeof (Float64);
 	return AudioUnitGetProperty (AU(), kAudioUnitProperty_SampleRate,
-								inScope, inEl,
+								inScope, inEl, 
 								&outRate, &dataSize);
 }
 
@@ -827,22 +906,22 @@ OSStatus	CAAudioUnit::SetSampleRate (AudioUnitScope		inScope,
 OSStatus	CAAudioUnit::SetSampleRate (Float64			inSampleRate)
 {
 	OSStatus result;
-
+	
 	UInt32 elCount;
-	require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home);
+	ca_require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home);
 	if (elCount) {
 		for (unsigned int i = 0; i < elCount; ++i) {
-			require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home);
+			ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home);
 		}
 	}
 
-	require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home);
+	ca_require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home);
 	if (elCount) {
 		for (unsigned int i = 0; i < elCount; ++i) {
-			require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home);
+			ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home);
 		}
 	}
-
+	
 home:
 	return result;
 }
@@ -866,7 +945,7 @@ OSStatus	CAAudioUnit::SetNumberChannels (AudioUnitScope	inScope,
 	CAStreamBasicDescription desc;
 	OSStatus result = GetFormat (inScope, inEl, desc);
 		if (result) return result;
-	desc.SetCanonical (inChans, desc.IsInterleaved());
+	desc.ChangeNumberChannels (inChans, desc.IsInterleaved());
 	result = SetFormat (inScope, inEl, desc);
 	return result;
 }
@@ -879,7 +958,7 @@ OSStatus		CAAudioUnit::IsElementCountWritable (AudioUnitScope inScope, bool &out
 	if (result)
 		return result;
 	outWritable = isWritable ? true : false;
-	return noErr;
+	return noErr;	
 }
 
 OSStatus		CAAudioUnit::GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const
@@ -902,12 +981,12 @@ bool			CAAudioUnit::HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNum
 	OSStatus result = GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
 								kAudioUnitScope_Global, 0,
 								&dataSize, isWritable); //don't care if this is writable
-
+		
 		// AU has to explicitly tell us about this.
 	if (result) return false;
 
 	StackAUChannelInfo info (dataSize);
-
+	
 	result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
 							kAudioUnitScope_Global, 0,
 							info.mChanInfo, &dataSize);
@@ -924,9 +1003,9 @@ bool			CAAudioUnit::HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNum
 
 -N 	(where N is less than -2), signifies the total channel count on the scope side (in or out)
 */
-bool	CAAudioUnit::ValidateDynamicScope (AudioUnitScope		inScope,
-											SInt32				&outTotalNumChannels,
-											const AUChannelInfo *info,
+bool	CAAudioUnit::ValidateDynamicScope (AudioUnitScope		inScope, 
+											SInt32				&outTotalNumChannels, 
+											const AUChannelInfo *info, 
 											UInt32				numInfo) const
 {
 	bool writable = false;
@@ -945,48 +1024,48 @@ bool	CAAudioUnit::ValidateDynamicScope (AudioUnitScope		inScope,
 			outTotalNumChannels = -1;
 			return true;
 		}
-
+		
 		// ok lets now test our special case....
 		if (inScope == kAudioUnitScope_Input) {
 				// isn't dynamic on this side at least
 			if (info[i].inChannels >= 0)
 				continue;
-
+				
 			if (info[i].inChannels < -2) {
 				outTotalNumChannels = abs (info[i].inChannels);
 				return true;
 			}
-		}
-
+		} 
+		
 		else if (inScope == kAudioUnitScope_Output) {
 				// isn't dynamic on this side at least
 			if (info[i].outChannels >= 0)
 				continue;
-
+				
 			if (info[i].outChannels < -2) {
 				outTotalNumChannels = abs (info[i].outChannels);
 				return true;
 			}
-		}
-
+		} 
+		
 		else {
 			break; // wrong scope was specified
 		}
 	}
-
-	return false;
+	
+	return false;	
 }
 
-OSStatus	CAAudioUnit::ConfigureDynamicScope (AudioUnitScope 		inScope,
-											UInt32 					inNumElements,
-											UInt32 					*inChannelsPerElement,
+OSStatus	CAAudioUnit::ConfigureDynamicScope (AudioUnitScope 		inScope, 
+											UInt32 					inNumElements, 
+											UInt32 					*inChannelsPerElement, 
 											Float64 				inSampleRate)
 {
 	SInt32 numChannels = 0;
 	bool isDyamic = HasDynamicScope (inScope, numChannels);
 	if (isDyamic == false)
 		return kAudioUnitErr_InvalidProperty;
-
+	
 	//lets to a sanity check...
 	// if numChannels == -1, then it can do "any"...
 	if (numChannels > 0) {
@@ -996,15 +1075,17 @@ OSStatus	CAAudioUnit::ConfigureDynamicScope (AudioUnitScope 		inScope,
 		if (count > numChannels)
 			return kAudioUnitErr_InvalidPropertyValue;
 	}
-
+	
 	OSStatus result = SetElementCount (inScope, inNumElements);
 	if (result)
 		return result;
-
-	CAStreamBasicDescription desc;
-	desc.mSampleRate = inSampleRate;
+		
 	for (unsigned int i = 0; i < inNumElements; ++i) {
-		desc.SetCanonical (inChannelsPerElement[i], false);
+		CAStreamBasicDescription desc;
+		result = GetFormat (inScope, i, desc);
+			if (result) return result;
+		desc.ChangeNumberChannels (inChannelsPerElement[i], desc.IsInterleaved());
+		desc.mSampleRate = inSampleRate;
 		result = SetFormat (inScope, i, desc);
 		if (result)
 			return result;
@@ -1034,13 +1115,28 @@ bool		CAAudioUnit::GetBypass 		() const
 }
 
 OSStatus	CAAudioUnit::SetBypass 		(bool	inBypass) const
-{
+{	
 	UInt32 bypass = inBypass ? 1 : 0;
 	return AudioUnitSetProperty (AU(), kAudioUnitProperty_BypassEffect,
 								kAudioUnitScope_Global, 0,
 								&bypass, sizeof (UInt32));
 }
 
+OSStatus	CAAudioUnit::GetMaxFramesPerSlice (UInt32& outMaxFrames) const
+{
+	UInt32 dataSize = sizeof(outMaxFrames);
+	return AudioUnitGetProperty (AU(), kAudioUnitProperty_MaximumFramesPerSlice,
+								kAudioUnitScope_Global, 0,
+								&outMaxFrames, &dataSize);
+}
+
+OSStatus	CAAudioUnit::SetMaxFramesPerSlice (UInt32 inMaxFrames)
+{
+	return AudioUnitSetProperty (AU(), kAudioUnitProperty_MaximumFramesPerSlice,
+								 kAudioUnitScope_Global, 0,
+								 &inMaxFrames, sizeof (UInt32));	
+}
+
 Float64		CAAudioUnit::Latency () const
 {
 	Float64 secs;
@@ -1065,12 +1161,23 @@ OSStatus	CAAudioUnit::SetAUPreset (CFPropertyListRef &inData)
 								&inData, sizeof (CFPropertyListRef));
 }
 
+#if !TARGET_OS_IPHONE
+OSStatus	CAAudioUnit::SetAUPresetFromDocument (CFPropertyListRef &inData)
+{
+	return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfoFromDocument,
+								kAudioUnitScope_Global, 0,
+								&inData, sizeof (CFPropertyListRef));
+}
+#endif
+
 OSStatus	CAAudioUnit::GetPresentPreset (AUPreset &outData) const
 {
 	UInt32 dataSize = sizeof(outData);
 	OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_PresentPreset,
 								kAudioUnitScope_Global, 0,
 								&outData, &dataSize);
+#if !TARGET_OS_IPHONE
+#ifndef __LP64__ 
 	if (result == kAudioUnitErr_InvalidProperty) {
 		dataSize = sizeof(outData);
 		result = AudioUnitGetProperty (AU(), kAudioUnitProperty_CurrentPreset,
@@ -1083,28 +1190,38 @@ OSStatus	CAAudioUnit::GetPresentPreset (AUPreset &outData) const
 				CFRetain (outData.presetName);
 		}
 	}
+#endif
+#endif
 	return result;
 }
-
+	
 OSStatus	CAAudioUnit::SetPresentPreset (AUPreset &inData)
 {
 	OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset,
 								kAudioUnitScope_Global, 0,
 								&inData, sizeof (AUPreset));
+#if !TARGET_OS_IPHONE
+#ifndef __LP64__
 	if (result == kAudioUnitErr_InvalidProperty) {
 		result = AudioUnitSetProperty (AU(), kAudioUnitProperty_CurrentPreset,
 								kAudioUnitScope_Global, 0,
 								&inData, sizeof (AUPreset));
 	}
+#endif
+#endif
 	return result;
 }
 
 bool		CAAudioUnit::HasCustomView () const
 {
+#if !TARGET_OS_IPHONE
 	UInt32 dataSize = 0;
-	OSStatus result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList,
+	OSStatus result = -4/*unimpErr*/;
+#ifndef __LP64__
+	result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList,
                                         kAudioUnitScope_Global, 0,
-                                        &dataSize, NULL);
+                                        &dataSize, NULL);	
+#endif
 	if (result || !dataSize) {
 		dataSize = 0;
 		result = GetPropertyInfo(kAudioUnitProperty_CocoaUI,
@@ -1114,18 +1231,22 @@ bool		CAAudioUnit::HasCustomView () const
 			return false;
 	}
 	return true;
+#else
+	return false;
+#endif
+
 }
 
 OSStatus		CAAudioUnit::GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
 											Float32 &outValue) const
 {
-	return mDataPtr ? (OSStatus) mDataPtr->GetParameter (inID, scope, element, outValue) : paramErr;
+	return mDataPtr ? mDataPtr->GetParameter (inID, scope, element, outValue) : static_cast<OSStatus>(paramErr);
 }
 
 OSStatus		CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
 											Float32 value, UInt32 bufferOffsetFrames)
 {
-	return mDataPtr ? (OSStatus) mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : paramErr;
+	return mDataPtr ? mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : static_cast<OSStatus>(paramErr);
 }
 
 OSStatus		CAAudioUnit::MIDIEvent (UInt32			inStatus,
@@ -1133,7 +1254,7 @@ OSStatus		CAAudioUnit::MIDIEvent (UInt32			inStatus,
 								UInt32					inData2,
 								UInt32					inOffsetSampleFrame)
 {
-	return mDataPtr ? (OSStatus) mDataPtr->MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame) : paramErr;
+	return mDataPtr ? mDataPtr->MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame) : paramErr;
 }
 
 OSStatus	CAAudioUnit::StartNote (MusicDeviceInstrumentID		inInstrument,
@@ -1142,17 +1263,18 @@ OSStatus	CAAudioUnit::StartNote (MusicDeviceInstrumentID		inInstrument,
 									UInt32						inOffsetSampleFrame,
 									const MusicDeviceNoteParams * inParams)
 {
-	return mDataPtr ? (OSStatus) mDataPtr->StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams)
-		: paramErr;
+	return mDataPtr ? mDataPtr->StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams) 
+					: paramErr;
 }
 
 OSStatus	CAAudioUnit::StopNote (MusicDeviceGroupID		inGroupID,
 									NoteInstanceID				inNoteInstanceID,
 									UInt32						inOffsetSampleFrame)
 {
-	return mDataPtr ? (OSStatus) mDataPtr->StopNote (inGroupID, inNoteInstanceID, inOffsetSampleFrame) : paramErr;
+	return mDataPtr ? mDataPtr->StopNote (inGroupID, inNoteInstanceID, inOffsetSampleFrame) : paramErr;
 }
 
+
 #pragma mark __Render
 
 OSStatus		CAAudioUnit::Render (AudioUnitRenderActionFlags 			* ioActionFlags,
@@ -1161,66 +1283,52 @@ OSStatus		CAAudioUnit::Render (AudioUnitRenderActionFlags 			* ioActionFlags,
 												UInt32						inNumberFrames,
 												AudioBufferList				* ioData)
 {
-	return mDataPtr ? (OSStatus) mDataPtr->Render (ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData) : paramErr;
+	return mDataPtr ? mDataPtr->Render (ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData) : static_cast<OSStatus>(paramErr);
 }
 
-static AURenderCallbackStruct sRenderCallback;
-static OSStatus PrerollRenderProc (	void 						* /*inRefCon*/,
-								AudioUnitRenderActionFlags		* /*inActionFlags*/,
-								const AudioTimeStamp 			* /*inTimeStamp*/,
-								UInt32 							/*inBusNumber*/,
-								UInt32							/*inNumFrames*/,
-								AudioBufferList 				*ioData)
-{
-	AudioBuffer *buf = ioData->mBuffers;
-	for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
-		memset((Byte *)buf->mData, 0, buf->mDataByteSize);
+extern "C" OSStatus
+AudioUnitProcess (					AudioUnit						inUnit, 
+									AudioUnitRenderActionFlags *	ioActionFlags, 
+									const AudioTimeStamp *			inTimeStamp, 
+									UInt32							inNumberFrames, 
+									AudioBufferList *				ioData);
 
-	return noErr;
+OSStatus		CAAudioUnit::Process (AudioUnitRenderActionFlags 			& ioActionFlags,
+												const AudioTimeStamp 		& inTimeStamp,
+												UInt32						inNumberFrames,
+												AudioBufferList				& ioData)
+{
+#if defined(__MAC_10_7) || defined(__IPHONE_4_0)
+	return AudioUnitProcess (AU(), &ioActionFlags, &inTimeStamp, inNumberFrames, &ioData);
+#else
+	return -4/*unimpErr*/;
+#endif
 }
 
-OSStatus 	CAAudioUnit::Preroll (UInt32 inFrameSize)
+extern "C" OSStatus
+AudioUnitProcessMultiple (			AudioUnit						inUnit, 
+									AudioUnitRenderActionFlags *	ioActionFlags, 
+									const AudioTimeStamp *			inTimeStamp, 
+									UInt32							inNumberFrames,
+									UInt32							inNumberInputBufferLists,
+									const AudioBufferList **		inInputBufferLists,
+									UInt32							inNumberOutputBufferLists,
+									AudioBufferList **				ioOutputBufferLists);
+
+OSStatus		CAAudioUnit::ProcessMultiple (AudioUnitRenderActionFlags 	& ioActionFlags,
+									const AudioTimeStamp					& inTimeStamp,
+									UInt32									inNumberFrames,
+									UInt32									inNumberInputBufferLists,
+									const AudioBufferList **				inInputBufferLists,
+									UInt32									inNumberOutputBufferLists,
+									AudioBufferList **						ioOutputBufferLists)
 {
-	CAStreamBasicDescription desc;
-	OSStatus result = GetFormat (kAudioUnitScope_Input, 0, desc);
-	bool hasInput = false;
-			//we have input
-	if (result == noErr)
-	{
-		sRenderCallback.inputProc = PrerollRenderProc;
-		sRenderCallback.inputProcRefCon = 0;
-
-		result = SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
-								0, &sRenderCallback, sizeof(sRenderCallback));
-		if (result) return result;
-		hasInput = true;
-	}
-
-	AudioUnitRenderActionFlags flags = 0;
-	AudioTimeStamp time;
-	memset (&time, 0, sizeof(time));
-	time.mFlags = kAudioTimeStampSampleTimeValid;
-
-	CAStreamBasicDescription outputFormat;
-	require_noerr (result = GetFormat (kAudioUnitScope_Output, 0, outputFormat), home);
-	{
-		AUOutputBL list (outputFormat, inFrameSize);
-		list.Prepare ();
-
-		require_noerr (result = Render (&flags, &time, 0, inFrameSize, list.ABL()), home);
-		require_noerr (result = GlobalReset(), home);
-	}
-
-home:
-	if (hasInput) {
-            // remove our installed callback
-		sRenderCallback.inputProc = 0;
-		sRenderCallback.inputProcRefCon = 0;
-
-		SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
-								0, &sRenderCallback, sizeof(sRenderCallback));
-	}
-	return result;
+#if defined(__MAC_10_7) || defined(__IPHONE_4_0)
+	return AudioUnitProcessMultiple (AU(), &ioActionFlags, &inTimeStamp, inNumberFrames, 
+				inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+#else
+	return -4/*unimpErr*/;
+#endif
 }
 
 #pragma mark __CAAUChanHelper
@@ -1230,13 +1338,13 @@ CAAUChanHelper::CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope)
 {
 	UInt32 elCount;
 	if (inAU.GetElementCount (inScope, elCount)) return;
-	if (elCount > 8) {
+	if (elCount > kStaticElCount) {
 		mChans = new UInt32[elCount];
 		mDidAllocate = true;
 		memset (mChans, 0, sizeof(int) * elCount);
 	} else {
 		mChans = mStaticChans;
-		memset (mChans, 0, sizeof(int) * 8);
+		memset (mChans, 0, sizeof(int) * kStaticElCount);
 	}
 	for (unsigned int i = 0; i < elCount; ++i) {
 		UInt32 numChans;
@@ -1246,13 +1354,26 @@ CAAUChanHelper::CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope)
 	mNumEls = elCount;
 }
 
+CAAUChanHelper::CAAUChanHelper(UInt32 inMaxElems) 
+	: mNumEls(inMaxElems), mDidAllocate(false) 
+{
+	if (inMaxElems > kStaticElCount) {
+		mChans = new UInt32[inMaxElems];
+		mDidAllocate = true;
+		memset (mChans, 0, sizeof(int) * inMaxElems);
+	} else {
+		mChans = mStaticChans;
+		memset (mChans, 0, sizeof(int) * kStaticElCount);
+	}
+}
+
 CAAUChanHelper::~CAAUChanHelper()
 {
 	if (mDidAllocate) delete [] mChans;
 }
 
-CAAUChanHelper&		CAAUChanHelper::operator= (const CAAUChanHelper &c)
-{
+CAAUChanHelper&		CAAUChanHelper::operator= (const CAAUChanHelper &c) 
+{ 
 	if (mDidAllocate) delete [] mChans;
 	if (c.mDidAllocate) {
 		mChans = new UInt32[c.mNumEls];
@@ -1262,16 +1383,39 @@ CAAUChanHelper&		CAAUChanHelper::operator= (const CAAUChanHelper &c)
 		mChans = mStaticChans;
 	}
 	memcpy (mChans, c.mChans, c.mNumEls * sizeof(int));
-
-	return *this;
+	
+	return *this; 
 }
 
+
 #pragma mark __Print Utilities
 
 void		CAAudioUnit::Print (FILE* file) const
 {
 	fprintf (file, "AudioUnit:%p\n", AU());
-	if (IsValid()) {
+	if (IsValid()) { 
 		fprintf (file, "\tnode=%ld\t", (long)GetAUNode()); Comp().Print (file);
 	}
 }
+
+#if CA_AU_USE_FAST_DISPATCH
+// Handle  GetComponentInstanceStorage(ComponentInstance aComponentInstance)
+static void *LoadGetComponentInstanceStorage (void *inst)
+{
+	typedef void* (*GetComponentInstanceStorageProc)(void* aComponentInstance);
+	static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
+	
+	static int sDoCSLoad = 1;
+	if (sDoCSLoad) {
+		sDoCSLoad = 0;
+		void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
+		if (!theImage) return NULL;
+	
+		sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
+	}
+	if (sGetComponentInstanceStorageProc)
+		return (*sGetComponentInstanceStorageProc)(inst);
+	return NULL;
+}
+#endif
+
diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h
similarity index 61%
copy from libs/appleutility/CAAudioUnit.h
copy to libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h
index 7be4846..07a522e 100644
--- a/libs/appleutility/CAAudioUnit.h
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h
@@ -1,59 +1,64 @@
-/*	Copyright: 	© Copyright 2005 Apple Computer, Inc. All rights reserved.
-
-	Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-			("Apple") in consideration of your agreement to the following terms, and your
-			use, installation, modification or redistribution of this Apple software
-			constitutes acceptance of these terms.  If you do not agree with these terms,
-			please do not use, install, modify or redistribute this Apple software.
-
-			In consideration of your agreement to abide by the following terms, and subject
-			to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
-			copyrights in this original Apple software (the "Apple Software"), to use,
-			reproduce, modify and redistribute the Apple Software, with or without
-			modifications, in source and/or binary forms; provided that if you redistribute
-			the Apple Software in its entirety and without modifications, you must retain
-			this notice and the following text and disclaimers in all such redistributions of
-			the Apple Software.  Neither the name, trademarks, service marks or logos of
-			Apple Computer, Inc. may be used to endorse or promote products derived from the
-			Apple Software without specific prior written permission from Apple.  Except as
-			expressly stated in this notice, no other rights or licenses, express or implied,
-			are granted by Apple herein, including but not limited to any patent rights that
-			may be infringed by your derivative works or by other works in which the Apple
-			Software may be incorporated.
-
-			The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-			WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-			WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-			PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-			COMBINATION WITH YOUR PRODUCTS.
-
-			IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-			CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-			GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-			ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-			OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-			(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-			ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/*
+     File: CAAudioUnit.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
 */
-/*=============================================================================
-	CAAudioUnit.h
-
-=============================================================================*/
-
 #ifndef __CAAudioUnit_h__
 #define __CAAudioUnit_h__
 
 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
-	#include <CoreServices/CoreServices.h>
-	#include <CoreAudio/CoreAudio.h>
+	#include <CoreAudio/CoreAudioTypes.h>
 	#include <AudioUnit/AudioUnit.h>
 	#include <AudioToolbox/AUGraph.h>
+	#include <AudioUnit/MusicDevice.h>
 #else
 	#include <ConditionalMacros.h>
-	#include <CoreServices.h>
 	#include <CoreAudioTypes.h>
 	#include <AudioUnit.h>
+	#include <MusicDevice.h>
 	#include <AUGraph.h>
+	#include <MusicDevice.h>
 #endif
 
 #include <vector>
@@ -68,19 +73,23 @@ class CAAUChanHelper;
 // The destructor will NOT automatically close the AU down
 // This state should be managed by the Caller
 // once closed, the unit represented by this object is no longer valid
-// it is up to the user of this object to ensure its validity is in sync
+// it is up to the user of this object to ensure its validity is in sync 
 // if it is removed from a graph
 
 // methods that can significantly change the state of the AU (like its format) are
 // NOT const whereas those that don't change the externally related state of the AU are not const
 
 class CAAudioUnit {
+	enum {
+		paramErr = -50,
+		badComponentSelector = (long)0x80008002
+	};
 public:
 	typedef std::vector<AudioChannelLayoutTag> 	ChannelTagVector;
 	typedef ChannelTagVector::iterator 			ChannelTagVectorIter;
 
 public:
-							CAAudioUnit ()
+							CAAudioUnit () 
 								: mDataPtr(0) {}
 
 							CAAudioUnit (const AudioUnit& inUnit);
@@ -94,29 +103,37 @@ public:
 
 							~CAAudioUnit ();
 
+	void					Close ();
 
+	
 	CAAudioUnit&			operator= (const CAAudioUnit& y);
 
 	bool					operator== (const CAAudioUnit& y) const;
 
 	bool					operator== (const AudioUnit& y) const;
 
-#pragma mark __State Management
+#pragma mark __State Management	
 	bool					IsValid () const;
-
+	
 	AudioUnit				AU() const;
 	operator AudioUnit () const { return AU(); }
 
 	const CAComponent&		Comp() const { return mComp; }
-
-	bool					FromAUGraph () const { return GetAUNode() != 0 || GetAUNode() != -1; }
-
+	
+	const CAComponentDescription& Desc() const { return mComp.Desc(); }
+	
+	bool					FromAUGraph () const { return GetAUNode() != 0 && GetAUNode() != kCAAU_DoNotKnowIfAUNode; }
+	
 	AUNode					GetAUNode () const;
 	operator AUNode () const { return GetAUNode(); }
-
+	
 #pragma mark __API Wrapper
-	OSStatus				Initialize() const { return AudioUnitInitialize(AU()); }
-	OSStatus				Uninitialize() const { return AudioUnitUninitialize(AU()); }
+	OSStatus				Initialize() const {
+								return AudioUnitInitialize(AU());
+							}
+	OSStatus				Uninitialize() const {
+								return AudioUnitUninitialize(AU());
+							}
 	OSStatus				GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
 											UInt32 *outDataSize, Boolean *outWritable) const
 							{
@@ -134,7 +151,7 @@ public:
 							}
 	OSStatus				SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
 											Float32 value, UInt32 bufferOffsetFrames=0);
-
+							
 	OSStatus				GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
 											Float32 &outValue) const;
 
@@ -144,6 +161,20 @@ public:
 												UInt32						inNumberFrames,
 												AudioBufferList				* ioData);
 
+	OSStatus				Process (AudioUnitRenderActionFlags 			& ioActionFlags,
+												const AudioTimeStamp 		& inTimeStamp,
+												UInt32						inNumberFrames,
+												AudioBufferList				& ioData);
+	
+	OSStatus				ProcessMultiple (AudioUnitRenderActionFlags 	& ioActionFlags,
+												const AudioTimeStamp		& inTimeStamp,
+												UInt32						inNumberFrames,
+												UInt32						inNumberInputBufferLists,
+												const AudioBufferList **	inInputBufferLists,
+												UInt32						inNumberOutputBufferLists,
+												AudioBufferList **			ioOutputBufferLists);
+
+	
 	OSStatus				Reset (AudioUnitScope scope, AudioUnitElement element)
 							{
 								return AudioUnitReset (AU(), scope, element);
@@ -153,33 +184,40 @@ public:
 								return AudioUnitReset (AU(), kAudioUnitScope_Global, 0);
 							}
 
-	OSStatus 				Preroll (UInt32 inFrameSize);
-
 	OSStatus				AddRenderNotify (AURenderCallback   inProc, void *inProcRefCon)
 							{
 								return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon);
 							}
-
+	
 	OSStatus				RemoveRenderNotify (AURenderCallback   inProc, void *inProcRefCon)
 							{
 								return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon);
 							}
 
-
-// Fast dispatch support for MIDI Effects or Music Devices
+	OSStatus				AddPropertyListener (AudioUnitPropertyID				inID,
+													AudioUnitPropertyListenerProc	inProc,
+													void *							inProcRefCon)
+							{
+								return AudioUnitAddPropertyListener (AU(), inID, inProc, inProcRefCon);
+							}
+	
+	OSStatus				RemovePropertyListener (AudioUnitPropertyID				inID,
+													AudioUnitPropertyListenerProc	inProc,
+													void *							inProcUserData);
+	
 	OSStatus				MIDIEvent (UInt32					inStatus,
 										UInt32					inData1,
 										UInt32					inData2,
 										UInt32					inOffsetSampleFrame);
-
+								
 								// uses the default VoiceForGroup value - this is the normal case
 	OSStatus				StartNote (MusicDeviceGroupID		inGroupID,
 									NoteInstanceID *			outNoteInstanceID,
 									UInt32						inOffsetSampleFrame,
 									const MusicDeviceNoteParams * inParams)
 							{
-								return StartNote (kMusicNoteEvent_UseGroupInstrument,
-													inGroupID, outNoteInstanceID,
+								return StartNote (kMusicNoteEvent_UseGroupInstrument, 
+													inGroupID, outNoteInstanceID, 
 													inOffsetSampleFrame, inParams);
 							}
 
@@ -203,42 +241,45 @@ public:
 							{
 								return CanDo (inChannelsInOut, inChannelsInOut);
 							}
-
-	bool					CanDo (		int 				inChannelsIn,
+							
+	bool					CanDo (		int 				inChannelsIn, 
 										int 				inChannelsOut) const;
-
+		
 		// This version does a more thorough test for ANY AU with ANY ins/outs
 		// you pass in the channel helper (for the current element count on that scope)
-
+		
 	bool					CanDo (		const CAAUChanHelper		&input,
 										const CAAUChanHelper		&output) const;
-
+	
 	bool					SupportsNumChannels () const;
 
-	bool					HasChannelLayouts (AudioUnitScope 		inScope,
+	bool					HasChannelLayouts (AudioUnitScope 		inScope, 
 											AudioUnitElement 		inEl) const;
-
-	int                                     GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt);
-	bool					GetChannelLayouts (AudioUnitScope 		inScope,
+		
+    int                                     GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt);
+	OSStatus				GetChannelLayoutTags (AudioUnitScope 	inScope,
 									AudioUnitElement 				inEl,
 									ChannelTagVector				&outChannelVector) const;
-
+	
+	bool					HasChannelLayout (AudioUnitScope 		inScope, 
+											AudioUnitElement 		inEl) const;
+	
 	OSStatus				GetChannelLayout (AudioUnitScope 		inScope,
 											AudioUnitElement 		inEl,
-											CAAudioChannelLayout	&outLayout) const;
+											CAAudioChannelLayout	&outLayout) const;	
 
-	OSStatus				SetChannelLayout (AudioUnitScope 		inScope,
+	OSStatus				SetChannelLayout (AudioUnitScope 		inScope, 
 											AudioUnitElement 		inEl,
-											CAAudioChannelLayout	&inLayout);
+											const CAAudioChannelLayout	&inLayout);
 
-	OSStatus				SetChannelLayout (AudioUnitScope 		inScope,
+	OSStatus				SetChannelLayout (AudioUnitScope 		inScope, 
 											AudioUnitElement 		inEl,
-											AudioChannelLayout		&inLayout,
+											const AudioChannelLayout		&inLayout,
 											UInt32					inSize);
-
+											
 	OSStatus				ClearChannelLayout (AudioUnitScope		inScope,
 											AudioUnitElement		inEl);
-
+												
 	OSStatus				GetFormat (AudioUnitScope					inScope,
 											AudioUnitElement			inEl,
 											AudioStreamBasicDescription	&outFormat) const;
@@ -257,16 +298,16 @@ public:
 
 	// this sets the sample rate on all in/out buses of the AU
 	OSStatus				SetSampleRate (Float64				inSampleRate);
-
+	
 	OSStatus				NumberChannels (AudioUnitScope		inScope,
 											AudioUnitElement	inEl,
 											UInt32				&outChans) const;
 
 	OSStatus				GetNumberChannels (AudioUnitScope	inScope,
 											AudioUnitElement	inEl,
-											UInt32				&outChans) const
-							{
-								return NumberChannels (inScope, inEl, outChans);
+											UInt32				&outChans) const 
+							{ 
+								return NumberChannels (inScope, inEl, outChans); 
 							}
 
 	OSStatus				SetNumberChannels (AudioUnitScope	inScope,
@@ -278,28 +319,28 @@ public:
 	OSStatus				GetElementCount (AudioUnitScope 	inScope, UInt32 &outCount) const;
 
 	OSStatus				SetElementCount (AudioUnitScope		inScope, UInt32 inCount);
-
+		
 		// value of -1 for outTotalNumChannels indicates no restriction on num channels
-		// for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to
+		// for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to 
 		// any number of channels.
 		// outTotalNumChannels is only valid if method returns true...
 	bool					HasDynamicInputs (SInt32 &outTotalNumChannels) const
 							{
 								return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels);
 							}
-
+							
 	bool					HasDynamicOutputs (SInt32 &outTotalNumChannels) const
 							{
 								return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels);
 							}
-
+	
 		// here, if the in (or out) elements are dynamic, then you supply the number of elements
 		// you want on in (or out) scope, and the number of channels on each consecutive element
 	OSStatus				ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
 							{
 								return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate);
 							}
-
+							
 	OSStatus				ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
 							{
 								return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate);
@@ -310,74 +351,88 @@ public:
 	bool					GetBypass 		() const;
 
 	OSStatus				SetBypass 		(bool				inBypass) const;
-
+	
+	OSStatus				GetMaxFramesPerSlice (UInt32& outMaxFrames) const;
+	
+	OSStatus				SetMaxFramesPerSlice (UInt32 inMaxFrames);
+	
 	Float64					Latency () const;
-
+	
 		// these calls just deal with the global preset state
 		// you could rescope them to deal with presets on the part scope
 	OSStatus				GetAUPreset (CFPropertyListRef &outData) const;
 
 	OSStatus				SetAUPreset (CFPropertyListRef &inData);
+	
+	OSStatus				SetAUPresetFromDocument (CFPropertyListRef &inData);
 
 	OSStatus				GetPresentPreset (AUPreset &outData) const;
-
+	
 	OSStatus				SetPresentPreset (AUPreset &inData);
-
+	
 	bool					HasCustomView () const;
-
-#pragma mark __Print
+	
+#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...
 	CAAudioUnit (const CAComponent& inComp);
 
 	bool				HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const;
-	OSStatus			ConfigureDynamicScope (AudioUnitScope   inScope,
-											UInt32				inNumElements,
-											UInt32				*inChannelsPerElement,
+	OSStatus			ConfigureDynamicScope (AudioUnitScope   inScope, 
+											UInt32				inNumElements, 
+											UInt32				*inChannelsPerElement, 
 											Float64				inSampleRate);
-	bool				ValidateChannelPair (int 				inChannelsIn,
+	bool				ValidateChannelPair (int 				inChannelsIn, 
 											int 				inChannelsOut,
 											const AUChannelInfo * info,
 											UInt32				numChanInfo) const;
-
-	bool				ValidateDynamicScope (AudioUnitScope	inScope,
-											SInt32				&outTotalNumChannels,
-											const AUChannelInfo * info,
+											
+	bool				ValidateDynamicScope (AudioUnitScope	inScope, 
+											SInt32				&outTotalNumChannels, 
+											const AUChannelInfo * info, 
 											UInt32 numInfo) const;
-	bool				CheckOneSide (const CAAUChanHelper		&inHelper,
-											bool				checkOutput,
-											const AUChannelInfo *info,
+	bool				CheckOneSide (const CAAUChanHelper		&inHelper, 
+											bool				checkOutput, 
+											const AUChannelInfo *info, 
 											UInt32				numInfo) const;
-
+	enum {
+			kCAAU_DoNotKnowIfAUNode = -1
+	};
 };
 
 class CAAUChanHelper {
 public:
-				CAAUChanHelper()
-					: mChans(mStaticChans), mNumEls(0), mDidAllocate(false)
+				CAAUChanHelper() 
+					: mChans(mStaticChans), mNumEls(0), mDidAllocate(false) 
 				{
-					memset (mChans, 0, sizeof(UInt32) * 8);
+					memset (mChans, 0, sizeof(UInt32) * kStaticElCount);
 				}
+				CAAUChanHelper(UInt32 inMaxElems);
 				CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope);
-				CAAUChanHelper (const CAAUChanHelper &c) :mChans(mStaticChans), mNumEls(0), mDidAllocate(false) { *this = c; }
-
+				CAAUChanHelper (const CAAUChanHelper &c) 
+					: mChans(mStaticChans), mNumEls(0), mDidAllocate(false) 
+					{ *this = c; }
+				
 				~CAAUChanHelper();
 
 	CAAUChanHelper& operator= (const CAAUChanHelper &c);
 
 	UInt32		* mChans;
 	UInt32		mNumEls;
-
+	
 private:
-	UInt32 mStaticChans[8];
+	enum {
+		kStaticElCount = 8
+	};
+	UInt32 mStaticChans[kStaticElCount];
 	bool mDidAllocate;
 };
 
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h
new file mode 100644
index 0000000..42bebfa
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h
@@ -0,0 +1,143 @@
+/*
+     File: CAAudioUnitOutputCapturer.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAAudioUnitOutputCapturer_h__
+#define __CAAudioUnitOutputCapturer_h__
+
+#include <AudioToolbox/ExtendedAudioFile.h>
+
+/*
+	Class to capture output from an AudioUnit for analysis.
+
+	example:
+
+	CFURL fileurl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/tmp/recording.caf"), kCFURLPOSIXPathStyle, false);
+
+	CAAudioUnitOutputCapturer captor(someAU, fileurl, 'caff', anASBD);
+
+	{
+	captor.Start();
+	...
+	captor.Stop();
+	} // can repeat
+
+	captor.Close(); // can be omitted; happens automatically from destructor
+*/
+
+class CAAudioUnitOutputCapturer {
+public:
+	enum { noErr = 0 };
+
+	CAAudioUnitOutputCapturer(AudioUnit au, CFURLRef outputFileURL, AudioFileTypeID fileType, const AudioStreamBasicDescription &format, UInt32 busNumber = 0) :
+		mFileOpen(false),
+		mClientFormatSet(false),
+		mAudioUnit(au),
+		mExtAudioFile(NULL),
+		mBusNumber (busNumber)
+	{	
+		CFShow(outputFileURL);
+		OSStatus err = ExtAudioFileCreateWithURL(outputFileURL, fileType, &format, NULL, kAudioFileFlags_EraseFile, &mExtAudioFile);
+		if (!err)
+			mFileOpen = true;
+	}
+	
+	void	Start() {
+		if (mFileOpen) {
+			if (!mClientFormatSet) {
+				AudioStreamBasicDescription clientFormat;
+				UInt32 size = sizeof(clientFormat);
+				AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, mBusNumber, &clientFormat, &size);
+				ExtAudioFileSetProperty(mExtAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
+				mClientFormatSet = true;
+			}
+			ExtAudioFileWriteAsync(mExtAudioFile, 0, NULL);	// initialize async writes
+			AudioUnitAddRenderNotify(mAudioUnit, RenderCallback, this);
+		}
+	}
+	
+	void	Stop() {
+		if (mFileOpen)
+			AudioUnitRemoveRenderNotify(mAudioUnit, RenderCallback, this);
+	}
+	
+	void	Close() {
+		if (mExtAudioFile) {
+			ExtAudioFileDispose(mExtAudioFile);
+			mExtAudioFile = NULL;
+		}
+	}
+	
+	~CAAudioUnitOutputCapturer() {
+		Close();
+	}
+
+private:
+	static OSStatus RenderCallback(	void *							inRefCon,
+									AudioUnitRenderActionFlags *	ioActionFlags,
+									const AudioTimeStamp *			inTimeStamp,
+									UInt32							inBusNumber,
+									UInt32							inNumberFrames,
+									AudioBufferList *				ioData)
+	{
+		if (*ioActionFlags & kAudioUnitRenderAction_PostRender) {
+			CAAudioUnitOutputCapturer *This = (CAAudioUnitOutputCapturer *)inRefCon;
+			static int TEMP_kAudioUnitRenderAction_PostRenderError	= (1 << 8);
+			if (This->mBusNumber == inBusNumber && !(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)) {
+				OSStatus result = ExtAudioFileWriteAsync(This->mExtAudioFile, inNumberFrames, ioData);
+				if (result) DebugMessageN1("ERROR WRITING FRAMES: %d\n", (int)result);
+			}
+		}
+		return noErr;
+	}
+	
+	bool				mFileOpen;
+	bool				mClientFormatSet;
+	AudioUnit			mAudioUnit;
+	ExtAudioFileRef		mExtAudioFile;
+	UInt32				mBusNumber;
+};
+
+#endif // __CAAudioUnitOutputCapturer_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp
new file mode 100644
index 0000000..203e437
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp
@@ -0,0 +1,262 @@
+/*
+     File: CAAudioValueRange.cpp
+ Abstract: CAAudioValueRange.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAAudioValueRange.h"
+
+//	Standard Library
+#include <algorithm>
+
+//==================================================================================================
+//	CAAudioValueRange
+//==================================================================================================
+
+Float64	CAAudioValueRange::BoundValue(const AudioValueRange& inRange, Float64 inValue)
+{
+	if (inValue <= inRange.mMinimum)
+	{
+		return inRange.mMinimum;
+	}
+	else if (inValue >= inRange.mMaximum)
+	{
+		return inRange.mMaximum;
+	}
+	else
+	{
+		return inValue;
+	}
+}
+
+Float64 CAAudioValueRange::PickCommonSampleRate(const AudioValueRange& inRange)
+{
+	//  This routine will pick a "common" sample rate from the give range of rates or the maximum
+	//  if no common rates can be found. It assumes that inRange contains a continuous range of
+	//  sample rates.
+	Float64 theAnswer = inRange.mMaximum;
+	
+	if(ContainsValue(inRange, 44100.0))
+	{
+		theAnswer = 44100.0;
+	}
+	else if(ContainsValue(inRange, 48000.0))
+	{
+		theAnswer = 48000.0;
+	}
+	else if(ContainsValue(inRange, 96000.0))
+	{
+		theAnswer = 96000.0;
+	}
+	else if(ContainsValue(inRange, 88200.0))
+	{
+		theAnswer = 88200.0;
+	}
+	else if(ContainsValue(inRange, 64000.0))
+	{
+		theAnswer = 64000.0;
+	}
+	else if(ContainsValue(inRange, 32000.0))
+	{
+		theAnswer = 32000.0;
+	}
+	else if(ContainsValue(inRange, 24000.0))
+	{
+		theAnswer = 24000.0;
+	}
+	else if(ContainsValue(inRange, 22050.0))
+	{
+		theAnswer = 22050.0;
+	}
+	else if(ContainsValue(inRange, 16000.0))
+	{
+		theAnswer = 16000.0;
+	}
+	else if(ContainsValue(inRange, 12000.0))
+	{
+		theAnswer = 12000.0;
+	}
+	else if(ContainsValue(inRange, 11025.0))
+	{
+		theAnswer = 11025.0;
+	}
+	else if(ContainsValue(inRange, 8000.0))
+	{
+		theAnswer = 8000.0;
+	}
+	
+	return theAnswer;
+}
+
+bool	CAAudioValueRange::Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange)
+{
+	bool isNonEmpty;
+	if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y))
+	{
+		outRange.mMinimum = std::max(x.mMinimum, y.mMinimum);
+		outRange.mMaximum = std::min(x.mMaximum, y.mMaximum);
+		isNonEmpty = true;
+	}
+	else
+	{
+		outRange.mMinimum = 0;
+		outRange.mMaximum = 0;
+		isNonEmpty = false;
+	}
+	return isNonEmpty;
+}
+
+bool	CAAudioValueRange::Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange)
+{
+	bool isDisjoint;
+	if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y))
+	{
+		outRange.mMinimum = std::min(x.mMinimum, y.mMinimum);
+		outRange.mMaximum = std::max(x.mMaximum, y.mMaximum);
+		isDisjoint = false;
+	}
+	else
+	{
+		outRange.mMinimum = 0;
+		outRange.mMaximum = 0;
+		isDisjoint = true;
+	}
+	return isDisjoint;
+}
+
+void	CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion)
+{
+	//	this method assumes that the ranges in inRangeList are disjoint and that they are sorted from low to high and
+	outUnion.clear();
+	
+	//	start at the beginning of inRangeList
+	CAAudioValueRangeList::const_iterator theIterator = inRangeList.begin();
+	
+	//	iterate through inRangeList and add all the ranges that are strictly less than inRange
+	while((theIterator != inRangeList.end()) && CAAudioValueRange::IsStrictlyLessThan(*theIterator, inRange))
+	{
+		//	put this range in the union
+		outUnion.push_back(*theIterator);
+		
+		//	go to the next one
+		std::advance(theIterator, 1);
+	}
+	
+	if(theIterator != inRangeList.end())
+	{
+		if(!CAAudioValueRange::IsStrictlyGreaterThan(*theIterator, inRange))
+		{
+			//	inRange intersects the range that theIterator points at, but might actually intersect several contiguous ranges
+			
+			//	initialize the starting point, noting that we can skip the current one since we already know it's in the intersection
+			CAAudioValueRangeList::const_iterator theGreaterIterator = theIterator;
+			std::advance(theGreaterIterator, 1);
+			
+			//	iterate until we find a range that is strictly greater than inRange
+			while((theGreaterIterator != inRangeList.end()) && !CAAudioValueRange::IsStrictlyGreaterThan(*theGreaterIterator, inRange))
+			{
+				//	go to the next one
+				std::advance(theGreaterIterator, 1);
+			}
+			
+			//	theGreaterIterator now points at either one past the highest range in the intersection or the end of the vector
+			//	Either way, we have to adjust it to point at the true highest range in the intersection
+			std::advance(theGreaterIterator, -1);
+			
+			//	now theIterator points at the lowest range in the intersection and theGreaterIterator points at the highest
+			//	so we can compute the coagulated range
+			AudioValueRange theCoagulation;
+			theCoagulation.mMinimum = std::min(theIterator->mMinimum, inRange.mMinimum);
+			theCoagulation.mMaximum = std::max(theGreaterIterator->mMaximum, inRange.mMaximum);
+			
+			//	add the coagulation to the union
+			outUnion.push_back(theCoagulation);
+			
+			//	adjust theIterator to point at the next range for processing
+			theIterator = theGreaterIterator;
+			std::advance(theIterator, 1);
+		}
+		else
+		{
+			//	the range theIterator points at is strictly greater than inRange, so insert inRange in front of it and we're done
+			outUnion.push_back(inRange);
+		}
+			
+		//	we need to now copy the remaining higher ranges in inRangeList into the union
+		while(theIterator != inRangeList.end())
+		{
+			//	put this range in the union
+			outUnion.push_back(*theIterator);
+			
+			//	go to the next one
+			std::advance(theIterator, 1);
+		}
+	}
+	else
+	{
+		//	inRange is larger than all of the ranges in inRangeList, so just add it onto the end of the union and we're done
+		//	This is also the case if inRangeList is empty
+		outUnion.push_back(inRange);
+	}
+}
+
+void	CAAudioValueRange_ComputeIntersection(UInt32 inNumberRangeList1Items, AudioValueRange inRangeList1[], const CAAudioValueRangeList& inRangeList2, CAAudioValueRangeList& outIntersections)
+{
+	outIntersections.clear();
+	for(UInt32 theRangeList1Index = 0; theRangeList1Index < inNumberRangeList1Items; ++theRangeList1Index)
+	{
+		for(CAAudioValueRangeList::const_iterator theRangeList2Iterator = inRangeList2.begin(); theRangeList2Iterator != inRangeList2.end(); std::advance(theRangeList2Iterator, 1))
+		{
+			AudioValueRange theIntersection;
+			if(CAAudioValueRange::Intersection(inRangeList1[theRangeList1Index], *theRangeList2Iterator, theIntersection))
+			{
+				outIntersections.push_back(theIntersection);
+			}
+		}
+	}
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h
new file mode 100644
index 0000000..e17c457
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h
@@ -0,0 +1,121 @@
+/*
+     File: CAAudioValueRange.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAAudioValueRange_h__)
+#define __CAAudioValueRange_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+//	Standard Library Includes
+#include <functional>
+#include <vector>
+
+//=============================================================================
+//	CAAudioValueRange
+//=============================================================================
+
+struct CAAudioValueRange
+:
+	public AudioValueRange
+{
+
+//	Construction/Destruction
+public:
+						CAAudioValueRange()																{ mMinimum = 0.0; mMaximum = 0.0; }
+						CAAudioValueRange(const AudioValueRange& v)										{ mMinimum = v.mMinimum; mMaximum = v.mMaximum; }
+						CAAudioValueRange(Float64 inMinimum, Float64 inMaximum)							{ mMinimum = inMinimum; mMaximum = inMaximum; }
+
+//	Assignment
+public:
+	CAAudioValueRange&	operator=(const AudioValueRange& v)												{ mMinimum = v.mMinimum; mMaximum = v.mMaximum; return *this; }
+
+//  Operations
+public:
+	static bool			ContainsValue(const AudioValueRange& inRange, Float64 inValue)					{ return (inValue >= inRange.mMinimum) && (inValue <= inRange.mMaximum); }
+	static Float64		BoundValue(const AudioValueRange& inRange, Float64 inValue);
+	static Float64		PickCommonSampleRate(const AudioValueRange& inRange);
+	static bool			IsStrictlyLessThan(const AudioValueRange& x, const AudioValueRange& y)			{ return x.mMaximum < y.mMinimum; }
+	static bool			IsStrictlyGreaterThan(const AudioValueRange& x, const AudioValueRange& y)		{ return x.mMinimum > y.mMaximum; }
+	static bool			IsStrictlyContainedBy(const AudioValueRange& x, const AudioValueRange& y)		{ return (x.mMinimum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
+	static bool			OverlapsLow(const AudioValueRange& x, const AudioValueRange& y)					{ return (x.mMinimum < y.mMinimum) && (x.mMaximum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
+	static bool			OverlapsHigh(const AudioValueRange& x, const AudioValueRange& y)				{ return (x.mMinimum >= y.mMinimum) && (x.mMinimum <= y.mMaximum) && (x.mMaximum > y.mMaximum); }
+	static bool			Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);
+	static bool			Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);
+
+//	STL Helpers
+public:
+	struct	LessThan
+	:
+		public std::binary_function<AudioValueRange, AudioValueRange, bool>
+	{
+		bool	operator()(const AudioValueRange& x, const AudioValueRange& y) const
+		{
+			return x.mMinimum < y.mMinimum;
+		}
+	};
+	
+};
+
+inline bool	operator<(const AudioValueRange& x, const AudioValueRange& y)								{ return x.mMinimum < y.mMinimum; }
+inline bool	operator==(const AudioValueRange& x, const AudioValueRange& y)								{ return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool	operator!=(const AudioValueRange& x, const AudioValueRange& y)								{ return !(x == y); }
+inline bool	operator<=(const AudioValueRange& x, const AudioValueRange& y)								{ return (x < y) || (x == y); }
+inline bool	operator>=(const AudioValueRange& x, const AudioValueRange& y)								{ return !(x < y); }
+inline bool	operator>(const AudioValueRange& x, const AudioValueRange& y)								{ return !((x < y) || (x == y)); }
+
+typedef	std::vector<CAAudioValueRange>	CAAudioValueRangeList;
+void	CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion);
+void	CAAudioValueRange_ComputeIntersection(UInt32 inNumberRangeList1Items, AudioValueRange inRangeList1[], const CAAudioValueRangeList& inRangeList2, CAAudioValueRangeList& outIntersections);
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h b/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h
new file mode 100644
index 0000000..2da2415
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h
@@ -0,0 +1,508 @@
+/*
+     File: CAAutoDisposer.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAPtr_h__)
+#define __CAPtr_h__
+
+#include <stdlib.h>		// for malloc
+#include <new>			// for bad_alloc
+#include <string.h>		// for memset
+
+inline void* CA_malloc(size_t size)
+{
+	void* p = malloc(size);
+	if (!p && size) throw std::bad_alloc();
+	return p;
+}
+
+inline void* CA_realloc(void* old, size_t size)
+{
+#if TARGET_OS_WIN32
+	void* p = realloc(old, size);
+#else
+	void* p = reallocf(old, size); // reallocf ensures the old pointer is freed if memory is full (p is NULL).
+#endif
+	if (!p && size) throw std::bad_alloc();
+	return p;
+}
+
+#ifndef UINTPTR_MAX
+#if __LP64__
+#define UINTPTR_MAX	  18446744073709551615ULL
+#else
+#define UINTPTR_MAX	  4294967295U
+#endif
+#endif
+
+inline void* CA_calloc(size_t n, size_t size)
+{	
+	// ensure that multiplication will not overflow
+	if (n && UINTPTR_MAX / n < size) throw std::bad_alloc();
+	
+	size_t nsize = n*size;
+	void* p = malloc(nsize);
+	if (!p && nsize) throw std::bad_alloc();
+
+	memset(p, 0, nsize);
+	return p;
+}
+
+
+// helper class for automatic conversions
+template <typename T>
+struct CAPtrRef
+{
+	T* ptr_;
+
+	explicit CAPtrRef(T* ptr) : ptr_(ptr) {}
+};
+
+template <typename T>
+class CAAutoFree
+{
+private:
+	T* ptr_;
+
+public:
+	
+	CAAutoFree() : ptr_(0) {}
+	
+	explicit CAAutoFree(T* ptr) : ptr_(ptr) {}
+	
+	template<typename U>
+	CAAutoFree(CAAutoFree<U>& that) : ptr_(that.release()) {} // take ownership
+
+	// C++ std says: a template constructor is never a copy constructor
+	CAAutoFree(CAAutoFree<T>& that) : ptr_(that.release()) {} // take ownership
+
+	CAAutoFree(size_t n, bool clear = false) 
+		// this becomes an ambiguous call if n == 0
+		: ptr_(0) 
+		{
+			size_t maxItems = ~size_t(0) / sizeof(T);
+			if (n > maxItems) 
+				throw std::bad_alloc();
+
+			ptr_ = static_cast<T*>(clear ? CA_calloc(n, sizeof(T)) : CA_malloc(n * sizeof(T)));
+		}
+	
+	~CAAutoFree() { free(); }
+	
+	void alloc(size_t numItems, bool clear = false) 
+	{
+		size_t maxItems = ~size_t(0) / sizeof(T);
+		if (numItems > maxItems) throw std::bad_alloc();
+		
+		free();
+		ptr_ = static_cast<T*>(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T)));
+	}
+	
+	void allocBytes(size_t numBytes, bool clear = false) 
+	{
+		free();
+		ptr_ = static_cast<T*>(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes));
+	}
+	
+	void reallocBytes(size_t numBytes) 
+	{
+		ptr_ = static_cast<T*>(CA_realloc(ptr_, numBytes));
+	}
+
+	void reallocItems(size_t numItems) 
+	{
+		size_t maxItems = ~size_t(0) / sizeof(T);
+		if (numItems > maxItems) throw std::bad_alloc();
+		
+		ptr_ = static_cast<T*>(CA_realloc(ptr_, numItems * sizeof(T)));
+	}
+	
+	template <typename U>
+	CAAutoFree& operator=(CAAutoFree<U>& that) 
+	{ 
+		set(that.release());	// take ownership
+		return *this;
+	}
+	
+	CAAutoFree& operator=(CAAutoFree& that) 
+	{ 
+		set(that.release());	// take ownership
+		return *this;
+	}
+	
+	CAAutoFree& operator=(T* ptr) 
+	{
+		set(ptr); 
+		return *this;
+	}
+	
+	template <typename U>
+	CAAutoFree& operator=(U* ptr) 
+	{
+		set(ptr); 
+		return *this;
+	}
+		
+	T& operator*() const { return *ptr_; }
+	T* operator->() const { return ptr_; }
+	
+	T* operator()() const { return ptr_; }
+	T* get() const { return ptr_; }
+	operator T*() const { return ptr_; }
+
+	bool operator==(CAAutoFree const& that) const { return ptr_ == that.ptr_; }
+	bool operator!=(CAAutoFree const& that) const { return ptr_ != that.ptr_; }
+	bool operator==(T* ptr) const { return ptr_ == ptr; }
+	bool operator!=(T* ptr) const { return ptr_ != ptr; }
+		
+	T* release() 
+	{
+		// release ownership
+		T* result = ptr_;
+		ptr_ = 0;
+		return result;
+	}
+	
+	void set(T* ptr)
+	{
+		if (ptr != ptr_)
+		{
+			::free(ptr_);
+			ptr_ = ptr;
+		}
+	}
+	
+	void free() 
+	{
+		set(0);
+	}
+
+
+	// automatic conversions to allow assignment from results of functions.
+	// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+	CAAutoFree(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+	CAAutoFree& operator=(CAPtrRef<T> ref)
+	{
+		set(ref.ptr_);
+		return *this;
+	}
+
+	template<typename U>
+	operator CAPtrRef<U>()
+		{ return CAPtrRef<U>(release()); }
+
+	template<typename U>
+	operator CAAutoFree<U>()
+		{ return CAAutoFree<U>(release()); }
+	
+};
+
+
+template <typename T>
+class CAAutoDelete
+{
+private:
+	T* ptr_;
+
+public:
+	CAAutoDelete() : ptr_(0) {}
+
+	explicit CAAutoDelete(T* ptr) : ptr_(ptr) {}
+	
+	template<typename U>
+	CAAutoDelete(CAAutoDelete<U>& that) : ptr_(that.release()) {} // take ownership
+
+	// C++ std says: a template constructor is never a copy constructor
+	CAAutoDelete(CAAutoDelete<T>& that) : ptr_(that.release()) {} // take ownership
+	
+	~CAAutoDelete() { free(); }
+	
+	template <typename U>
+	CAAutoDelete& operator=(CAAutoDelete<U>& that) 
+	{ 
+		set(that.release());	// take ownership
+		return *this;
+	}
+	
+	CAAutoDelete& operator=(CAAutoDelete& that) 
+	{ 
+		set(that.release());	// take ownership
+		return *this;
+	}
+	
+	CAAutoDelete& operator=(T* ptr) 
+	{
+		set(ptr); 
+		return *this;
+	}
+	
+	template <typename U>
+	CAAutoDelete& operator=(U* ptr) 
+	{
+		set(ptr); 
+		return *this;
+	}
+		
+	T& operator*() const { return *ptr_; }
+	T* operator->() const { return ptr_; }
+	
+	T* operator()() const { return ptr_; }
+	T* get() const { return ptr_; }
+	operator T*() const { return ptr_; }
+	
+	bool operator==(CAAutoDelete const& that) const { return ptr_ == that.ptr_; }
+	bool operator!=(CAAutoDelete const& that) const { return ptr_ != that.ptr_; }
+	bool operator==(T* ptr) const { return ptr_ == ptr; }
+	bool operator!=(T* ptr) const { return ptr_ != ptr; }
+		
+	T* release() 
+	{
+		// release ownership
+		T* result = ptr_;
+		ptr_ = 0;
+		return result;
+	}
+	
+	void set(T* ptr)
+	{
+		if (ptr != ptr_)
+		{
+			delete ptr_;
+			ptr_ = ptr;
+		}
+	}
+	
+	void free() 
+	{
+		set(0);
+	}
+
+
+	// automatic conversions to allow assignment from results of functions.
+	// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+	CAAutoDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+	CAAutoDelete& operator=(CAPtrRef<T> ref)
+	{
+		set(ref.ptr_);
+		return *this;
+	}
+
+	template<typename U>
+	operator CAPtrRef<U>()
+		{ return CAPtrRef<U>(release()); }
+
+	template<typename U>
+	operator CAAutoFree<U>()
+		{ return CAAutoFree<U>(release()); }
+	
+};
+
+
+template <typename T>
+class CAAutoArrayDelete
+{
+private:
+	T* ptr_;
+
+public:
+	CAAutoArrayDelete() : ptr_(0) {}
+
+	explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {}
+	
+	template<typename U>
+	CAAutoArrayDelete(CAAutoArrayDelete<U>& that) : ptr_(that.release()) {} // take ownership
+
+	// C++ std says: a template constructor is never a copy constructor
+	CAAutoArrayDelete(CAAutoArrayDelete<T>& that) : ptr_(that.release()) {} // take ownership
+	
+	// this becomes an ambiguous call if n == 0
+	CAAutoArrayDelete(size_t n) : ptr_(new T[n]) {}
+	
+	~CAAutoArrayDelete() { free(); }
+	
+	void alloc(size_t numItems) 
+	{
+		free();
+		ptr_ = new T [numItems];
+	}
+	
+	template <typename U>
+	CAAutoArrayDelete& operator=(CAAutoArrayDelete<U>& that) 
+	{ 
+		set(that.release());	// take ownership
+		return *this;
+	}
+	
+	CAAutoArrayDelete& operator=(CAAutoArrayDelete& that) 
+	{ 
+		set(that.release());	// take ownership
+		return *this;
+	}
+	
+	CAAutoArrayDelete& operator=(T* ptr) 
+	{
+		set(ptr); 
+		return *this;
+	}
+	
+	template <typename U>
+	CAAutoArrayDelete& operator=(U* ptr) 
+	{
+		set(ptr); 
+		return *this;
+	}
+		
+	T& operator*() const { return *ptr_; }
+	T* operator->() const { return ptr_; }
+	
+	T* operator()() const { return ptr_; }
+	T* get() const { return ptr_; }
+	operator T*() const { return ptr_; }
+
+	bool operator==(CAAutoArrayDelete const& that) const { return ptr_ == that.ptr_; }
+	bool operator!=(CAAutoArrayDelete const& that) const { return ptr_ != that.ptr_; }
+	bool operator==(T* ptr) const { return ptr_ == ptr; }
+	bool operator!=(T* ptr) const { return ptr_ != ptr; }
+		
+	T* release() 
+	{
+		// release ownership
+		T* result = ptr_;
+		ptr_ = 0;
+		return result;
+	}
+	
+	void set(T* ptr)
+	{
+		if (ptr != ptr_)
+		{
+			delete [] ptr_;
+			ptr_ = ptr;
+		}
+	}
+	
+	void free() 
+	{
+		set(0);
+	}
+
+
+	// automatic conversions to allow assignment from results of functions.
+	// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+	CAAutoArrayDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+	CAAutoArrayDelete& operator=(CAPtrRef<T> ref)
+	{
+		set(ref.ptr_);
+		return *this;
+	}
+
+	template<typename U>
+	operator CAPtrRef<U>()
+		{ return CAPtrRef<U>(release()); }
+
+	template<typename U>
+	operator CAAutoArrayDelete<U>()
+		{ return CAAutoFree<U>(release()); }
+	
+};
+
+
+
+
+
+// convenience function
+template <typename T>
+void free(CAAutoFree<T>& p)
+{
+	p.free();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+// example program showing ownership transfer
+
+CAAutoFree<char> source()
+{
+	// source allocates and returns ownership to the caller.
+	const char* str = "this is a test";
+	size_t size = strlen(str) + 1;
+	CAAutoFree<char> captr(size, false);
+	strlcpy(captr(), str, size);
+	printf("source %08X %08X '%s'\n", &captr, captr(), captr());
+	return captr;
+}
+
+void user(CAAutoFree<char> const& captr)
+{
+	// passed by const reference. user can access the pointer but does not take ownership.
+	printf("user: %08X %08X '%s'\n", &captr, captr(), captr());
+}
+
+void sink(CAAutoFree<char> captr)
+{
+	// passed by value. sink takes ownership and frees the pointer on return.
+	printf("sink: %08X %08X '%s'\n", &captr, captr(), captr());
+}
+
+
+int main (int argc, char * const argv[]) 
+{
+
+	CAAutoFree<char> captr(source());
+	printf("main captr A %08X %08X\n", &captr, captr());
+	user(captr);
+	sink(captr);
+	printf("main captr B %08X %08X\n", &captr, captr());
+    return 0;
+}
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h b/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h
new file mode 100644
index 0000000..21cb516
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h
@@ -0,0 +1,206 @@
+/*
+     File: CABitOperations.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef _CABitOperations_h_
+#define _CABitOperations_h_
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+    //#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
+	#include <CoreFoundation/CFBase.h>
+#else
+//	#include <MacTypes.h>
+	#include "CFBase.h"
+#endif
+#include <TargetConditionals.h>
+
+// return whether a number is a power of two
+inline UInt32 IsPowerOfTwo(UInt32 x) 
+{ 
+	return (x & (x-1)) == 0;
+}
+
+// count the leading zeros in a word
+// Metrowerks Codewarrior. powerpc native count leading zeros instruction:
+// I think it's safe to remove this ...
+//#define CountLeadingZeroes(x)  ((int)__cntlzw((unsigned int)x))
+
+inline UInt32 CountLeadingZeroes(UInt32 arg)
+{
+// GNUC / LLVM have a builtin
+#if defined(__GNUC__) || defined(__llvm___)
+#if (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+	if (arg == 0) return 32;
+#endif	// TARGET_CPU_X86 || TARGET_CPU_X86_64
+	return __builtin_clz(arg);
+#elif TARGET_OS_WIN32
+	UInt32 tmp;
+	__asm{
+		bsr eax, arg
+		mov ecx, 63
+		cmovz eax, ecx
+		xor eax, 31
+		mov tmp, eax	// this moves the result in tmp to return.
+    }
+	return tmp;
+#else
+#error "Unsupported architecture"
+#endif	// defined(__GNUC__)
+}
+// Alias (with different spelling)
+#define CountLeadingZeros CountLeadingZeroes
+
+inline UInt32 CountLeadingZeroesLong(UInt64 arg)
+{
+// GNUC / LLVM have a builtin
+#if defined(__GNUC__) || defined(__llvm___)
+#if (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+	if (arg == 0) return 64;
+#endif	// TARGET_CPU_X86 || TARGET_CPU_X86_64
+	return __builtin_clzll(arg);
+#elif TARGET_OS_WIN32
+	UInt32 x = CountLeadingZeroes((UInt32)(arg >> 32));
+	if(x < 32)
+		return x;
+	else
+		return 32+CountLeadingZeroes((UInt32)arg);
+#else
+#error "Unsupported architecture"
+#endif	// defined(__GNUC__)
+}
+#define CountLeadingZerosLong CountLeadingZeroesLong
+
+// count trailing zeroes
+inline UInt32 CountTrailingZeroes(UInt32 x)
+{
+	return 32 - CountLeadingZeroes(~x & (x-1));
+}
+
+// count leading ones
+inline UInt32 CountLeadingOnes(UInt32 x)
+{
+	return CountLeadingZeroes(~x);
+}
+
+// count trailing ones
+inline UInt32 CountTrailingOnes(UInt32 x)
+{
+	return 32 - CountLeadingZeroes(x & (~x-1));
+}
+
+// number of bits required to represent x.
+inline UInt32 NumBits(UInt32 x)
+{
+	return 32 - CountLeadingZeroes(x);
+}
+
+// base 2 log of next power of two greater or equal to x
+inline UInt32 Log2Ceil(UInt32 x)
+{
+	return 32 - CountLeadingZeroes(x - 1);
+}
+
+// base 2 log of next power of two less or equal to x
+inline UInt32 Log2Floor(UInt32 x)
+{
+	return 32 - CountLeadingZeroes(x) - 1;
+}
+
+// next power of two greater or equal to x
+inline UInt32 NextPowerOfTwo(UInt32 x)
+{
+	return 1 << Log2Ceil(x);
+}
+
+// counting the one bits in a word
+inline UInt32 CountOnes(UInt32 x)
+{
+	// secret magic algorithm for counting bits in a word.
+    x = x - ((x >> 1) & 0x55555555);
+    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+    return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
+}
+
+// counting the zero bits in a word
+inline UInt32 CountZeroes(UInt32 x)
+{
+	return CountOnes(~x);
+}
+
+// return the bit position (0..31) of the least significant bit
+inline UInt32 LSBitPos(UInt32 x)
+{
+	return CountTrailingZeroes(x & -(SInt32)x);
+}
+
+// isolate the least significant bit
+inline UInt32 LSBit(UInt32 x)
+{
+	return x & -(SInt32)x;
+}
+
+// return the bit position (0..31) of the most significant bit
+inline UInt32 MSBitPos(UInt32 x)
+{
+	return 31 - CountLeadingZeroes(x);
+}
+
+// isolate the most significant bit
+inline UInt32 MSBit(UInt32 x)
+{
+	return 1 << MSBitPos(x);
+}
+
+// Division optimized for power of 2 denominators
+inline UInt32 DivInt(UInt32 numerator, UInt32 denominator)
+{
+	if(IsPowerOfTwo(denominator))
+		return numerator >> (31 - CountLeadingZeroes(denominator));
+	else
+		return numerator/denominator;
+}
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABool.h b/libs/appleutility/CoreAudio/PublicUtility/CABool.h
new file mode 100644
index 0000000..719fd74
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABool.h
@@ -0,0 +1,89 @@
+/*
+     File: CABool.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CABool_h__)
+#define __CABool_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//=============================================================================
+//	CABool
+//
+//  This class implements a boolean value that has a third state that marks
+//  it as uninitialized. Accessing the value of an instance of this class that
+//  is uninitialized will throw an exception.
+//=============================================================================
+
+class CABool
+{
+
+//	Construction/Destruction
+public:
+					CABool() : mValue(-1) {}
+					CABool(bool inValue) : mValue(inValue ? 1 : 0) {}
+					CABool(const CABool& inValue) : mValue(inValue.mValue) {}
+					~CABool() {}
+					
+	CABool&			operator=(bool inValue) { mValue = inValue; return *this; }
+	CABool&			operator=(const CABool& inValue) { mValue = inValue.mValue; return *this; }
+	
+					operator bool() const { ThrowIf(mValue == -1, CAException('nope'), "CABool: uninitialized"); return mValue != 0; }
+	bool			IsInitialized() const { return mValue != -1; }
+	void			Uninitialize() { mValue = -1; }
+
+private:
+	SInt32			mValue;
+	
+					CABool(const void*);	// prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp
new file mode 100644
index 0000000..3249013
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp
@@ -0,0 +1,259 @@
+/*
+     File: CABufferList.cpp
+ Abstract: CABufferList.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CABufferList.h"
+#include "CAByteOrder.h"
+
+void		CABufferList::AllocateBuffers(UInt32 nBytes)
+{
+	if (nBytes <= GetNumBytes()) return;
+
+	if (mABL.mNumberBuffers > 1)
+		// align successive buffers for Altivec and to take alternating
+		// cache line hits by spacing them by odd multiples of 16
+		nBytes = ((nBytes + 15) & ~15) | 16;
+	UInt32 memorySize = nBytes * mABL.mNumberBuffers;
+	Byte *newMemory = new Byte[memorySize], *p = newMemory;
+	memset(newMemory, 0, memorySize);	// get page faults now, not later
+	
+	AudioBuffer *buf = mABL.mBuffers;
+	for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+		if (buf->mData != NULL && buf->mDataByteSize > 0)
+			// preserve existing buffer contents
+			memcpy(p, buf->mData, buf->mDataByteSize);
+		buf->mDataByteSize = nBytes;
+		buf->mData = p;
+		p += nBytes;
+	}
+	Byte *oldMemory = mBufferMemory;
+	mBufferMemory = newMemory;
+	mBufferCapacity = nBytes;
+	delete[] oldMemory;
+}
+
+void		CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList)
+{
+	if (mABL.mNumberBuffers != inSrcList->mABL.mNumberBuffers) return;
+	if (mABL.mNumberBuffers != inSetPtrList->mABL.mNumberBuffers) return;
+	if (nBytes <= GetNumBytes()) {
+		CopyAllFrom(inSrcList, inSetPtrList);
+		return;
+	}
+	inSetPtrList->VerifyNotTrashingOwnedBuffer();
+	UInt32 fromByteSize = inSrcList->GetNumBytes();
+	
+	if (mABL.mNumberBuffers > 1)
+		// align successive buffers for Altivec and to take alternating
+		// cache line hits by spacing them by odd multiples of 16
+		nBytes = ((nBytes + 15) & ~15) | 16;
+	UInt32 memorySize = nBytes * mABL.mNumberBuffers;
+	Byte *newMemory = new Byte[memorySize], *p = newMemory;
+	memset(newMemory, 0, memorySize);	// make buffer "hot"
+	
+	AudioBuffer *buf = mABL.mBuffers;
+	AudioBuffer *ptrBuf = inSetPtrList->mABL.mBuffers;
+	AudioBuffer *srcBuf = inSrcList->mABL.mBuffers;
+	for (UInt32 i = mABL.mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) {
+		if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0)
+			// preserve existing buffer contents
+			memmove(p, srcBuf->mData, srcBuf->mDataByteSize);
+		buf->mDataByteSize = nBytes;
+		buf->mData = p;
+		ptrBuf->mDataByteSize = srcBuf->mDataByteSize;
+		ptrBuf->mData = p;
+		p += nBytes;
+	}
+	Byte *oldMemory = mBufferMemory;
+	mBufferMemory = newMemory;
+	mBufferCapacity = nBytes;
+	if (inSrcList != inSetPtrList)
+		inSrcList->BytesConsumed(fromByteSize);
+	delete[] oldMemory;
+}
+
+void		CABufferList::DeallocateBuffers()
+{
+	AudioBuffer *buf = mABL.mBuffers;
+	for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+		buf->mData = NULL;
+		buf->mDataByteSize = 0;
+	}
+	if (mBufferMemory != NULL) {
+		delete[] mBufferMemory;
+		mBufferMemory = NULL;
+		mBufferCapacity = 0;
+	}
+    
+}
+
+static void show(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label, const char *fmtstr=NULL)
+{
+	printf("%s %p (%d fr%s):\n", label ? label : "AudioBufferList", &abl, framesToPrint, fmtstr ? fmtstr : "");
+	const AudioBuffer *buf = abl.mBuffers;
+	for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) {
+		printf("    [%2d] %5dbytes %dch @ %p", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+		if (framesToPrint && buf->mData != NULL) {
+			printf(":");
+			Byte *p = (Byte *)buf->mData;
+			for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; )
+				switch (wordSize) {
+				case 0:	// native float
+					printf(" %6.3f", *(Float32 *)p);
+					p += sizeof(Float32);
+					break;
+				// positive: big endian
+				case 1:
+				case -1:
+					printf(" %02X", *p);
+					p += 1;
+					break;
+				case 2:
+					printf(" %04X", CFSwapInt16BigToHost(*(UInt16 *)p));
+					p += 2;
+					break;
+				case 3:
+					printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]);
+					p += 3;
+					break;
+				case 4:
+					printf(" %08X", (unsigned int)CFSwapInt32BigToHost(*(UInt32 *)p));
+					p += 4;
+					break;
+				case 10:
+					printf(" %6.3f", CASwapFloat32BigToHost(*(Float32 *)p));
+					p += sizeof(Float32);
+					break;
+				case -2:
+					printf(" %04X", CFSwapInt16LittleToHost(*(UInt16 *)p));
+					p += 2;
+					break;
+				case -3:
+					printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]);
+					p += 3;
+					break;
+				case -4:
+					printf(" %08X", (unsigned int)CFSwapInt32LittleToHost(*(UInt32 *)p));
+					p += 4;
+					break;
+				case -10:
+					printf(" %6.3f", CASwapFloat32LittleToHost(*(Float32 *)p));
+					p += sizeof(Float32);
+					break;
+				}
+		}
+		printf("\n");
+	}
+}
+
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &asbd, const char *label)
+{
+	CAStreamBasicDescription fmt(asbd);
+	int wordSize = 1;
+	char fmtstr[80] = { 0 };
+	
+	if (fmt.mFormatID == kAudioFormatLinearPCM) {
+		if (fmt.mFormatFlags & kLinearPCMFormatFlagIsFloat) {
+			if (fmt.mBitsPerChannel == 32) {
+				if (fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) {
+					wordSize = 10;
+					strlcpy(fmtstr, ", BEF", sizeof(fmtstr));
+				} else {
+					wordSize = -10;
+					strlcpy(fmtstr, ", LEF", sizeof(fmtstr));
+				}
+			}
+		} else {
+			wordSize = fmt.SampleWordSize();
+			if (wordSize > 0) {
+				int fracbits = (asbd.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+				if (fracbits > 0)
+					snprintf(fmtstr, sizeof(fmtstr), ", %d.%d-bit", (int)asbd.mBitsPerChannel - fracbits, fracbits);
+				else
+					snprintf(fmtstr, sizeof(fmtstr), ", %d-bit", (int)asbd.mBitsPerChannel);
+
+				if (!(fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)) {
+					wordSize = -wordSize;
+					strlcat(fmtstr, " LEI", sizeof(fmtstr));
+				} else {
+					strlcat(fmtstr, " BEI", sizeof(fmtstr));
+				}
+			}
+		}
+	}
+	show(abl, framesToPrint, wordSize, label, fmtstr);
+}
+
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label)
+{
+	show(abl, framesToPrint, wordSize, label);
+}
+
+extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize)
+{
+	show(*abl, framesToPrint, wordSize, NULL);
+}
+
+// if the return result is odd, there was a null buffer.
+extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullok)
+{
+	const AudioBuffer *buf = abl->mBuffers, *bufend = buf + abl->mNumberBuffers;
+	int sum = 0;	// defeat attempts by the compiler to optimize away the code that touches the buffers
+	int anyNull = 0;
+	for ( ; buf < bufend; ++buf) {
+		const int *p = (const int *)buf->mData;
+		if (p == NULL) {
+			anyNull = 1;
+			if (nullok) continue;
+		}
+		unsigned datasize = buf->mDataByteSize;
+		if (datasize >= sizeof(int) && p != NULL) {
+			sum += p[0];
+			sum += p[datasize / sizeof(int) - 1];
+		}
+	}
+	return anyNull | (sum & ~1);
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h
new file mode 100644
index 0000000..72c93f8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h
@@ -0,0 +1,324 @@
+/*
+     File: CABufferList.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CABufferList_h__
+#define __CABufferList_h__
+
+#include <stddef.h>
+#include "CAStreamBasicDescription.h"
+#include "CAXException.h"
+
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &fmt, const char *label=NULL);
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label=NULL);
+extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize);
+extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullOK=false);
+
+/* ____________________________________________________________________________
+//	CABufferList - variable length buffer list
+
+	This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
+	is preferred.
+	
+	CABufferList can be used in one of two ways:
+		- as mutable pointers into non-owned memory
+		- as an immutable array of buffers (owns its own memory).
+
+ 	All buffers are assumed to have the same format (number of channels, word size), so that
+		we can assume their mDataByteSizes are all the same.
+____________________________________________________________________________ */
+class CABufferList {
+public:
+	void *	operator new(size_t /*size*/, int nBuffers) {
+				return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
+			}
+	static CABufferList *	New(const char *name, const CAStreamBasicDescription &format)
+	{
+		UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels();
+		return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
+	}
+	static CABufferList *	New(const CAStreamBasicDescription &format) { return New("", format); }
+
+	static CABufferList *	New(UInt32 numBuffers, UInt32 channelsPerBuffer, const char *name="") {
+		return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
+	}
+
+protected:
+	CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) :
+		mName(name),
+		mBufferMemory(NULL),
+		mBufferCapacity(0)
+	{
+		//XAssert(numBuffers > 0 /*&& channelsPerBuffer > 0*/);
+		mABL.mNumberBuffers = numBuffers;
+		AudioBuffer *buf = mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+			buf->mNumberChannels = channelsPerBuffer;
+			buf->mDataByteSize = 0;
+			buf->mData = NULL;
+		}
+	}
+
+public:
+	~CABufferList()
+	{
+		if (mBufferMemory)
+			delete[] mBufferMemory;
+	}
+	
+	const char *				Name() { return mName; }
+	
+	const AudioBufferList &		GetBufferList() const { return mABL; }
+	
+	AudioBufferList &			GetModifiableBufferList() { return _GetBufferList(); }
+	
+	UInt32		GetNumberBuffers() const { return mABL.mNumberBuffers; }
+	
+	UInt32		GetNumBytes() const
+	{
+		return mABL.mBuffers[0].mDataByteSize;
+	}
+	
+	void		SetBytes(UInt32 nBytes, void *data)
+	{
+		VerifyNotTrashingOwnedBuffer();
+		XAssert(mABL.mNumberBuffers == 1);
+		mABL.mBuffers[0].mDataByteSize = nBytes;
+		mABL.mBuffers[0].mData = data;
+	}
+	
+	void		CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl)
+					// copies bytes from srcbl
+					// make ptrbl reflect the length copied
+					// note that srcbl may be same as ptrbl!
+	{
+		// Note that this buffer *can* own memory and its pointers/lengths are not
+		// altered; only its buffer contents, which are copied from srcbl.
+		// The pointers/lengths in ptrbl are updated to reflect the addresses/lengths
+		// of the copied data, and srcbl's contents are consumed.
+		ptrbl->VerifyNotTrashingOwnedBuffer();
+		UInt32 nBytes = srcbl->GetNumBytes();
+		AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = srcbl->mABL.mBuffers,
+					*ptrbuf = ptrbl->mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) {
+			memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
+			ptrbuf->mData = mybuf->mData;
+			ptrbuf->mDataByteSize = srcbuf->mDataByteSize;
+		}
+		if (srcbl != ptrbl)
+			srcbl->BytesConsumed(nBytes);
+	}
+	
+	// copies data from another buffer list.
+	void		CopyDataFrom(const AudioBufferList &other)
+	{
+		for (unsigned i = 0; i < other.mNumberBuffers; ++i) {
+			XAssert(mBufferCapacity == 0 || other.mBuffers[i].mDataByteSize <= mBufferCapacity);
+			memcpy(mABL.mBuffers[i].mData, other.mBuffers[i].mData, 
+				mABL.mBuffers[i].mDataByteSize = other.mBuffers[i].mDataByteSize);
+		}
+	}
+	
+	void		AppendFrom(CABufferList *blp, UInt32 nBytes)
+	{
+		// this may mutate a buffer that owns memory.
+		AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = blp->mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) {
+			XAssert(nBytes <= srcbuf->mDataByteSize);
+			XAssert(mBufferCapacity == 0 || mybuf->mDataByteSize + nBytes <= mBufferCapacity);
+			memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes);
+			mybuf->mDataByteSize += nBytes;
+		}
+		blp->BytesConsumed(nBytes);
+	}
+	
+	void		PadWithZeroes(UInt32 desiredBufferSize)
+					// for cases where an algorithm (e.g. SRC) requires some
+					// padding to create silence following end-of-file
+	{
+		XAssert(mBufferCapacity == 0 || desiredBufferSize <= mBufferCapacity);
+		if (GetNumBytes() > desiredBufferSize) return;
+		AudioBuffer *buf = mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+			memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize);
+			buf->mDataByteSize = desiredBufferSize;
+		}
+	}
+	
+	void		SetToZeroes(UInt32 nBytes)
+	{
+		XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity);
+		AudioBuffer *buf = mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+			memset((Byte *)buf->mData, 0, nBytes);
+			buf->mDataByteSize = nBytes;
+		}
+	}
+	
+	void		Reset()
+	{
+		DeallocateBuffers();
+	}
+	
+	Boolean		SameDataAs(const CABufferList* anotherBufferList)
+	{
+		// check to see if two buffer lists point to the same memory.
+		if (mABL.mNumberBuffers != anotherBufferList->mABL.mNumberBuffers) return false;
+		
+		for (UInt32 i = 0; i < mABL.mNumberBuffers; ++i) {
+			if (mABL.mBuffers[i].mData != anotherBufferList->mABL.mBuffers[i].mData) return false;
+		}
+		return true;
+	}
+	
+	void		BytesConsumed(UInt32 nBytes)
+					// advance buffer pointers, decrease buffer sizes
+	{
+		VerifyNotTrashingOwnedBuffer();
+		AudioBuffer *buf = mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+			XAssert(nBytes <= buf->mDataByteSize);
+			buf->mData = (Byte *)buf->mData + nBytes;
+			buf->mDataByteSize -= nBytes;
+		}
+	}
+	
+	void		SetFrom(const AudioBufferList *abl)
+	{
+		VerifyNotTrashingOwnedBuffer();
+		memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
+	}
+	
+	void		SetFrom(const CABufferList *blp)
+	{
+		SetFrom(&blp->GetBufferList());
+	}
+	
+	void		SetFrom(const AudioBufferList *abl, UInt32 nBytes)
+	{
+		VerifyNotTrashingOwnedBuffer();
+		AudioBuffer *mybuf = mABL.mBuffers;
+		const AudioBuffer *srcbuf = abl->mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) {
+			mybuf->mNumberChannels = srcbuf->mNumberChannels;
+			mybuf->mDataByteSize = nBytes;
+			mybuf->mData = srcbuf->mData;
+		}
+	}
+	
+	void		SetFrom(const CABufferList *blp, UInt32 nBytes)
+	{
+		SetFrom(&blp->GetBufferList(), nBytes);
+	}
+	
+	AudioBufferList *	ToAudioBufferList(AudioBufferList *abl) const
+	{
+		memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mABL.mNumberBuffers] - (char *)abl);
+		return abl;
+	}
+	
+	void		AllocateBuffers(UInt32 nBytes);
+	void		AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList);
+	
+	void		DeallocateBuffers();
+	
+	void		UseExternalBuffer(Byte *ptr, UInt32 nBytes);
+    
+	void		AdvanceBufferPointers(UInt32 nBytes) // $$$ ReducingSize
+					// this is for bufferlists that function simply as
+					// an array of pointers into another bufferlist, being advanced,
+					// as in RenderOutput implementations
+	{
+		VerifyNotTrashingOwnedBuffer();
+		AudioBuffer *buf = mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+			buf->mData = (Byte *)buf->mData + nBytes;
+			buf->mDataByteSize -= nBytes;
+		}
+	}
+	
+	void		SetNumBytes(UInt32 nBytes)
+	{
+		XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity);
+		AudioBuffer *buf = mABL.mBuffers;
+		for (UInt32 i = mABL.mNumberBuffers; i--; ++buf)
+			buf->mDataByteSize = nBytes;
+	}
+
+	void		Print(const char *label=NULL, int nframes=0, int wordSize=0) const
+	{
+		if (label == NULL)
+			label = mName;
+		printf("%s - ", label);
+		CAShowAudioBufferList(&GetBufferList(), nframes, wordSize);
+		if (mBufferMemory)
+			printf("  owned memory @ 0x%p:\n", mBufferMemory);
+	}
+	
+	UInt32		GetCapacityBytes() const { return mBufferCapacity; }
+	
+	template <typename T>
+	T*			GetData(UInt32 inBuffer) {
+		return static_cast<T*>(mABL.mBuffers[inBuffer].mData);
+	}
+
+protected:
+	AudioBufferList &	_GetBufferList() { return mABL; }	// use with care
+							// if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer
+	void				VerifyNotTrashingOwnedBuffer()
+	{
+		// This needs to be called from places where we are modifying the buffer pointers.
+		// It's an error to modify the buffer pointers or lengths if we own the buffer memory.
+		XAssert(mBufferMemory == NULL);
+	}
+
+	const char *						mName;	// for debugging
+	Byte *								mBufferMemory;
+	UInt32								mBufferCapacity;	// max mDataByteSize of each buffer
+	AudioBufferList						mABL;
+	// don't add anything here
+};
+
+#endif // __CABufferList_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp
new file mode 100644
index 0000000..2161be7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp
@@ -0,0 +1,84 @@
+/*
+     File: CABundleLocker.cpp
+ Abstract: CABundleLocker.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CABundleLocker.h"
+#include <pthread.h>
+
+/*
+some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
+*/
+
+static pthread_mutex_t sCABundleLocker = PTHREAD_MUTEX_INITIALIZER;
+
+#define RECURSIVE_LOCK 0
+
+#if RECURSIVE_LOCK
+static pthread_once_t sOnce = PTHREAD_ONCE_INIT;
+
+static void InitCABundleLocker()
+{
+	// have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
+	pthread_mutexattr_t attr;
+	pthread_mutexattr_init(&attr);
+	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+	pthread_mutex_init(&sCABundleLocker, &attr);
+	pthread_mutexattr_destroy(&attr);
+}
+#endif
+
+CABundleLocker::CABundleLocker()
+{
+#if RECURSIVE_LOCK
+	pthread_once(&sOnce, InitCABundleLocker);
+#endif
+	pthread_mutex_lock(&sCABundleLocker);
+}
+
+CABundleLocker::~CABundleLocker()
+{
+	pthread_mutex_unlock(&sCABundleLocker);
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h
new file mode 100644
index 0000000..821ca34
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h
@@ -0,0 +1,69 @@
+/*
+     File: CABundleLocker.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef _CABundleLocker_h_
+#define _CABundleLocker_h_
+
+#include <TargetConditionals.h>
+ 
+/*
+some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
+*/
+
+class CABundleLocker
+{
+public:
+
+#if TARGET_OS_MAC
+	CABundleLocker();
+	~CABundleLocker();
+#else
+	CABundleLocker() {}
+	~CABundleLocker() {}
+#endif
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h b/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h
new file mode 100644
index 0000000..9a56c6d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h
@@ -0,0 +1,161 @@
+/*
+     File: CAByteOrder.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAByteOrder_h__)
+#define __CAByteOrder_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include "CoreFoundation.h"
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+CF_INLINE Float32 CASwapFloat32 (Float32 arg) {
+	union {
+		Float32 f;
+		UInt32 i;
+	} flip;
+
+	flip.f = arg;
+	flip.i = CFSwapInt32 (flip.i);
+	
+	return flip.f;
+}
+
+CF_INLINE Float64 CASwapFloat64 (Float64 arg) {
+	union {
+		Float64 f;
+		UInt64 i;
+	} flip;
+
+	flip.f = arg;
+	flip.i = CFSwapInt64 (flip.i);
+	
+	return flip.f;
+}
+
+#pragma mark -Flippers
+
+CF_INLINE Float32 CASwapFloat32BigToHost(Float32 arg) {
+#if defined(__BIG_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64BigToHost(Float64 arg) {
+#if defined(__BIG_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32HostToBig(Float32 arg) {
+#if defined(__BIG_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64HostToBig(Float64 arg) {
+#if defined(__BIG_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32LittleToHost(Float32 arg) {
+#if defined(__LITTLE_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64LittleToHost(Float64 arg) {
+#if defined(__LITTLE_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32HostToLittle(Float32 arg) {
+#if defined(__LITTLE_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64HostToLittle(Float64 arg) {
+#if defined(__LITTLE_ENDIAN__)
+    return arg;
+#else
+	return CASwapFloat64(arg);
+#endif
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp
new file mode 100644
index 0000000..e7c057d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp
@@ -0,0 +1,821 @@
+/*
+     File: CACFArray.cpp
+ Abstract: CACFArray.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	Self Include
+#include "CACFArray.h"
+
+//	PublicUtility Includes
+#include "CACFDictionary.h"
+#include "CACFNumber.h"
+#include "CACFString.h"
+
+//=============================================================================
+//	CACFArray
+//=============================================================================
+
+bool	CACFArray::HasItem(const void* inItem) const
+{
+	bool theAnswer = false;
+	if(mCFArray != NULL)
+	{
+		CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
+		theAnswer = CFArrayContainsValue(mCFArray, theRange, inItem);
+	}
+	return theAnswer;
+}
+
+bool	CACFArray::GetIndexOfItem(const void* inItem, UInt32& outIndex) const
+{
+	bool theAnswer = false;
+	outIndex = 0;
+	if(mCFArray != NULL)
+	{
+		CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
+		CFIndex theIndex = CFArrayGetFirstIndexOfValue(mCFArray, theRange, inItem);
+		if(theIndex != -1)
+		{
+			theAnswer = true;
+			outIndex = ToUInt32(theIndex);
+		}
+	}
+	return theAnswer;
+}
+
+bool	CACFArray::GetBool(UInt32 inIndex, bool& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inIndex, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
+		{
+			outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+			theAnswer = true;
+		}
+		else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			SInt32 theNumericValue = 0;
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+			outValue = theNumericValue != 0;
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetSInt32(UInt32 inIndex, SInt32& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetUInt32(UInt32 inIndex, UInt32& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetSInt64(UInt32 inIndex, SInt64& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetUInt64(UInt32 inIndex, UInt64& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetFloat32(UInt32 inIndex, Float32& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat32Type, &outItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetFloat64(UInt32 inIndex, Float64& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat64Type, &outItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::Get4CC(UInt32 inIndex, UInt32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inIndex, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+			theAnswer = true;
+		}
+		else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+		{
+			CFStringRef theString = static_cast<CFStringRef>(theValue);
+			if(CFStringGetLength(theString) == 4)
+			{
+				char theCString[5];
+				CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII);
+				outValue = CFSwapInt32BigToHost(*reinterpret_cast<UInt32*>(theCString));
+			}
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetString(UInt32 inIndex, CFStringRef& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
+		{
+			outItem = static_cast<CFStringRef>(theItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetArray(UInt32 inIndex, CFArrayRef& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
+		{
+			outItem = static_cast<CFArrayRef>(theItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
+		{
+			outItem = static_cast<CFDictionaryRef>(theItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetData(UInt32 inIndex, CFDataRef& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFDataGetTypeID()))
+		{
+			outItem = static_cast<CFDataRef>(theItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFUUIDGetTypeID()))
+		{
+			outItem = static_cast<CFUUIDRef>(theItem);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::GetCFType(UInt32 inIndex, CFTypeRef& outItem) const
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && (inIndex < GetNumberItems()))
+	{
+		outItem = CFArrayGetValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex));
+		theAnswer = outItem != NULL;
+	}
+	
+	return theAnswer;
+}
+
+void	CACFArray::GetCACFString(UInt32 inIndex, CACFString& outItem) const
+{
+	outItem = static_cast<CFStringRef>(NULL);
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
+		{
+			outItem = static_cast<CFStringRef>(theItem);
+		}
+	}
+}
+
+void	CACFArray::GetCACFArray(UInt32 inIndex, CACFArray& outItem) const
+{
+	outItem = static_cast<CFArrayRef>(NULL);
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
+		{
+			outItem = static_cast<CFArrayRef>(theItem);
+		}
+	}
+}
+
+void	CACFArray::GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const
+{
+	outItem = static_cast<CFDictionaryRef>(NULL);
+	CFTypeRef theItem = NULL;
+	if(GetCFType(inIndex, theItem))
+	{
+		if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
+		{
+			outItem = static_cast<CFDictionaryRef>(theItem);
+		}
+	}
+}
+
+bool	CACFArray::AppendBool(bool inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFBoolean theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = AppendCFType(theItem.GetCFBoolean());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::AppendSInt32(SInt32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = AppendCFType(theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::AppendUInt32(UInt32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = AppendCFType(theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::AppendSInt64(SInt64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = AppendCFType(theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::AppendUInt64(UInt64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = AppendCFType(theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::AppendFloat32(Float32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = AppendCFType(theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::AppendFloat64(Float64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = AppendCFType(theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::AppendString(const CFStringRef inItem)
+{
+	return AppendCFType(inItem);
+}
+
+bool	CACFArray::AppendArray(const CFArrayRef inItem)
+{
+	return AppendCFType(inItem);
+}
+
+bool	CACFArray::AppendDictionary(const CFDictionaryRef inItem)
+{
+	return AppendCFType(inItem);
+}
+
+bool	CACFArray::AppendData(const CFDataRef inItem)
+{
+	return AppendCFType(inItem);
+}
+
+bool	CACFArray::AppendCFType(const CFTypeRef inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CFArrayAppendValue(mCFArray, inItem);
+		theAnswer = true;
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertBool(UInt32 inIndex, bool inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFBoolean theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = InsertCFType(inIndex, theItem.GetCFBoolean());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertSInt32(UInt32 inIndex, SInt32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertUInt32(UInt32 inIndex, UInt32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertSInt64(UInt32 inIndex, SInt64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertUInt64(UInt32 inIndex, UInt64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertFloat32(UInt32 inIndex, Float32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertFloat64(UInt32 inIndex, Float64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::InsertString(UInt32 inIndex, const CFStringRef inItem)
+{
+	return InsertCFType(inIndex, inItem);
+}
+
+bool	CACFArray::InsertArray(UInt32 inIndex, const CFArrayRef inItem)
+{
+	return InsertCFType(inIndex, inItem);
+}
+
+bool	CACFArray::InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem)
+{
+	return InsertCFType(inIndex, inItem);
+}
+
+bool	CACFArray::InsertData(UInt32 inIndex, const CFDataRef inItem)
+{
+	return InsertCFType(inIndex, inItem);
+}
+
+bool	CACFArray::InsertCFType(UInt32 inIndex, const CFTypeRef inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable)
+	{
+		if(inIndex < GetNumberItems())
+		{
+			CFArrayInsertValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex), inItem);
+		}
+		else
+		{
+			CFArrayAppendValue(mCFArray, inItem);
+		}
+		theAnswer = true;
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetBool(UInt32 inIndex, bool inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CACFBoolean theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = SetCFType(inIndex, theItem.GetCFBoolean());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetSInt32(UInt32 inIndex, SInt32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetUInt32(UInt32 inIndex, UInt32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetSInt64(UInt32 inIndex, SInt64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetUInt64(UInt32 inIndex, UInt64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetFloat32(UInt32 inIndex, Float32 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetFloat64(UInt32 inIndex, Float64 inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CACFNumber theItem(inItem);
+		if(theItem.IsValid())
+		{
+			theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFArray::SetString(UInt32 inIndex, const CFStringRef inItem)
+{
+	return SetCFType(inIndex, inItem);
+}
+
+bool	CACFArray::SetArray(UInt32 inIndex, const CFArrayRef inItem)
+{
+	return SetCFType(inIndex, inItem);
+}
+
+bool	CACFArray::SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem)
+{
+	return SetCFType(inIndex, inItem);
+}
+
+bool	CACFArray::SetData(UInt32 inIndex, const CFDataRef inItem)
+{
+	return SetCFType(inIndex, inItem);
+}
+
+bool	CACFArray::SetCFType(UInt32 inIndex, const CFTypeRef inItem)
+{
+	bool theAnswer = false;
+	
+	if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+	{
+		CFArraySetValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex), inItem);
+		theAnswer = true;
+	}
+	
+	return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h
new file mode 100644
index 0000000..89c8c55
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h
@@ -0,0 +1,195 @@
+/*
+     File: CACFArray.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFArray_h__)
+#define __CACFArray_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include <CoreAudioTypes.h>
+	#include <CoreFoundation.h>
+#endif
+
+#include "CADebugMacros.h"
+
+//=============================================================================
+//	Types
+//=============================================================================
+
+class	CACFDictionary;
+class	CACFString;
+
+//=============================================================================
+//	CACFArray
+//=============================================================================
+
+class CACFArray
+{
+
+//	Construction/Destruction
+public:
+						CACFArray()																	: mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(true), mMutable(true) {}
+	explicit			CACFArray(bool inRelease)													: mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
+						CACFArray(UInt32 inMaxNumberItems, bool inRelease)							: mCFArray(CFArrayCreateMutable(NULL, static_cast<CFIndex>(inMaxNumberItems), &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
+						CACFArray(CFArrayRef inCFArray, bool inRelease)								: mCFArray(const_cast<CFMutableArrayRef>(inCFArray)), mRelease(inRelease), mMutable(false) {}
+						CACFArray(CFMutableArrayRef inCFArray, bool inRelease)						: mCFArray(inCFArray), mRelease(inRelease), mMutable(true) {}
+						CACFArray(const CACFArray& inArray)											: mCFArray(inArray.mCFArray), mRelease(inArray.mRelease), mMutable(inArray.mMutable) { Retain(); }
+	CACFArray&			operator=(const CACFArray& inArray)											{ Release(); mCFArray = inArray.mCFArray; mRelease = inArray.mRelease; mMutable = inArray.mMutable; Retain(); return *this; }
+	CACFArray&			operator=(CFArrayRef inCFArray)												{ Release(); mCFArray = const_cast<CFMutableArrayRef>(inCFArray); mMutable = false; Retain(); return *this; }
+	CACFArray&			operator=(CFMutableArrayRef inCFArray)										{ Release(); mCFArray = inCFArray; mMutable = true; Retain(); return *this; }
+						~CACFArray()																{ Release(); }
+
+private:
+	void				Retain()																	{ if(mRelease && (mCFArray != NULL)) { CFRetain(mCFArray); } }
+	void				Release()																	{ if(mRelease && (mCFArray != NULL)) { CFRelease(mCFArray); } }
+		
+//	Attributes
+public:
+	bool				IsValid() const																{ return mCFArray != NULL; }
+	bool				IsMutable() const															{ return mMutable; }
+	bool				CanModify() const															{ return mMutable && (mCFArray != NULL); }
+	
+	bool				WillRelease() const															{ return mRelease; }
+	void				ShouldRelease(bool inRelease)												{ mRelease = inRelease; }
+	
+	CFTypeID			GetTypeID() const															{ return CFGetTypeID(mCFArray); }
+	
+	CFArrayRef			GetCFArray() const															{ return mCFArray; }
+	CFArrayRef			CopyCFArray() const															{ if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
+	
+	CFMutableArrayRef	GetCFMutableArray() const													{ return mCFArray; }
+	CFMutableArrayRef	CopyCFMutableArray() const													{ if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
+	CFPropertyListRef   AsPropertyList() const														{ return mCFArray; }
+
+	void				SetCFMutableArrayFromCopy(CFArrayRef inArray, bool inRelease = true)		{ Release(); mCFArray = CFArrayCreateMutableCopy(NULL, 0, inArray); mMutable = true; mRelease = inRelease; }
+
+//	Item Operations
+public:
+	UInt32				GetNumberItems() const														{ UInt32 theAnswer = 0; if(mCFArray != NULL) { theAnswer = ToUInt32(CFArrayGetCount(mCFArray)); } return theAnswer; }
+	bool				HasItem(const void* inItem) const;
+	void				RemoveItem(const void* inItem)												{ UInt32 theIndex; if(CanModify() && GetIndexOfItem(inItem, theIndex)) { RemoveItemAtIndex(theIndex); } }
+	bool				GetIndexOfItem(const void* inItem, UInt32& outIndex) const;
+	void				RemoveItemAtIndex(UInt32 inIndex)											{ if(CanModify()) { CFArrayRemoveValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex)); } }
+	void				Clear()																		{ if(CanModify()) { CFArrayRemoveAllValues(mCFArray); } }
+	void				Sort(CFComparatorFunction inCompareFunction)								{ if(CanModify()) { CFRange theRange = { 0, CFArrayGetCount(mCFArray) }; CFArraySortValues(mCFArray, theRange, inCompareFunction, NULL); } }
+	void				SortNumbers()																{ Sort((CFComparatorFunction)CFNumberCompare); }
+	void				SortStrings()																{ Sort((CFComparatorFunction)CFStringCompare); }
+	
+	bool				GetBool(UInt32 inIndex, bool& outValue) const;
+	bool				GetSInt32(UInt32 inIndex, SInt32& outItem) const;
+	bool				GetUInt32(UInt32 inIndex, UInt32& outItem) const;
+	bool				GetSInt64(UInt32 inIndex, SInt64& outItem) const;
+	bool				GetUInt64(UInt32 inIndex, UInt64& outItem) const;
+	bool				GetFloat32(UInt32 inIndex, Float32& outItem) const;
+	bool				GetFloat64(UInt32 inIndex, Float64& outItem) const;
+	bool				Get4CC(UInt32 inIndex, UInt32& outValue) const;
+	bool				GetString(UInt32 inIndex, CFStringRef& outItem) const;
+	bool				GetArray(UInt32 inIndex, CFArrayRef& outItem) const;
+	bool				GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const;
+	bool				GetData(UInt32 inIndex, CFDataRef& outItem) const;
+	bool				GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const;
+	bool				GetCFType(UInt32 inIndex, CFTypeRef& outItem) const;
+	
+	void				GetCACFString(UInt32 inIndex, CACFString& outItem) const;
+	void				GetCACFArray(UInt32 inIndex, CACFArray& outItem) const;
+	void				GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const;
+	
+	bool				AppendBool(bool inItem);
+	bool				AppendSInt32(SInt32 inItem);
+	bool				AppendUInt32(UInt32 inItem);
+	bool				AppendSInt64(SInt64 inItem);
+	bool				AppendUInt64(UInt64 inItem);
+	bool				AppendFloat32(Float32 inItem);
+	bool				AppendFloat64(Float64 inItem);
+	bool				AppendString(const CFStringRef inItem);
+	bool				AppendArray(const CFArrayRef inItem);
+	bool				AppendDictionary(const CFDictionaryRef inItem);
+	bool				AppendData(const CFDataRef inItem);
+	bool				AppendCFType(const CFTypeRef inItem);
+	
+	bool				InsertBool(UInt32 inIndex, bool inItem);
+	bool				InsertSInt32(UInt32 inIndex, SInt32 inItem);
+	bool				InsertUInt32(UInt32 inIndex, UInt32 inItem);
+	bool				InsertSInt64(UInt32 inIndex, SInt64 inItem);
+	bool				InsertUInt64(UInt32 inIndex, UInt64 inItem);
+	bool				InsertFloat32(UInt32 inIndex, Float32 inItem);
+	bool				InsertFloat64(UInt32 inIndex, Float64 inItem);
+	bool				InsertString(UInt32 inIndex, const CFStringRef inItem);
+	bool				InsertArray(UInt32 inIndex, const CFArrayRef inItem);
+	bool				InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
+	bool				InsertData(UInt32 inIndex, const CFDataRef inItem);
+	bool				InsertCFType(UInt32 inIndex, const CFTypeRef inItem);
+	
+	bool				SetBool(UInt32 inIndex, bool inItem);
+	bool				SetSInt32(UInt32 inIndex, SInt32 inItem);
+	bool				SetUInt32(UInt32 inIndex, UInt32 inItem);
+	bool				SetSInt64(UInt32 inIndex, SInt64 inItem);
+	bool				SetUInt64(UInt32 inIndex, UInt64 inItem);
+	bool				SetFloat32(UInt32 inIndex, Float32 inItem);
+	bool				SetFloat64(UInt32 inIndex, Float64 inItem);
+	bool				SetString(UInt32 inIndex, const CFStringRef inItem);
+	bool				SetArray(UInt32 inIndex, const CFArrayRef inItem);
+	bool				SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
+	bool				SetData(UInt32 inIndex, const CFDataRef inItem);
+	bool				SetCFType(UInt32 inIndex, const CFTypeRef inItem);
+
+//	Implementation
+private:
+	CFMutableArrayRef	mCFArray;
+	bool				mRelease;
+	bool				mMutable;
+	
+						CACFArray(const void*);	// prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFData.h b/libs/appleutility/CoreAudio/PublicUtility/CACFData.h
new file mode 100644
index 0000000..7ce08dc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFData.h
@@ -0,0 +1,108 @@
+/*
+     File: CACFData.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFData_h__)
+#define __CACFData_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <CoreFoundation/CFData.h>
+#else
+	#include <CoreAudioTypes.h>
+	#include <CFData.h>
+#endif
+
+#include "CADebugMacros.h"
+
+//=============================================================================
+//	CACFData
+//=============================================================================
+
+class CACFData
+{
+
+//	Construction/Destruction
+public:
+	explicit	CACFData(CFDataRef inCFData) : mCFData(inCFData), mWillRelease(true) {}
+				CACFData(CFDataRef inCFData, bool inWillRelease) : mCFData(inCFData), mWillRelease(inWillRelease) {}
+				CACFData(const void* inData, UInt32 inDataSize) : mCFData(NULL), mWillRelease(true) { mCFData = CFDataCreate(NULL, static_cast<const UInt8*>(inData), static_cast<CFIndex>(inDataSize)); }
+				~CACFData() { Release(); }
+				CACFData(const CACFData& inNumber) : mCFData(inNumber.mCFData), mWillRelease(inNumber.mWillRelease) { Retain(); }
+	CACFData&	operator=(const CACFData& inNumber) { Release(); mCFData = inNumber.mCFData; mWillRelease = inNumber.mWillRelease; Retain(); return *this; }
+	CACFData&	operator=(CFDataRef inCFData) { Release(); mCFData = inCFData; mWillRelease = true; return *this; }
+
+private:
+	void		Retain() { if(mWillRelease && (mCFData != NULL)) { CFRetain(mCFData); } }
+	void		Release() { if(mWillRelease && (mCFData != NULL)) { CFRelease(mCFData); } }
+	
+	CFDataRef	mCFData;
+	bool		mWillRelease;
+
+//	Operations
+public:
+	void		AllowRelease() { mWillRelease = true; }
+	void		DontAllowRelease() { mWillRelease = false; }
+	bool		IsValid() { return mCFData != NULL; }
+
+//	Value Access
+public:
+	CFDataRef	GetCFData() const { return mCFData; }
+	CFDataRef	CopyCFData() const { if(mCFData != NULL) { CFRetain(mCFData); } return mCFData; }
+	
+	UInt32		GetSize() const { return ToUInt32(CFDataGetLength(mCFData)); }
+	const void*	GetDataPtr() const { return CFDataGetBytePtr(mCFData); }
+	void		CopyData(UInt32 inStartOffset, void* outData, UInt32 inDataSize) const { CFRange theRange = { static_cast<CFIndex>(inStartOffset), static_cast<CFIndex>(inDataSize) }; CFDataGetBytes(mCFData, theRange, static_cast<UInt8*>(outData)); }
+	
+	SInt32		GetSInt32() const { SInt32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(SInt32)); return theAnswer; }
+	Float32		GetFloat32() const { Float32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(Float32)); return theAnswer; }
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp
new file mode 100644
index 0000000..fbac774
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp
@@ -0,0 +1,581 @@
+/*
+     File: CACFDictionary.cpp
+ Abstract: CACFDictionary.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	Self Include
+#include "CACFDictionary.h"
+
+//	PublicUtility Includes
+#include "CACFArray.h"
+#include "CACFNumber.h"
+#include "CACFString.h"
+
+//=============================================================================
+//	CACFDictionary
+//=============================================================================
+
+bool	CACFDictionary::HasKey(const CFStringRef inKey) const
+{
+	return CFDictionaryContainsKey(mCFDictionary, inKey) != 0;
+}
+
+UInt32	CACFDictionary::Size () const
+{
+	return mCFDictionary ? ToUInt32(CFDictionaryGetCount(mCFDictionary)) : 0;
+}
+
+void	CACFDictionary::GetKeys (const void **keys) const
+{
+	CFDictionaryGetKeysAndValues(mCFDictionary, keys, NULL);
+}
+
+void	CACFDictionary::GetKeysAndValues (const void **keys, const void **values) const
+{
+	CFDictionaryGetKeysAndValues(mCFDictionary, keys, values);
+}
+
+bool	CACFDictionary::GetBool(const CFStringRef inKey, bool& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
+		{
+			outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+			theAnswer = true;
+		}
+		else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			SInt32 theNumericValue = 0;
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+			outValue = theNumericValue != 0;
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetSInt32(const CFStringRef inKey, SInt32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetUInt32(const CFStringRef inKey, UInt32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetSInt64(const CFStringRef inKey, SInt64& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetUInt64(const CFStringRef inKey, UInt64& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetFloat32FromString(const CFStringRef inKey, Float32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+		{
+			outValue = static_cast<Float32>(CFStringGetDoubleValue(static_cast<CFStringRef>(theValue)));
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetUInt32FromString(const CFStringRef inKey, UInt32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+		{
+			outValue = CFStringGetIntValue(static_cast<CFStringRef>(theValue));
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetFloat32(const CFStringRef inKey, Float32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetFloat64(const CFStringRef inKey, Float64& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetFixed32(const CFStringRef inKey, Float32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			SInt32 theFixed32 = 0;
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theFixed32);
+			
+			//	this is a 16.16 value so convert it to a float
+			Float32 theSign = theFixed32 < 0 ? -1.0f : 1.0f;
+			theFixed32 *= (SInt32)theSign;
+			Float32 theWholePart = (theFixed32 & 0x7FFF0000) >> 16;
+			Float32 theFractPart = theFixed32 & 0x0000FFFF;
+			theFractPart /= 65536.0f;
+			outValue = theSign * (theWholePart + theFractPart);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetFixed64(const CFStringRef inKey, Float64& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			SInt64 theFixed64 = 0;
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &theFixed64);
+			outValue = static_cast<Float64>(theFixed64 >> 32);
+			outValue += static_cast<Float64>(theFixed64 & 0x00000000FFFFFFFFLL) / static_cast<Float64>(0x0000000100000000LL);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::Get4CC(const CFStringRef inKey, UInt32& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+		{
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+			theAnswer = true;
+		}
+		else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+		{
+			CFStringRef theString = static_cast<CFStringRef>(theValue);
+			if(CFStringGetLength(theString) == 4)
+			{
+				char theCString[5];
+				CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII);
+				outValue = CFSwapInt32BigToHost(*reinterpret_cast<UInt32*>(theCString));
+			}
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetString(const CFStringRef inKey, CFStringRef& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+		{
+			outValue = static_cast<CFStringRef>(theValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+	
+bool	CACFDictionary::GetArray(const CFStringRef inKey, CFArrayRef& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
+		{
+			outValue = static_cast<CFArrayRef>(theValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+	
+bool	CACFDictionary::GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
+		{
+			outValue = static_cast<CFDictionaryRef>(theValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetData(const CFStringRef inKey, CFDataRef& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFDataGetTypeID()))
+		{
+			outValue = static_cast<CFDataRef>(theValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const
+{
+	bool theAnswer = false;
+	
+	if(mCFDictionary != NULL)
+	{
+		outValue = CFDictionaryGetValue(mCFDictionary, inKey);
+		theAnswer = (outValue != NULL);
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetURL(const CFStringRef inKey, CFURLRef& outValue) const
+{
+	bool theAnswer = false;
+	
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFURLGetTypeID()))
+		{
+			outValue = static_cast<CFURLRef>(theValue);
+			theAnswer = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const
+{
+	bool theAnswer = false;
+	
+	if(mCFDictionary != NULL)
+	{
+		CACFString theKey(inKey);
+		if(theKey.IsValid())
+		{
+			theAnswer = GetCFType(theKey.GetCFString(), outValue);
+		}
+	}
+	
+	return theAnswer;
+}
+
+void	CACFDictionary::GetCACFString(const CFStringRef inKey, CACFString& outValue) const
+{
+	outValue = static_cast<CFStringRef>(NULL);
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+		{
+			outValue = static_cast<CFStringRef>(theValue);
+		}
+	}
+}
+	
+void	CACFDictionary::GetCACFArray(const CFStringRef inKey, CACFArray& outValue) const
+{
+	outValue = static_cast<CFArrayRef>(NULL);
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
+		{
+			outValue = static_cast<CFArrayRef>(theValue);
+		}
+	}
+}
+	
+void	CACFDictionary::GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outValue) const
+{
+	outValue = static_cast<CFDictionaryRef>(NULL);
+	CFTypeRef theValue = NULL;
+	if(GetCFType(inKey, theValue))
+	{
+		if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
+		{
+			outValue = static_cast<CFDictionaryRef>(theValue);
+		}
+	}
+}
+
+bool	CACFDictionary::AddBool(const CFStringRef inKey, bool inValue)
+{
+	CACFBoolean theValue(inValue);
+	return AddCFType(inKey, theValue.GetCFBoolean());
+}
+
+bool	CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue)
+{
+	CACFNumber theValue(inValue);
+	return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool	CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue)
+{
+	CACFNumber theValue(inValue);
+	return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool	CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue)
+{
+	CACFNumber theValue(inValue);
+	return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool	CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue)
+{
+	CACFNumber theValue(inValue);
+	return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool	CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue)
+{
+	CACFNumber theValue(inValue);
+	return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool	CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue)
+{
+	CACFNumber theValue(inValue);
+	return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool	CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue)
+{
+	return AddCFType(inKey, inValue);
+}
+
+bool	CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue)
+{
+	return AddCFType(inKey, inValue);
+}
+
+bool	CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue)
+{
+	return AddCFType(inKey, inValue);
+}
+
+bool	CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue)
+{
+	return AddCFType(inKey, inValue);
+}
+
+bool	CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue)
+{
+	return AddCFType(inKey, inValue);
+}
+
+bool	CACFDictionary::AddURL(const CFStringRef inKey, const CFURLRef inValue)
+{
+	return AddCFType (inKey, inValue);
+}
+
+bool	CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue)
+{
+	bool theAnswer = false;
+	
+	if (inKey)
+	{
+		CACFString theKey(inKey);
+		if(theKey.IsValid())
+		{
+			theAnswer = AddCFType(theKey.GetCFString(), inValue);
+		}
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFDictionary::AddCString(const CFStringRef inKey, const char* inValue)
+{
+	bool theAnswer = false;
+	
+	if (inValue)
+	{
+		CACFString theValue(inValue);
+		if(theValue.IsValid())
+		{
+			theAnswer = AddCFType(inKey, theValue.GetCFString());
+		}
+	}
+	return theAnswer;
+}
+
+bool	CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue)
+{
+	bool theAnswer = false;
+	
+	if(mMutable && (mCFDictionary != NULL) && inValue)
+	{
+		CFDictionarySetValue(mCFDictionary, inKey, inValue);
+		theAnswer = true;
+	}
+	
+	return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h
new file mode 100644
index 0000000..c389e50
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h
@@ -0,0 +1,176 @@
+/*
+     File: CACFDictionary.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFDictionary_h__)
+#define __CACFDictionary_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include <CoreFoundation.h>
+#endif
+
+//=============================================================================
+//	Types
+//=============================================================================
+
+class	CACFArray;
+class	CACFString;
+
+//=============================================================================
+//	CACFDictionary
+//=============================================================================
+
+class CACFDictionary 
+{
+
+//	Construction/Destruction
+public:
+							CACFDictionary()														: mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(true), mMutable(true) {}
+	explicit				CACFDictionary(bool inRelease)											: mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {}
+							CACFDictionary(CFDictionaryRef inCFDictionary, bool inRelease)			: mCFDictionary(const_cast<CFMutableDictionaryRef>(inCFDictionary)), mRelease(inRelease), mMutable(false) {}
+							CACFDictionary(CFMutableDictionaryRef inCFDictionary, bool inRelease)	: mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {}
+							CACFDictionary(const CACFDictionary& inDictionary)						: mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { Retain(); }
+	CACFDictionary&			operator=(const CACFDictionary& inDictionary)							{ Release(); mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; Retain(); return *this; } 
+	CACFDictionary&			operator=(CFDictionaryRef inDictionary)									{ Release(); mCFDictionary = const_cast<CFMutableDictionaryRef>(inDictionary); mMutable = false; Retain(); return *this; } 
+	CACFDictionary&			operator=(CFMutableDictionaryRef inDictionary)							{ Release(); mCFDictionary = inDictionary; mMutable = true; Retain(); return *this; } 
+							~CACFDictionary()														{ Release(); }
+
+private:
+	void					Retain()																{ if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } }
+	void					Release()																{ if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } }
+		
+//	Attributes
+public:
+	bool					IsValid() const															{ return mCFDictionary != NULL; }
+	bool					IsMutable() const														{ return mMutable;}
+	bool					CanModify() const														{ return mMutable && (mCFDictionary != NULL); }
+	
+	bool					WillRelease() const														{ return mRelease; }
+	void					ShouldRelease(bool inRelease)											{ mRelease = inRelease; }
+	
+	CFDictionaryRef			GetDict() const															{ return mCFDictionary; }
+	CFDictionaryRef			GetCFDictionary() const													{ return mCFDictionary; }
+	CFDictionaryRef			CopyCFDictionary() const												{ if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+
+	CFMutableDictionaryRef	GetMutableDict()														{ return mCFDictionary; }
+	CFMutableDictionaryRef	GetCFMutableDictionary() const											{ return mCFDictionary; }
+	CFMutableDictionaryRef	CopyCFMutableDictionary() const											{ if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+	void					SetCFMutableDictionaryFromCopy(CFDictionaryRef inDictionary, bool inRelease = true)		{ Release(); mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); mMutable = true; mRelease = inRelease; }
+	void					SetCFMutableDictionaryToEmpty(bool inRelease = true)					{ Release(); mCFDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); mMutable = true; mRelease = inRelease; }
+
+	CFPropertyListRef		AsPropertyList() const													{ return mCFDictionary; }
+	OSStatus				GetDictIfMutable(CFMutableDictionaryRef& outDict) const					{ OSStatus theAnswer = -1; if(mMutable) { outDict = mCFDictionary; theAnswer = 0; } return theAnswer; }
+
+//	Item Operations
+public:
+	bool					HasKey(const CFStringRef inKey) const;
+	UInt32					Size() const;
+	void					GetKeys(const void** keys) const;
+	void					GetKeysAndValues (const void **keys, const void **values) const;
+	
+	bool					GetBool(const CFStringRef inKey, bool& outValue) const;
+	bool					GetSInt32(const CFStringRef inKey, SInt32& outValue) const;
+	bool					GetUInt32(const CFStringRef inKey, UInt32& outValue) const;
+	bool					GetUInt32FromString(const CFStringRef inKey, UInt32& outValue) const;
+	bool					GetSInt64(const CFStringRef inKey, SInt64& outValue) const;
+	bool					GetUInt64(const CFStringRef inKey, UInt64& outValue) const;
+	bool					GetFloat32(const CFStringRef inKey, Float32& outValue) const;
+	bool					GetFloat32FromString(const CFStringRef inKey, Float32& outValue) const;
+	bool					GetFloat64(const CFStringRef inKey, Float64& outValue) const;
+	bool					GetFixed32(const CFStringRef inKey, Float32& outValue) const;
+	bool					GetFixed64(const CFStringRef inKey, Float64& outValue) const;
+	bool					Get4CC(const CFStringRef inKey, UInt32& outValue) const;
+	bool					GetString(const CFStringRef inKey, CFStringRef& outValue) const;	
+	bool					GetArray(const CFStringRef inKey, CFArrayRef& outValue) const;	
+	bool					GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const;	
+	bool					GetData(const CFStringRef inKey, CFDataRef& outValue) const;
+	bool					GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const;
+	bool					GetURL(const CFStringRef inKey, CFURLRef& outValue) const;
+	bool					GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const;
+
+	void					GetCACFString(const CFStringRef inKey, CACFString& outItem) const;
+	void					GetCACFArray(const CFStringRef inKey, CACFArray& outItem) const;
+	void					GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outItem) const;
+	
+	bool					AddBool(const CFStringRef inKey, bool inValue);
+	bool					AddSInt32(const CFStringRef inKey, SInt32 inValue);
+	bool					AddUInt32(const CFStringRef inKey, UInt32 inValue);
+	bool					AddSInt64(const CFStringRef inKey, SInt64 inValue);
+	bool					AddUInt64(const CFStringRef inKey, UInt64 inValue);
+	bool					AddFloat32(const CFStringRef inKey, Float32 inValue);
+	bool					AddFloat64(const CFStringRef inKey, Float64 inValue);
+	bool					AddNumber(const CFStringRef inKey, const CFNumberRef inValue);
+	bool					AddString(const CFStringRef inKey, const CFStringRef inValue);
+	bool					AddArray(const CFStringRef inKey, const CFArrayRef inValue);
+	bool					AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue);
+	bool					AddData(const CFStringRef inKey, const CFDataRef inValue);
+	bool					AddCFType(const CFStringRef inKey, const CFTypeRef inValue);
+	bool					AddURL(const CFStringRef inKey, const CFURLRef inValue);
+	
+	bool					AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue);
+	bool					AddCString(const CFStringRef inKey, const char* inValue);
+
+	void					RemoveKey(const CFStringRef inKey)										{ if(CanModify()) { CFDictionaryRemoveValue(mCFDictionary, inKey); } }
+	void					Clear()																	{ if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } }
+	
+	void					Show()																	{ CFShow(mCFDictionary); }
+	
+//	Implementation
+private:
+	CFMutableDictionaryRef 	mCFDictionary;
+	bool					mRelease;
+	bool					mMutable;
+	
+							CACFDictionary(const void*);	// prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif //__CACFDictionary_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp
new file mode 100644
index 0000000..36c6923
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp
@@ -0,0 +1,107 @@
+/*
+     File: CACFDistributedNotification.cpp
+ Abstract: CACFDistributedNotification.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CACFDistributedNotification.h"
+
+//	PublicUtility Includes
+#include "CADebugMacros.h"
+
+//==================================================================================================
+//	CACFDistributedNotification
+//==================================================================================================
+
+void	CACFDistributedNotification::AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior)
+{
+#if	!TARGET_OS_IPHONE
+	CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
+	CFNotificationSuspensionBehavior theSuspensionBehavior = inSuspensionBehavior;
+#else
+	#pragma unused(inSuspensionBehavior)
+	CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
+	CFNotificationSuspensionBehavior theSuspensionBehavior = static_cast<CFNotificationSuspensionBehavior>(0);
+#endif
+	 
+	CFNotificationCenterAddObserver(theCenter, inObserver, inCallback, inName, NULL, theSuspensionBehavior);
+}
+
+void	CACFDistributedNotification::RemoveObserver(const void* inObserver, CFStringRef inName)
+{
+#if	!TARGET_OS_IPHONE
+	CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
+#else
+	CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
+#endif
+	 
+	CFNotificationCenterRemoveObserver(theCenter, inObserver, inName, NULL);
+}
+
+void	CACFDistributedNotification::PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions)
+{
+#if	!TARGET_OS_IPHONE
+	CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
+	CFDictionaryRef theUserInfo = inUserInfo;
+	CFOptionFlags theFlags = kCFNotificationDeliverImmediately;
+	if(inPostToAllSessions)
+	{
+		theFlags += kCFNotificationPostToAllSessions;
+	}
+#else
+	//	flag unsupported features
+	Assert(inUserInfo == NULL, "CACFDistributedNotification::PostNotification: distributed notifications do not support a payload");
+	Assert(inPostToAllSessions, "CACFDistributedNotification::PostNotification: distributed notifications do not support per-session delivery");
+	
+	CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
+	CFDictionaryRef theUserInfo = NULL;
+	CFOptionFlags theFlags = 0;
+#endif
+	 
+	 CFNotificationCenterPostNotificationWithOptions(theCenter, inName, NULL, theUserInfo, theFlags);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h
new file mode 100644
index 0000000..d75e23b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h
@@ -0,0 +1,73 @@
+/*
+     File: CACFDistributedNotification.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFDistributedNotification_h__)
+#define __CACFDistributedNotification_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+//==================================================================================================
+//	CACFDistributedNotification
+//==================================================================================================
+
+class CACFDistributedNotification
+{
+
+//	Operations
+public:
+	static void		AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior = CFNotificationSuspensionBehaviorCoalesce);
+	static void		RemoveObserver(const void* inObserver, CFStringRef inName);
+	static void		PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions);
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp
new file mode 100644
index 0000000..9a33d5d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp
@@ -0,0 +1,168 @@
+/*
+     File: CACFMachPort.cpp
+ Abstract: CACFMachPort.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+#include "CACFMachPort.h"
+#include "CAException.h"
+#include "CADebugMacros.h"
+
+//==================================================================================================
+//	CACFMachPort
+//==================================================================================================
+
+//	This constructor is the short form. The CFMachPort will own the send and receive rights.
+CACFMachPort::CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData)
+:
+	mMachPort(NULL),
+	mRunLoopSource(NULL),
+	mOwnsPort(true)
+{
+	CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL };
+	mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL);
+	ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort(s): couldn't create the CFMachPort");
+
+	mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0);
+	if(mRunLoopSource == NULL)
+	{
+		CFMachPortInvalidate(mMachPort);
+		CFRelease(mMachPort);
+		mMachPort = NULL;
+		DebugMessage("CACFMachPort::CACFMachPort(s): couldn't create the CFRunLoopSource");
+		throw CAException('what');
+	}
+}
+
+//	This constructor is the general form:
+//	-	If inMachPort is MACH_PORT_NULL, the CFMachPort will allocate the port and own the send and
+//		receive rights. Otherwise, the caller owns the rights and is resposible for cleaning them
+//		up.
+//	-	If inCallBack is NULL, then received messages will just get swallowed by the CFMachPort.
+//		This is useful if you are only using the CFMachPort to track port death (aka invalidation).
+//	-	If inInvalidationCallBack is non-NULL, then it will be installed as the invalidation
+//		callback on the CFMachPort.
+CACFMachPort::CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData)
+:
+	mMachPort(NULL),
+	mRunLoopSource(NULL),
+	mOwnsPort(false)
+{
+	CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL };
+	
+	if(inMachPort == MACH_PORT_NULL)
+	{
+		mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL);
+		ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort");
+		mOwnsPort = true;
+	}
+	else
+	{
+		mMachPort = CFMachPortCreateWithPort(NULL, inMachPort, inCallBack, &theContext, NULL);
+		ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort with a port");
+		mOwnsPort = false;
+	}
+
+	mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0);
+	if(mRunLoopSource == NULL)
+	{
+		if(mOwnsPort)
+		{
+			CFMachPortInvalidate(mMachPort);
+		}
+		CFRelease(mMachPort);
+		mMachPort = NULL;
+		DebugMessage("CACFMachPort::CACFMachPort: couldn't create the CFRunLoopSource");
+		throw CAException('what');
+	}
+	
+	if(inInvalidationCallBack != NULL)
+	{
+		CFMachPortSetInvalidationCallBack(mMachPort, inInvalidationCallBack);
+	}
+}
+
+CACFMachPort::~CACFMachPort()
+{
+	if(mRunLoopSource != NULL)
+	{
+		CFRelease(mRunLoopSource);
+	}
+	
+	if(mMachPort != NULL)
+	{
+		if(mOwnsPort)
+		{
+			CFMachPortInvalidate(mMachPort);
+		}
+		CFRelease(mMachPort);
+	}
+}
+
+kern_return_t	CACFMachPort::ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut)
+{
+	//	snag the port
+	mach_port_t thePort = CFMachPortGetPort(mMachPort);
+
+	//	fill out the message header
+	outMessage->msgh_bits = 0;
+	outMessage->msgh_size = 0;
+	outMessage->msgh_remote_port = MACH_PORT_NULL;
+	outMessage->msgh_local_port = thePort;
+	outMessage->msgh_reserved = 0;
+	outMessage->msgh_id = 0;
+
+	//	figure the options
+	mach_msg_options_t theOptions = MACH_RCV_MSG;
+	if(inTimeOut > 0)
+	{
+		theOptions |= MACH_RCV_TIMEOUT;
+	}
+	
+	//	receive the messsage
+	return mach_msg(outMessage, theOptions, 0, inMaxMessageSize, thePort, inTimeOut, MACH_PORT_NULL);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h
new file mode 100644
index 0000000..18b8ccc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h
@@ -0,0 +1,95 @@
+/*
+     File: CACFMachPort.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFMachPort_h__)
+#define __CACFMachPort_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	System Includes
+#include <CoreFoundation/CFMachPort.h>
+#include <mach/mach.h>
+
+//==================================================================================================
+//	CACFMachPort
+//
+//	This class wraps a CFMachPort.
+//	
+//	Note that when you create a CFMachPort object, CF will attach the run loop source for the the
+//	Mach Port that handles Port Death notifications (aka the Invalidation Callback) to the current
+//	thread's run loop. This is something over which there is no control, so be sure to create the
+//	CFMachPort on the thread on which you want to handle Port Death notificaitons on.
+//==================================================================================================
+
+class	CACFMachPort
+{
+
+//	Construction/Destruction
+public:
+						CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData = NULL);
+						CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData);
+	virtual				~CACFMachPort();
+
+//	Attributes
+public:
+	CFMachPortRef		GetMachPortRef() const { return mMachPort; }
+	mach_port_t			GetMachPort() const { return CFMachPortGetPort(mMachPort); }
+	CFRunLoopSourceRef	GetRunLoopSource() const { return mRunLoopSource; }
+
+//	Operations
+public:
+	kern_return_t		ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut);
+
+//	Implementation
+protected:
+	CFMachPortRef		mMachPort;
+	CFRunLoopSourceRef	mRunLoopSource;
+	bool				mOwnsPort;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp
new file mode 100644
index 0000000..97b5da1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp
@@ -0,0 +1,163 @@
+/*
+     File: CACFMessagePort.cpp
+ Abstract: CACFMessagePort.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CACFMessagePort.h"
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//=============================================================================
+//	CACFLocalMessagePort
+//=============================================================================
+
+CACFLocalMessagePort::CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData)
+:
+	mMessagePort(NULL),
+	mRunLoopSource(NULL),
+	mDispatchQueue(NULL)
+{
+	//	create the CFMessagePort
+	CFMessagePortContext theContext = { 0, inUserData, NULL, NULL, NULL };
+	mMessagePort = CFMessagePortCreateLocal(NULL, inName, inPortCallBack, &theContext, NULL);
+	if(mMessagePort != NULL)
+	{
+		//	add the invalidation callback, if any
+		if(inInvalidationCallBack != NULL)
+		{
+			CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack);
+		}
+	}
+}
+
+CACFLocalMessagePort::~CACFLocalMessagePort()
+{
+	if(mRunLoopSource != NULL)
+	{
+		CFRelease(mRunLoopSource);
+	}
+	if(mMessagePort != NULL)
+	{
+		CFMessagePortInvalidate(mMessagePort);
+		CFRelease(mMessagePort);
+	}
+}
+
+CFRunLoopSourceRef	CACFLocalMessagePort::GetRunLoopSource() const
+{
+	Assert(mDispatchQueue == NULL, "CACFLocalMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+	if(mRunLoopSource == NULL)
+	{
+		const_cast<CACFLocalMessagePort*>(this)->mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
+	}
+	return mRunLoopSource;
+}
+
+void	CACFLocalMessagePort::SetDispatchQueue(dispatch_queue_t inDispatchQueue)
+{
+	Assert(mRunLoopSource == NULL, "CACFLocalMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+	mDispatchQueue = inDispatchQueue;
+	CFMessagePortSetDispatchQueue(mMessagePort, mDispatchQueue);
+}
+
+//=============================================================================
+//	CACFRemoteMessagePort
+//=============================================================================
+
+CACFRemoteMessagePort::CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack)
+:
+	mMessagePort(NULL),
+	mRunLoopSource(NULL),
+	mDispatchQueue(NULL)
+{
+	//	create the CFMessagePort
+	mMessagePort = CFMessagePortCreateRemote(NULL, inName);
+	if(mMessagePort != NULL)
+	{
+		//	failure to create a remote port does not need to throw an exception
+		//	because it isn't really an error since the port in question may not
+		//	exist and this fact requires a more complex response than an excpeption
+		//	provides for.
+		
+		//	add the invalidation callback, if any
+		if(inInvalidationCallBack != NULL)
+		{
+			CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack);
+		}
+	}
+}
+
+CACFRemoteMessagePort::~CACFRemoteMessagePort()
+{
+	if(mRunLoopSource != NULL)
+	{
+		CFRelease(mRunLoopSource);
+	}
+	if(mMessagePort != NULL)
+	{
+		//CFMessagePortInvalidate(mMessagePort);
+		CFRelease(mMessagePort);
+	}
+}
+
+CFRunLoopSourceRef	CACFRemoteMessagePort::GetRunLoopSource() const
+{
+	Assert(mDispatchQueue == NULL, "CACFRemoteMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+	if(mRunLoopSource == NULL)
+	{
+		const_cast<CACFRemoteMessagePort*>(this)->mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
+	}
+	return mRunLoopSource;
+}
+
+void	CACFRemoteMessagePort::SetDispatchQueue(dispatch_queue_t inDispatchQueue)
+{
+	Assert(mRunLoopSource == NULL, "CACFRemoteMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+	mDispatchQueue = inDispatchQueue;
+	CFMessagePortSetDispatchQueue(mMessagePort, mDispatchQueue);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h
new file mode 100644
index 0000000..c369251
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h
@@ -0,0 +1,119 @@
+/*
+     File: CACFMessagePort.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFMessagePort_h__)
+#define __CACFMessagePort_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CFMessagePort.h>
+#else
+	#include <CFMessagePort.h>
+#endif
+
+//=============================================================================
+//	CACFLocalMessagePort
+//=============================================================================
+
+class CACFLocalMessagePort
+{
+
+//	Construction/Destruction
+public:
+						CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData = NULL);
+	virtual				~CACFLocalMessagePort();
+
+//	Attributes
+public:
+	bool				IsValid() const { return mMessagePort != NULL; }
+	CFMessagePortRef	GetMessagePortRef() const { return mMessagePort; }
+	CFRunLoopSourceRef	GetRunLoopSource() const;
+	void				SetDispatchQueue(dispatch_queue_t inDispatchQueue);
+
+//	Implementation
+protected:
+	CFMessagePortRef	mMessagePort;
+	CFRunLoopSourceRef	mRunLoopSource;
+	dispatch_queue_t	mDispatchQueue;
+
+};
+
+//=============================================================================
+//	CACFRemoteMessagePort
+//=============================================================================
+
+class CACFRemoteMessagePort
+{
+
+//	Construction/Destruction
+public:
+						CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack);
+	virtual				~CACFRemoteMessagePort();
+
+//	Attributes
+public:
+	bool				IsValid() const { return mMessagePort != NULL; }
+	CFMessagePortRef	GetMessagePortRef() const { return mMessagePort; }
+	CFRunLoopSourceRef	GetRunLoopSource() const;
+	void				SetDispatchQueue(dispatch_queue_t inDispatchQueue);
+
+//	Operations
+public:
+	SInt32				SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, NULL, NULL); }
+	SInt32				SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout, CFStringRef inReplyMode, CFDataRef& outReturnData) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, inReplyMode, &outReturnData); }
+
+//	Implementation
+protected:
+	CFMessagePortRef	mMessagePort;
+	CFRunLoopSourceRef	mRunLoopSource;
+	dispatch_queue_t	mDispatchQueue;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp
new file mode 100644
index 0000000..36d1c2e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp
@@ -0,0 +1,83 @@
+/*
+     File: CACFNumber.cpp
+ Abstract: CACFNumber.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CACFNumber.h"
+
+//=============================================================================
+//	CACFNumber
+//=============================================================================
+
+Float32	CACFNumber::GetFixed32() const
+{
+	SInt32 theFixedValue = GetSInt32();
+	
+	//	this is a 16.16 value so convert it to a float
+	Float32 theSign = theFixedValue < 0 ? -1.0f : 1.0f;
+	theFixedValue *= (SInt32)theSign;
+	Float32 theWholePart = (theFixedValue & 0x7FFF0000) >> 16;
+	Float32 theFractPart = theFixedValue & 0x0000FFFF;
+	theFractPart /= 65536.0f;
+	
+	return theSign * (theWholePart + theFractPart);
+}
+
+Float64	CACFNumber::GetFixed64() const
+{
+	SInt64 theFixedValue = GetSInt64();
+	
+	//	this is a 32.32 value so convert it to a double
+	Float64 theSign = theFixedValue < 0 ? -1.0 : 1.0;
+	theFixedValue *= (SInt64)theSign;
+	Float64 theWholePart = (theFixedValue & 0x7FFFFFFF00000000LL) >> 32;
+	Float64 theFractPart = theFixedValue & 0x00000000FFFFFFFFLL;
+	theFractPart /= 4294967296.0;
+	
+	return theSign * (theWholePart + theFractPart);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h
new file mode 100644
index 0000000..25887f6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h
@@ -0,0 +1,151 @@
+/*
+     File: CACFNumber.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFNumber_h__)
+#define __CACFNumber_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <CoreFoundation/CFNumber.h>
+#else
+	#include <CoreAudioTypes.h>
+	#include <CFNumber.h>
+#endif
+
+//=============================================================================
+//	CACFBoolean
+//=============================================================================
+
+class	CACFBoolean
+{
+//	Construction/Destruction
+public:
+	explicit		CACFBoolean(CFBooleanRef inCFBoolean) : mCFBoolean(inCFBoolean), mWillRelease(true) {}
+					CACFBoolean(CFBooleanRef inCFBoolean, bool inWillRelease) : mCFBoolean(inCFBoolean), mWillRelease(inWillRelease) {}
+	explicit		CACFBoolean(bool inValue) : mCFBoolean(inValue ? kCFBooleanTrue : kCFBooleanFalse), mWillRelease(true) { Retain(); }
+					~CACFBoolean() { Release(); }
+					CACFBoolean(const CACFBoolean& inBoolean) : mCFBoolean(inBoolean.mCFBoolean), mWillRelease(inBoolean.mWillRelease) { Retain(); }
+	CACFBoolean&	operator=(const CACFBoolean& inBoolean) { Release(); mCFBoolean = inBoolean.mCFBoolean; mWillRelease = inBoolean.mWillRelease; Retain(); return *this; }
+	CACFBoolean&	operator=(CFBooleanRef inCFBoolean) { Release(); mCFBoolean = inCFBoolean; mWillRelease = true; return *this; }
+
+private:
+	void			Retain() { if(mWillRelease && (mCFBoolean != NULL)) { CFRetain(mCFBoolean); } }
+	void			Release() { if(mWillRelease && (mCFBoolean != NULL)) { CFRelease(mCFBoolean); } }
+	
+	CFBooleanRef	mCFBoolean;
+	bool			mWillRelease;
+
+//	Operations
+public:
+	void			AllowRelease() { mWillRelease = true; }
+	void			DontAllowRelease() { mWillRelease = false; }
+	bool			IsValid() { return mCFBoolean != NULL; }
+
+//	Value Access
+public:
+	CFBooleanRef	GetCFBoolean() const { return mCFBoolean; }
+	CFBooleanRef	CopyCFBoolean() const { if(mCFBoolean != NULL) { CFRetain(mCFBoolean); } return mCFBoolean; }
+
+	bool			GetBoolean() const { bool theAnswer = false; if(mCFBoolean != NULL) { theAnswer = CFEqual(mCFBoolean, kCFBooleanTrue); } return theAnswer; }
+	
+					CACFBoolean(const void*);	// prevent accidental instantiation with a pointer via bool constructor
+};
+
+//=============================================================================
+//	CACFNumber
+//=============================================================================
+
+class	CACFNumber
+{
+//	Construction/Destruction
+public:
+	explicit	CACFNumber(CFNumberRef inCFNumber) : mCFNumber(inCFNumber), mWillRelease(true) {}
+				CACFNumber(CFNumberRef inCFNumber, bool inWillRelease) : mCFNumber(inCFNumber), mWillRelease(inWillRelease) {}
+				CACFNumber(SInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {}
+				CACFNumber(UInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {}
+				CACFNumber(SInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {}
+				CACFNumber(UInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {}
+				CACFNumber(Float32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat32Type, &inValue)), mWillRelease(true) {}
+				CACFNumber(Float64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat64Type, &inValue)), mWillRelease(true) {}
+				~CACFNumber() { Release(); }
+				CACFNumber(const CACFNumber& inNumber) : mCFNumber(inNumber.mCFNumber), mWillRelease(inNumber.mWillRelease) { Retain(); }
+	CACFNumber&	operator=(const CACFNumber& inNumber) { Release(); mCFNumber = inNumber.mCFNumber; mWillRelease = inNumber.mWillRelease; Retain(); return *this; }
+	CACFNumber&	operator=(CFNumberRef inCFNumber) { Release(); mCFNumber = inCFNumber; mWillRelease = true; return *this; }
+
+private:
+	void		Retain() { if(mWillRelease && (mCFNumber != NULL)) { CFRetain(mCFNumber); } }
+	void		Release() { if(mWillRelease && (mCFNumber != NULL)) { CFRelease(mCFNumber); } }
+	
+	CFNumberRef	mCFNumber;
+	bool		mWillRelease;
+
+//	Operations
+public:
+	void		AllowRelease() { mWillRelease = true; }
+	void		DontAllowRelease() { mWillRelease = false; }
+	bool		IsValid() const { return mCFNumber != NULL; }
+
+//	Value Access
+public:
+	CFNumberRef	GetCFNumber() const { return mCFNumber; }
+	CFNumberRef	CopyCFNumber() const { if(mCFNumber != NULL) { CFRetain(mCFNumber); } return mCFNumber; }
+
+	SInt8		GetSInt8() const { SInt8 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt8Type, &theAnswer); } return theAnswer; }
+	SInt32		GetSInt32() const { SInt32 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt32Type, &theAnswer); } return theAnswer; }
+	UInt32		GetUInt32() const { UInt32 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt32Type, &theAnswer); } return theAnswer; }
+	Float32		GetFloat32() const { Float32 theAnswer = 0.0f; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberFloat32Type, &theAnswer); } return theAnswer; }
+	Float32		GetFixed32() const;
+	Float64		GetFixed64() const;
+	SInt64		GetSInt64() const { SInt64 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt64Type, &theAnswer); } return theAnswer; }
+	
+				CACFNumber(const void*);	// prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h b/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h
new file mode 100644
index 0000000..748016b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h
@@ -0,0 +1,138 @@
+/*
+     File: CACFObject.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFObject_h__)
+#define __CACFObject_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include <CoreAudioTypes.h>
+	#include <CoreFoundation.h>
+#endif
+
+//=============================================================================
+//	Wrappers for CFRetain and CFRelease that check for NULL
+//=============================================================================
+
+template <typename CFObjectType>
+CFObjectType CACFRetain(CFObjectType inObject)
+{
+	CFObjectType theAnswer = inObject;
+	if(inObject != NULL)
+	{
+		theAnswer = reinterpret_cast<CFObjectType>(CFRetain(inObject));
+	}
+	return theAnswer;
+}
+
+inline void	CACFRelease(CFTypeRef inObject)
+{
+	if(inObject != NULL)
+	{
+		CFRelease(inObject);
+	}
+}
+
+//=============================================================================
+//	CACFObject
+//
+//	Notes
+//	-	Using the AssignWithoutRetain() method will fool the static analyzer into thinking that the
+//		CFObject being assigned will be leaked. This is because the static analyzer is not smart
+//		enough to understand that the destructor will release the object.
+//=============================================================================
+
+template <class CFObjectType>
+class CACFObject
+{
+
+//	Construction/Destruction
+public:
+						CACFObject() : mCFObject(NULL), mWillRelease(true) {}
+	explicit			CACFObject(CFObjectType inCFObject) : mCFObject(inCFObject), mWillRelease(true) {}
+						CACFObject(CFObjectType inCFObject, bool inWillRelease) : mCFObject(inCFObject), mWillRelease(inWillRelease) {}
+						~CACFObject() { Release(); }
+						CACFObject(const CACFObject& inObject) : mCFObject(inObject.mCFObject), mWillRelease(inObject.mWillRelease) { Retain(); }
+	CACFObject&			operator=(const CACFObject& inObject) { Release(); mCFObject = inObject.mCFObject; mWillRelease = inObject.mWillRelease; Retain(); return *this; }
+	CACFObject&			operator=(CFObjectType inCFObject) { Release(); mCFObject = inCFObject; mWillRelease = true; Retain(); return *this; }
+	void				AssignWithoutRetain(CFObjectType inObject) { if (inObject != mCFObject) { Release(); mCFObject = inObject; } mWillRelease = true; }
+
+private:
+	void				Retain() { if(mWillRelease && (mCFObject != NULL)) { CFRetain(mCFObject); } }
+	void				Release() { if(mWillRelease && (mCFObject != NULL)) { CFRelease(mCFObject); mCFObject = NULL; } }
+	
+	CFObjectType		mCFObject;
+	bool				mWillRelease;
+
+//	Operations
+public:
+	void				AllowRelease() { mWillRelease = true; }
+	void				DontAllowRelease() { mWillRelease = false; }
+	bool				IsValid() const { return mCFObject != NULL; }
+	CFTypeID			GetTypeID() const { return CFGetTypeID(mCFObject); }
+	bool				IsEqual(CFObjectType inCFObject) const { return CFEqual(inCFObject, mCFObject) != 0; }
+
+//	Value Access
+public:
+	CFObjectType		GetCFObject() const { return mCFObject; }
+	CFObjectType		CopyCFObject() const { if(mCFObject != NULL) { CFRetain(mCFObject); } return mCFObject; }
+	const CFObjectType*	GetPointerToStorage() const	{ return &mCFObject; }
+
+};
+
+typedef	CACFObject<CFBundleRef>			CACFBundle;
+typedef	CACFObject<CFPropertyListRef>	CACFPropertyList;
+typedef	CACFObject<CFTypeRef>			CACFType;
+typedef	CACFObject<CFUUIDRef>			CACFUUID;
+typedef	CACFObject<CFURLRef>			CACFURL;
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h b/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h
new file mode 100644
index 0000000..babde13
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h
@@ -0,0 +1,101 @@
+/*
+     File: CACFPlugIn.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFPlugIn_h__)
+#define __CACFPlugIn_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CFPlugIn.h>
+
+//==================================================================================================
+//	CACFPlugIn
+//==================================================================================================
+
+class CACFPlugIn
+{
+
+//	Construction/Destruction
+public:
+					CACFPlugIn()														: mCFPlugIn(NULL), mWillRelease(true) {}
+					CACFPlugIn(CFPlugInRef inCFPlugIn, bool inWillRelease = true)		: mCFPlugIn(inCFPlugIn), mWillRelease(inWillRelease) {}
+					CACFPlugIn(CFURLRef inURL, bool inWillRelease = true)				: mCFPlugIn(CFPlugInCreate(NULL, inURL)), mWillRelease(inWillRelease) {}
+					~CACFPlugIn()														{ Release(); }
+					CACFPlugIn(const CACFPlugIn& inObject)								: mCFPlugIn(inObject.mCFPlugIn), mWillRelease(inObject.mWillRelease) { Retain(); }
+	CACFPlugIn&		operator=(const CACFPlugIn& inObject)								{ Release(); mCFPlugIn = inObject.mCFPlugIn; mWillRelease = inObject.mWillRelease; Retain(); return *this; }
+	CACFPlugIn&		operator=(CFPlugInRef inCFPlugIn)									{ Release(); mCFPlugIn = inCFPlugIn; mWillRelease = true; return *this; }
+
+private:
+	void			Retain()															{ if(mWillRelease && (mCFPlugIn != NULL)) { CFRetain(mCFPlugIn); } }
+	void			Release()															{ if(mWillRelease && (mCFPlugIn != NULL)) { CFRelease(mCFPlugIn); mCFPlugIn = NULL; } }
+	
+	CFPlugInRef		mCFPlugIn;
+	bool			mWillRelease;
+
+//	Operations
+public:
+	void			AllowRelease()														{ mWillRelease = true; }
+	void			DontAllowRelease()													{ mWillRelease = false; }
+	bool			IsValid() const														{ return mCFPlugIn != NULL; }
+	
+	CFBundleRef		GetBundle() const													{ CFBundleRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInGetBundle(mCFPlugIn); } return theAnswer; }
+	CFStringRef		CopyBundleID() const												{ CFStringRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetIdentifier(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; }
+	UInt32			GetBundleVersion() const											{ UInt32 theAnswer = 0; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetVersionNumber(theBundle); } return theAnswer; }
+	CFDictionaryRef CopyBundleInfo() const												{ CFDictionaryRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetInfoDictionary(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; }
+	CFArrayRef		FindFactoriesForType(CFUUIDRef inTypeUUID) const					{ CFArrayRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInFindFactoriesForPlugInTypeInPlugIn(inTypeUUID, mCFPlugIn); } return theAnswer; }
+
+//	Value Access
+public:
+	CFPlugInRef		GetCFPlugIn() const													{ return mCFPlugIn; }
+	CFPlugInRef		CopyCFPlugIn() const												{ if(mCFPlugIn != NULL) { CFRetain(mCFPlugIn); } return mCFPlugIn; }
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp
new file mode 100644
index 0000000..cb2e86c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp
@@ -0,0 +1,287 @@
+/*
+     File: CACFPreferences.cpp
+ Abstract: CACFPreferences.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CACFPreferences.h"
+
+//	PublicUtility Includes
+#include "CACFDistributedNotification.h"
+#include "CADebugMacros.h"
+
+//==================================================================================================
+//	CACFPreferences
+//==================================================================================================
+
+CFPropertyListRef	CACFPreferences::CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+	//	synchronize to make sure that what's in memory matches what's on disk
+	Synchronize(inCurrentUser, inCurrentHost, false);
+	
+	CFPropertyListRef theAnswer = NULL;
+	CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+	CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+	
+	theAnswer = CFPreferencesCopyValue(inKey, kCFPreferencesAnyApplication, theUser, theHost);
+	
+	return theAnswer;
+}
+
+CFStringRef	CACFPreferences::CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+	CFStringRef theAnswer = NULL;
+	
+	//	get the raw value
+	CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+	
+	if(theRawValue != NULL)
+	{
+		//	get it's type ID and make sure it's a CFString
+		CFTypeID theTypeID = CFGetTypeID(theRawValue);
+		if(theTypeID == CFStringGetTypeID())
+		{
+			//	cast the value
+			theAnswer = static_cast<CFStringRef>(theRawValue);
+		}
+		else
+		{
+			CFRelease(theRawValue);
+			DebugMessage("CACFPreferences::CopyStringValue: not a CFString");
+		}
+	}
+	
+	return theAnswer;
+}
+
+CFNumberRef	CACFPreferences::CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+	CFNumberRef theAnswer = NULL;
+	
+	//	get the raw value
+	CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+	
+	if(theRawValue != NULL)
+	{
+		//	get it's type ID and make sure it's a CFNumber
+		CFTypeID theTypeID = CFGetTypeID(theRawValue);
+		if(theTypeID == CFNumberGetTypeID())
+		{
+			//	cast the value
+			theAnswer = static_cast<CFNumberRef>(theRawValue);
+		}
+		else
+		{
+			CFRelease(theRawValue);
+			DebugMessage("CACFPreferences::CopyNumberValue: not a CFNumber");
+		}
+	}
+	
+	return theAnswer;
+}
+
+CFArrayRef	CACFPreferences::CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+	CFArrayRef theAnswer = NULL;
+	
+	//	get the raw value
+	CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+	
+	if(theRawValue != NULL)
+	{
+		//	get it's type ID and make sure it's a CFArray
+		CFTypeID theTypeID = CFGetTypeID(theRawValue);
+		if(theTypeID == CFArrayGetTypeID())
+		{
+			//	cast the value
+			theAnswer = static_cast<CFArrayRef>(theRawValue);
+		}
+		else
+		{
+			CFRelease(theRawValue);
+			DebugMessage("CACFPreferences::CopyArrayValue: not a CFArray");
+		}
+	}
+	
+	return theAnswer;
+}
+
+CFDictionaryRef	CACFPreferences::CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+	CFDictionaryRef theAnswer = NULL;
+	
+	//	get the raw value
+	CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+	
+	if(theRawValue != NULL)
+	{
+		//	get it's type ID and make sure it's a CFDictionary
+		CFTypeID theTypeID = CFGetTypeID(theRawValue);
+		if(theTypeID == CFDictionaryGetTypeID())
+		{
+			//	cast the value
+			theAnswer = static_cast<CFDictionaryRef>(theRawValue);
+		}
+		else
+		{
+			CFRelease(theRawValue);
+			DebugMessage("CACFPreferences::CopyDictionaryValue: not a CFDictionary");
+		}
+	}
+	
+	return theAnswer;
+}
+
+void	CACFPreferences::SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize)
+{
+	CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+	CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+	CFPreferencesSetValue(inKey, inValue, kCFPreferencesAnyApplication, theUser, theHost);
+	
+	if(inSynchronize)
+	{
+		Synchronize(inCurrentUser, inCurrentHost, true);
+	}
+}
+
+void	CACFPreferences::DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize)
+{
+	CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+	CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+	CFPreferencesSetValue(inKey, NULL, kCFPreferencesAnyApplication, theUser, theHost);
+	
+	if(inSynchronize)
+	{
+		Synchronize(theUser, inCurrentHost, true);
+	}
+}
+
+void	CACFPreferences::Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce)
+{
+	if(inForce || ArePrefsOutOfDate(inCurrentUser, inCurrentHost))
+	{
+		CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+		CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+		CFPreferencesSynchronize(kCFPreferencesAnyApplication, theUser, theHost);
+		MarkPrefsClean(inCurrentUser, inCurrentHost);
+	}
+}
+
+void	CACFPreferences::MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost)
+{
+	if(!inCurrentUser && !inCurrentHost)
+	{
+		sAnyUserAnyHostPrefsOutOfDate = true;
+	}
+	else if(!inCurrentUser && inCurrentHost)
+	{
+		sAnyUserCurrentHostPrefsOutOfDate = true;
+	}
+	else if(inCurrentUser && !inCurrentHost)
+	{
+		sCurrentUserAnyHostPrefsOutOfDate = true;
+	}
+	else if(inCurrentUser && inCurrentHost)
+	{
+		sCurrentUserCurrentHostPrefsOutOfDate = true;
+	}
+}
+
+void	CACFPreferences::MarkPrefsClean(bool inCurrentUser, bool inCurrentHost)
+{
+	if(!inCurrentUser && !inCurrentHost)
+	{
+		sAnyUserAnyHostPrefsOutOfDate = false;
+	}
+	else if(!inCurrentUser && inCurrentHost)
+	{
+		sAnyUserCurrentHostPrefsOutOfDate = false;
+	}
+	else if(inCurrentUser && !inCurrentHost)
+	{
+		sCurrentUserAnyHostPrefsOutOfDate = false;
+	}
+	else if(inCurrentUser && inCurrentHost)
+	{
+		sCurrentUserCurrentHostPrefsOutOfDate = false;
+	}
+}
+
+void	CACFPreferences::SendNotification(CFStringRef inName)
+{
+	CACFDistributedNotification::PostNotification(inName, NULL, true);
+}
+
+bool	CACFPreferences::ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost)
+{
+	bool theAnswer = false;
+	
+	if(!inCurrentUser && !inCurrentHost)
+	{
+		theAnswer = sAnyUserAnyHostPrefsOutOfDate;
+	}
+	else if(!inCurrentUser && inCurrentHost)
+	{
+		theAnswer = sAnyUserCurrentHostPrefsOutOfDate;
+	}
+	else if(inCurrentUser && !inCurrentHost)
+	{
+		theAnswer = sCurrentUserAnyHostPrefsOutOfDate;
+	}
+	else if(inCurrentUser && inCurrentHost)
+	{
+		theAnswer = sCurrentUserCurrentHostPrefsOutOfDate;
+	}
+	
+	return theAnswer;
+}
+
+bool	CACFPreferences::sAnyUserAnyHostPrefsOutOfDate = false;
+bool	CACFPreferences::sAnyUserCurrentHostPrefsOutOfDate = false;
+bool	CACFPreferences::sCurrentUserAnyHostPrefsOutOfDate = false;
+bool	CACFPreferences::sCurrentUserCurrentHostPrefsOutOfDate = false;
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h
new file mode 100644
index 0000000..040490f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h
@@ -0,0 +1,92 @@
+/*
+     File: CACFPreferences.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFPreferences_h__)
+#define __CACFPreferences_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include <CoreFoundation.h>
+#endif
+
+//==================================================================================================
+//	CACFPreferences
+//==================================================================================================
+
+class CACFPreferences
+{
+
+//	Operations
+public:
+	static CFPropertyListRef	CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+	static CFStringRef			CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+	static CFNumberRef			CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+	static CFArrayRef			CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+	static CFDictionaryRef		CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+	static void					SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize);
+	static void					DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize);
+	static void					Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce);
+	static void					MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost);
+	static void					MarkPrefsClean(bool inCurrentUser, bool inCurrentHost);
+	static void					SendNotification(CFStringRef inName);
+
+private:
+	static bool					ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost);
+	
+	static bool					sAnyUserAnyHostPrefsOutOfDate;
+	static bool					sAnyUserCurrentHostPrefsOutOfDate;
+	static bool					sCurrentUserAnyHostPrefsOutOfDate;
+	static bool					sCurrentUserCurrentHostPrefsOutOfDate;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp
new file mode 100644
index 0000000..3ce81a5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp
@@ -0,0 +1,110 @@
+/*
+     File: CACFString.cpp
+ Abstract: CACFString.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CACFString.h"
+
+//=============================================================================
+//	CACFString
+//=============================================================================
+
+UInt32	CACFString::GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding)
+{
+	CFIndex theAnswer = 0;
+	
+	if(inCFString != NULL)
+	{
+		CFRange theRange = { 0, CFStringGetLength(inCFString) };
+		CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, NULL, 0x7FFFFFFF, &theAnswer);
+	}
+	
+	return UInt32(theAnswer);
+}
+
+void	CACFString::GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding)
+{
+	if(ioStringSize > 0)
+	{
+		if(inCFString != NULL)
+		{
+			CFIndex theLength = 0;
+			CFRange theRange = { 0, CFStringGetLength(inCFString) };
+			CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, (UInt8*)outString, static_cast<CFIndex>(ioStringSize - 1), &theLength);
+			outString[theLength] = 0;
+			ioStringSize = ToUInt32(theLength) + 1;
+		}
+		else
+		{
+			outString[0] = 0;
+			ioStringSize = 1;
+		}
+	}
+}
+
+void	CACFString::GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize)
+{
+	if(ioStringSize > 0)
+	{
+		if(inCFString != NULL)
+		{
+			CFRange theStringRange = { 0, CFStringGetLength(inCFString) };
+			if(static_cast<UInt32>(theStringRange.length) > ioStringSize)
+			{
+				theStringRange.length = static_cast<CFIndex>(ioStringSize);
+			}
+			CFStringGetCharacters(inCFString, theStringRange, outString);
+			ioStringSize = ToUInt32(theStringRange.length);
+		}
+		else
+		{
+			outString[0] = 0;
+			ioStringSize = 0;
+		}
+	}
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFString.h b/libs/appleutility/CoreAudio/PublicUtility/CACFString.h
new file mode 100644
index 0000000..3abce51
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFString.h
@@ -0,0 +1,196 @@
+/*
+     File: CACFString.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CACFString_h__)
+#define __CACFString_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CADebugMacros.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <CoreFoundation/CFString.h>
+#else
+	#include <CoreAudioTypes.h>
+	#include <CFString.h>
+#endif
+
+//=============================================================================
+//	CACFString
+//
+//	Notes
+//	-	Using the AssignWithoutRetain() method will fool the static analyzer into thinking that the
+//		CFString being assigned will be leaked. This is because the static analyzer is not smart
+//		enough to understand that the destructor will release the object.
+//=============================================================================
+
+class	CACFString
+{
+//	Construction/Destruction
+public:
+						CACFString() : mCFString(NULL), mWillRelease(true) {}
+	explicit			CACFString(CFStringRef inCFString) : mCFString(inCFString), mWillRelease(true) {}
+						CACFString(const char* inCString) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(true) {}
+						CACFString(CFStringRef inCFString, bool inWillRelease) : mCFString(inCFString), mWillRelease(inWillRelease) {}
+						CACFString(const char* inCString, bool inWillRelease) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(inWillRelease) {}
+						CACFString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFString(CFStringCreateWithCString(NULL, inCString, inCStringEncoding)), mWillRelease(inWillRelease) {}
+						~CACFString() { Release(); }
+						CACFString(const CACFString& inString) : mCFString(inString.mCFString), mWillRelease(inString.mWillRelease) { Retain(); }
+	CACFString&			operator=(const CACFString& inString) { if (inString.mCFString != mCFString) { Release(); mCFString = inString.mCFString; mWillRelease = inString.mWillRelease; Retain(); } return *this; }
+	CACFString&			operator=(CFStringRef inCFString) { if (inCFString != mCFString) { Release(); mCFString = inCFString; } mWillRelease = true; Retain(); return *this; }
+	void				AssignWithoutRetain(CFStringRef inCFString) { if (inCFString != mCFString) { Release(); mCFString = inCFString; } mWillRelease = true; }
+
+private:
+	void				Retain() { if(mWillRelease && (mCFString != NULL)) { CFRetain(mCFString); } }
+	void				Release() { if(mWillRelease && (mCFString != NULL)) { CFRelease(mCFString); } }
+	
+	CFStringRef			mCFString;
+	bool				mWillRelease;
+
+//	Operations
+public:
+	void				AllowRelease() { mWillRelease = true; }
+	void				DontAllowRelease() { mWillRelease = false; }
+	bool				IsValid() const { return mCFString != NULL; }
+	bool				IsEqualTo(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringCompare(inString, mCFString, 0) == kCFCompareEqualTo; } return theAnswer; }
+	bool				StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasPrefix(mCFString, inString); } return theAnswer; }
+	bool				EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasSuffix(mCFString, inString); } return theAnswer; }
+
+//	Value Access
+public:
+	CFStringRef			GetCFString() const { return mCFString; }
+	CFStringRef			CopyCFString() const { if(mCFString != NULL) { CFRetain(mCFString); } return mCFString; }
+	const CFStringRef*	GetPointerToStorage() const	{ return &mCFString; }
+	CFStringRef&		GetStorage() { Release(); mWillRelease = true; return mCFString; }
+	UInt32				GetLength() const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = ToUInt32(CFStringGetLength(mCFString)); } return theAnswer; }
+	UInt32				GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = GetStringByteLength(mCFString, inEncoding); } return theAnswer; }
+	void				GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { GetCString(mCFString, outString, ioStringSize, inEncoding); }
+	void				GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { GetUnicodeString(mCFString, outString, ioStringSize); }
+	SInt32				GetAsInteger() { return GetAsInteger(mCFString); }
+	Float64				GetAsFloat64() { return GetAsFloat64(mCFString); }
+
+	static UInt32		GetStringLength(CFStringRef inCFString)  { UInt32 theAnswer = 0; if(inCFString != NULL) { theAnswer = ToUInt32(CFStringGetLength(inCFString)); } return theAnswer; }
+	static UInt32		GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
+	static void			GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
+	static void			GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize);
+	static SInt32		GetAsInteger(CFStringRef inCFString) { SInt32 theAnswer = 0; if(inCFString != NULL){ theAnswer = CFStringGetIntValue(inCFString); } return theAnswer; }
+	static Float64		GetAsFloat64(CFStringRef inCFString) { Float64 theAnswer = 0; if(inCFString != NULL){ theAnswer = CFStringGetDoubleValue(inCFString); } return theAnswer; }
+	
+};
+
+inline bool	operator<(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareLessThan; }
+inline bool	operator==(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareEqualTo; }
+inline bool	operator!=(const CACFString& x, const CACFString& y) { return !(x == y); }
+inline bool	operator<=(const CACFString& x, const CACFString& y) { return (x < y) || (x == y); }
+inline bool	operator>=(const CACFString& x, const CACFString& y) { return !(x < y); }
+inline bool	operator>(const CACFString& x, const CACFString& y) { return !((x < y) || (x == y)); }
+
+inline bool	operator<(const CACFString& x, CFStringRef y) { return CFStringCompare(x.GetCFString(), y, 0) == kCFCompareLessThan; }
+inline bool	operator==(const CACFString& x, CFStringRef y) { return CFStringCompare(x.GetCFString(), y, 0) == kCFCompareEqualTo; }
+inline bool	operator!=(const CACFString& x, CFStringRef y) { return !(x == y); }
+inline bool	operator<=(const CACFString& x, CFStringRef y) { return (x < y) || (x == y); }
+inline bool	operator>=(const CACFString& x, CFStringRef y) { return !(x < y); }
+inline bool	operator>(const CACFString& x, CFStringRef y) { return !((x < y) || (x == y)); }
+
+inline bool	operator<(CFStringRef x, const CACFString& y) { return CFStringCompare(x, y.GetCFString(), 0) == kCFCompareLessThan; }
+inline bool	operator==(CFStringRef x, const CACFString& y) { return CFStringCompare(x, y.GetCFString(), 0) == kCFCompareEqualTo; }
+inline bool	operator!=(CFStringRef x, const CACFString& y) { return !(x == y); }
+inline bool	operator<=(CFStringRef x, const CACFString& y) { return (x < y) || (x == y); }
+inline bool	operator>=(CFStringRef x, const CACFString& y) { return !(x < y); }
+inline bool	operator>(CFStringRef x, const CACFString& y) { return !((x < y) || (x == y)); }
+
+//=============================================================================
+//	CACFMutableString
+//=============================================================================
+
+class	CACFMutableString
+{
+//	Construction/Destruction
+public:
+						CACFMutableString() : mCFMutableString(NULL), mWillRelease(true) {}
+						CACFMutableString(CFMutableStringRef inCFMutableString, bool inWillRelease = true) : mCFMutableString(inCFMutableString), mWillRelease(inWillRelease) {}
+						CACFMutableString(CFStringRef inStringToCopy, bool /*inMakeCopy*/, bool inWillRelease = true) : mCFMutableString(CFStringCreateMutableCopy(NULL, 0, inStringToCopy)), mWillRelease(inWillRelease) {}
+						CACFMutableString(const char* inCString, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
+						CACFMutableString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString, inCStringEncoding); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
+						~CACFMutableString() { Release(); }
+						CACFMutableString(const CACFMutableString& inString) : mCFMutableString(inString.mCFMutableString), mWillRelease(inString.mWillRelease) { Retain(); }
+	CACFMutableString&	operator=(const CACFMutableString& inString) { Release(); mCFMutableString = inString.mCFMutableString; mWillRelease = inString.mWillRelease; Retain(); return *this; }
+	CACFMutableString&	operator=(CFMutableStringRef inCFMutableString) { Release(); mCFMutableString = inCFMutableString; mWillRelease = true; return *this; }
+
+private:
+	void				Retain() { if(mWillRelease && (mCFMutableString != NULL)) { CFRetain(mCFMutableString); } }
+	void				Release() { if(mWillRelease && (mCFMutableString != NULL)) { CFRelease(mCFMutableString); } }
+	
+	CFMutableStringRef	mCFMutableString;
+	bool				mWillRelease;
+
+//	Operations
+public:
+	void				AllowRelease() { mWillRelease = true; }
+	void				DontAllowRelease() { mWillRelease = false; }
+	bool				IsValid() { return mCFMutableString != NULL; }
+	bool				IsEqualTo(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringCompare(inString, mCFMutableString, 0) == kCFCompareEqualTo; } return theAnswer; }
+	bool				StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasPrefix(mCFMutableString, inString); } return theAnswer; }
+	bool				EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasSuffix(mCFMutableString, inString); } return theAnswer; }
+	void				Append(CFStringRef inString) { if(mCFMutableString != NULL) { CFStringAppend(mCFMutableString, inString); } }
+
+//	Value Access
+public:
+	CFMutableStringRef	GetCFMutableString() const { return mCFMutableString; }
+	CFMutableStringRef	CopyCFMutableString() const { if(mCFMutableString != NULL) { CFRetain(mCFMutableString); } return mCFMutableString; }
+	UInt32				GetLength() const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = ToUInt32(CFStringGetLength(mCFMutableString)); } return theAnswer; }
+	UInt32				GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = CACFString::GetStringByteLength(mCFMutableString, inEncoding); } return theAnswer; }
+	void				GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { CACFString::GetCString(mCFMutableString, outString, ioStringSize, inEncoding); }
+	void				GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { CACFString::GetUnicodeString(mCFMutableString, outString, ioStringSize); }
+	SInt32				GetAsInteger() { return CACFString::GetAsInteger(mCFMutableString); }
+	Float64				GetAsFloat64() { return CACFString::GetAsFloat64(mCFMutableString); }
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp
new file mode 100644
index 0000000..04eae54
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp
@@ -0,0 +1,182 @@
+/*
+     File: CAComponent.cpp
+ Abstract: CAComponent.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAComponent.h"
+#include "CAComponentDescription.h"
+#include "CACFDictionary.h"
+#include <stdlib.h>
+#include "CAAutoDisposer.h"
+
+CAComponent::CAComponent (const AudioComponentDescription& inDesc, CAComponent* next)
+	: mManuName(0), mAUName(0), mCompName(0)
+{
+	mComp = AudioComponentFindNext ((next ? next->Comp() : NULL), &inDesc);
+	if (mComp)
+		AudioComponentGetDescription(Comp(), &mDesc);
+	else
+		memcpy (&mDesc, &inDesc, sizeof(AudioComponentDescription));
+}
+
+CAComponent::CAComponent (const AudioComponent& comp) 
+	: mComp (comp),
+	  mManuName(0), 
+	  mAUName(0), 
+	  mCompName(0)
+{
+	AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::CAComponent (const AudioComponentInstance& compInst) 
+	: mComp (NULL), 
+	  mManuName(0), 
+	  mAUName(0), 
+	  mCompName(0)
+{ 
+	mComp = AudioComponentInstanceGetComponent (compInst);
+	AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::CAComponent (OSType inType, OSType inSubtype, OSType inManu)
+	: mDesc (inType, inSubtype, inManu),
+	  mManuName(0), mAUName(0), mCompName(0)
+{
+	mComp = AudioComponentFindNext (NULL, &mDesc);
+	AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::~CAComponent ()
+{
+	Clear();
+}
+
+OSStatus		CAComponent::GetVersion (UInt32 &outVersion) const
+{
+	return AudioComponentGetVersion (mComp, &outVersion);
+}
+
+void			CAComponent::Clear ()
+{
+	if (mManuName) { CFRelease (mManuName); mManuName = 0; }
+	if (mAUName) { CFRelease (mAUName);  mAUName = 0; }
+	if (mCompName) { CFRelease (mCompName); mCompName = 0; }
+}
+
+CAComponent&	CAComponent::operator= (const CAComponent& y)
+{
+	Clear();
+
+	mComp = y.mComp;
+	mDesc = y.mDesc;
+
+	if (y.mManuName) { mManuName = y.mManuName; CFRetain (mManuName); }
+	if (y.mAUName) { mAUName = y.mAUName; CFRetain (mAUName); }
+	if (y.mCompName) { mCompName = y.mCompName; CFRetain (mCompName); } 
+
+	return *this;
+}
+
+void 		CAComponent::SetCompNames () const
+{
+	if (!mCompName) {
+	
+		CFStringRef compName;
+		OSStatus result = AudioComponentCopyName (Comp(), &compName);
+		if (result) return;
+		
+		const_cast<CAComponent*>(this)->mCompName = compName;
+		if (compName)
+		{
+			CFArrayRef splitStrArray = CFStringCreateArrayBySeparatingStrings(NULL, compName, CFSTR(":"));
+			
+			// we need to retain these values so the strings are not lost when the array is released
+			const_cast<CAComponent*>(this)->mManuName = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 0);
+            CFRetain(this->mManuName);
+			if (CFArrayGetCount(splitStrArray) > 1)
+			{
+				CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 1);
+				
+				CFMutableStringRef mstr = CFStringCreateMutableCopy (NULL, CFStringGetLength(str), str);
+
+				// this needs to trim out white space:
+				
+				CFStringTrimWhitespace (mstr);
+			
+				const_cast<CAComponent*>(this)->mAUName = mstr;
+			} else
+				const_cast<CAComponent*>(this)->mAUName = NULL;
+			
+			CFRelease(splitStrArray);
+		}
+	}
+}
+
+static void	_ShowCF (FILE* file, CFStringRef str)
+{
+	if (CFGetTypeID(str) != CFStringGetTypeID()) {
+		CFShow(str);
+		return;
+	}
+
+	CFIndex len = CFStringGetLength(str);
+	char* chars = (char*)CA_malloc (len * 2); // give us plenty of room for unichar chars
+	if (CFStringGetCString (str, chars, len * 2, kCFStringEncodingUTF8))
+		fprintf (file, "%s", chars);
+	else
+		CFShow (str);
+
+	free (chars);
+}
+
+void	CAComponent::Print(FILE* file) const
+{
+	fprintf (file, "CAComponent: %p", Comp());
+	if (mManuName) {
+		fprintf (file, ", Manu:"); _ShowCF (file, mManuName);
+		if (mAUName) fprintf (file, ", Name:"); _ShowCF (file, mAUName);
+	}
+	fprintf (file, ", "); 
+	Desc ().Print(file);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h
new file mode 100644
index 0000000..5ff24ee
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h
@@ -0,0 +1,121 @@
+/*
+     File: CAComponent.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAComponent_h__
+#define __CAComponent_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#else
+	#include <ConditionalMacros.h>
+#endif
+
+#include "CAComponentDescription.h"
+
+class CAComponent 
+{
+public:
+	CAComponent ()
+		: mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) {}
+		
+		// if next is specifed that is used to find the next component after that one
+	CAComponent (const AudioComponentDescription& inDesc, CAComponent* next = 0);
+	
+	CAComponent (const CAComponent& y) 
+		: mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) { *this = y; }
+
+	CAComponent (const AudioComponent& comp);
+	
+	CAComponent (const AudioComponentInstance& compInst);
+
+	CAComponent (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+	
+	~CAComponent ();
+	
+	CAComponent&	operator= (const CAComponent& y);
+	
+		// returns true if this object references a valid component
+	bool			IsValid () const { return Comp() != 0; }
+	
+	bool			HasAUStrings() const { 	SetCompNames (); return mManuName != 0; }
+
+		// CFStringRef should be retained by caller if needed beyond lifetime of this object
+		
+		// Can return NULL if component doesn't follow AU naming conventions
+	CFStringRef		GetAUManu () const { SetCompNames (); return mManuName; }
+	CFStringRef		GetAUName () const { SetCompNames (); return mAUName ? mAUName : mCompName; }
+		
+		// Return value of NULL indicates a problem getting that information from the component
+	CFStringRef		GetCompName () const { SetCompNames(); return mCompName; }
+	
+	const CAComponentDescription&	Desc () const { return mDesc; }
+			
+	OSStatus		Open (AudioComponentInstance& outInst) const 
+	{
+		return AudioComponentInstanceNew (Comp(), &outInst);
+  	}
+
+	OSStatus			GetVersion (UInt32 &outVersion) const;
+	
+	const AudioComponent&		Comp() const { return mComp; }
+	
+	void				Print(FILE* file = stdout) const;
+
+	OSStatus			Save (CFPropertyListRef *outData) const;
+		
+	OSStatus			Restore (CFPropertyListRef &inData);
+	
+private:
+	AudioComponent mComp;
+	CAComponentDescription mDesc;
+	
+	CFStringRef mManuName, mAUName, mCompName;
+
+	void	SetCompNames () const;
+	void	SetCompInfo () const;
+	void	Clear ();
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp
new file mode 100644
index 0000000..a3c877b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp
@@ -0,0 +1,110 @@
+/*
+     File: CAComponentDescription.cpp
+ Abstract: CAComponentDescription.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAComponentDescription.h"
+#include "CAStreamBasicDescription.h"
+#include <ctype.h>
+
+void CAShowComponentDescription(const AudioComponentDescription *desc)
+{
+	CAComponentDescription::_CAShowComponentDescription (desc, stdout);
+}
+
+void 	CAComponentDescription::_CAShowComponentDescription(const AudioComponentDescription *desc, FILE* file)
+{
+	if (desc)
+	{
+		char str[24];
+		fprintf (file, "AudioComponentDescription: %s - ", CAStringForOSType(desc->componentType, str, sizeof(str)));
+		fprintf (file, "%s - ", CAStringForOSType(desc->componentSubType, str, sizeof(str)));
+		fprintf (file, "%s", CAStringForOSType(desc->componentManufacturer, str, sizeof(str)));		
+		fprintf (file, ", 0x%X, 0x%X\n", (int)desc->componentFlags, (int)desc->componentFlagsMask);
+	}
+}
+
+CAComponentDescription::CAComponentDescription (OSType inType, OSType inSubtype, OSType inManu)
+{
+	componentType = inType;
+	componentSubType = inSubtype;
+	componentManufacturer = inManu;
+	componentFlags = 0;
+	componentFlagsMask = 0;
+}
+
+bool	CAComponentDescription::IsAU () const 
+{ 
+	bool flag = IsEffect() || IsMusicDevice() || IsOffline();
+	if (flag) return true;
+	
+	switch (componentType) {
+		case kAudioUnitType_Output:
+		case kAudioUnitType_FormatConverter:
+		case kAudioUnitType_Mixer:
+			return true;
+	}
+	return false;
+}
+
+inline bool _MatchTest (const OSType &inTypeA, const OSType &inTypeB)
+{
+	return ((inTypeA == inTypeB) || (!inTypeA && !inTypeB) || (inTypeA && !inTypeB) || (!inTypeA && inTypeB)); 
+}
+
+bool	CAComponentDescription::Matches (const AudioComponentDescription &desc) const
+{
+	bool matches = false;
+		
+		// see if the type matches
+	matches = _MatchTest (componentType, desc.componentType);
+	
+	if (matches)
+		matches = _MatchTest (componentSubType, desc.componentSubType);
+	
+	if (matches)
+		matches = _MatchTest (componentManufacturer, desc.componentManufacturer);
+	
+	return matches;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h
new file mode 100644
index 0000000..5c756ea
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h
@@ -0,0 +1,145 @@
+/*
+     File: CAComponentDescription.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAComponentDescription_h__
+#define __CAComponentDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioUnit.h>
+#else
+	#include <ConditionalMacros.h>
+	#include <AudioUnit.h>
+#endif
+
+#include "CACFDictionary.h"
+#include <stdio.h>
+#include <string.h>
+
+void CAShowComponentDescription(const AudioComponentDescription *desc);
+
+// ____________________________________________________________________________
+//
+//	CAComponentDescription
+class CAComponentDescription : public AudioComponentDescription {
+public:
+	CAComponentDescription() { memset (this, 0, sizeof (AudioComponentDescription)); }
+	
+	CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+
+	CAComponentDescription(const AudioComponentDescription& desc) { memcpy (this, &desc, sizeof (AudioComponentDescription)); }
+		
+	// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+	//
+	// interrogation
+	
+	bool	IsAU () const;
+	
+	bool	IsAUFX() const { return componentType == kAudioUnitType_Effect; }
+	bool	IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; }
+    
+    bool    IsAUMI() const { return componentType == 'aumi' /*kAudioUnitType_MIDIProcessor*/; }
+	
+	bool	IsAUAX () const { return componentType == 'auax' /*kAudioUnitType_Auxiliary*/; }
+	
+	bool 	IsEffect () const { return IsAUFX() || IsAUFM() || IsPanner(); }
+	
+	bool	IsOffline () const { return componentType == 'auol' /*kAudioUnitType_Offline*/; }
+	
+	bool 	IsFConv () const { return componentType == kAudioUnitType_FormatConverter; }
+	
+	bool	IsPanner () const { return componentType == kAudioUnitType_Panner; }
+	
+	bool	IsMusicDevice () const { return componentType == kAudioUnitType_MusicDevice; }
+	
+#ifndef MAC_OS_X_VERSION_10_4
+	bool	IsGenerator () const { return componentType =='augn'; }
+#else
+	bool	IsGenerator () const { return componentType ==kAudioUnitType_Generator; }
+#endif
+	
+	bool	IsOutput () const { return componentType == kAudioUnitType_Output; }
+	
+	bool	IsSource () const { return IsMusicDevice() || IsGenerator(); }
+	
+	OSType	Type () const { return componentType; }
+	OSType	SubType () const { return componentSubType; }
+	OSType 	Manu () const { return componentManufacturer; }
+
+	int		Count() const { return AudioComponentCount(const_cast<CAComponentDescription*>(this)); }
+	
+		// does a semantic match where "wild card" values for type, subtype, manu will match
+	bool	Matches (const AudioComponentDescription &desc) const;
+	
+	// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+	//
+	//	other
+	
+	void	Print(FILE* file = stdout) const 	{ _CAShowComponentDescription (this, file); }
+
+	OSStatus			Save (CFPropertyListRef *outData) const;
+	OSStatus			Restore (CFPropertyListRef &inData);
+
+private:
+	static void _CAShowComponentDescription (const AudioComponentDescription *desc, FILE* file);
+	friend void CAShowComponentDescription (const AudioComponentDescription *desc);
+};
+
+inline bool	operator< (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+	return memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags)) < 0;
+}
+
+inline bool	operator== (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+	return !memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags));
+}
+
+inline bool	operator!= (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+	return !(x == y);
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp
new file mode 100644
index 0000000..9739e37
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp
@@ -0,0 +1,90 @@
+/*
+     File: CADebugMacros.cpp
+ Abstract: CADebugMacros.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CADebugMacros.h"
+#include <stdio.h>
+#include <stdarg.h>
+#if TARGET_API_MAC_OSX
+	#include <syslog.h>
+#endif
+
+#if DEBUG
+#include <stdio.h>
+
+void	DebugPrint(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vprintf(fmt, args);
+	va_end(args);
+}
+#endif // DEBUG
+
+void	LogError(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+#if DEBUG
+	vprintf(fmt, args);
+#endif
+#if TARGET_API_MAC_OSX
+	vsyslog(LOG_ERR, fmt, args);
+#endif
+	va_end(args);
+}
+
+void	LogWarning(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+#if DEBUG
+	vprintf(fmt, args);
+#endif
+#if TARGET_API_MAC_OSX
+	vsyslog(LOG_WARNING, fmt, args);
+#endif
+	va_end(args);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h
new file mode 100644
index 0000000..15af919
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h
@@ -0,0 +1,581 @@
+/*
+     File: CADebugMacros.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CADebugMacros_h__)
+#define __CADebugMacros_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+//	CADebugMacros
+//=============================================================================
+
+//#define	CoreAudio_StopOnFailure			1
+//#define	CoreAudio_TimeStampMessages		1
+//#define	CoreAudio_ThreadStampMessages	1
+//#define	CoreAudio_FlushDebugMessages	1
+
+#if TARGET_RT_BIG_ENDIAN
+	#define	CA4CCToCString(the4CC)					{ ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 }
+	#define CACopy4CCToCString(theCString, the4CC)	{ theCString[0] = ((char*)&the4CC)[0]; theCString[1] = ((char*)&the4CC)[1]; theCString[2] = ((char*)&the4CC)[2]; theCString[3] = ((char*)&the4CC)[3]; theCString[4] = 0; }
+#else
+	#define	CA4CCToCString(the4CC)					{ ((char*)&the4CC)[3], ((char*)&the4CC)[2], ((char*)&the4CC)[1], ((char*)&the4CC)[0], 0 }
+	#define CACopy4CCToCString(theCString, the4CC)	{ theCString[0] = ((char*)&the4CC)[3]; theCString[1] = ((char*)&the4CC)[2]; theCString[2] = ((char*)&the4CC)[1]; theCString[3] = ((char*)&the4CC)[0]; theCString[4] = 0; }
+#endif
+
+//	This is a macro that does a sizeof and casts the result to a UInt32. This is useful for all the
+//	places where -wshorten64-32 catches assigning a sizeof expression to a UInt32.
+//	For want of a better place to park this, we'll park it here.
+#define	SizeOf32(X)	((UInt32)sizeof(X))
+
+//	This is a macro that does a offsetof and casts the result to a UInt32. This is useful for all the
+//	places where -wshorten64-32 catches assigning an offsetof expression to a UInt32.
+//	For want of a better place to park this, we'll park it here.
+#define	OffsetOf32(X, Y)	((UInt32)offsetof(X, Y))
+
+//	This macro casts the expression to a UInt32. It is called out specially to allow us to track casts
+//	that have been added purely to avert -wshorten64-32 warnings on 64 bit platforms.
+//	For want of a better place to park this, we'll park it here.
+#define	ToUInt32(X)	((UInt32)(X))
+#define	ToSInt32(X)	((SInt32)(X))
+
+#pragma mark	Basic Definitions
+
+#if	DEBUG || CoreAudio_Debug
+	// can be used to break into debugger immediately, also see CADebugger
+	#define BusError()		{ long* p=NULL; *p=0; }
+	
+	//	basic debugging print routines
+	#if	TARGET_OS_MAC && !TARGET_API_MAC_CARBON
+		extern void DebugStr(const unsigned char* debuggerMsg);
+		#define	DebugMessage(msg)	DebugStr("\p"msg)
+		#define DebugMessageN1(msg, N1)
+		#define DebugMessageN2(msg, N1, N2)
+		#define DebugMessageN3(msg, N1, N2, N3)
+	#else
+		#include "CADebugPrintf.h"
+		
+		#if	(CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
+			#define	FlushRtn	,fflush(DebugPrintfFile)
+		#else
+			#define	FlushRtn
+		#endif
+		
+		#if		CoreAudio_ThreadStampMessages
+			#include <pthread.h>
+			#include "CAHostTimeBase.h"
+			#if TARGET_RT_64_BIT
+				#define	DebugPrintfThreadIDFormat	"%16p"
+			#else
+				#define	DebugPrintfThreadIDFormat	"%8p"
+			#endif
+			#define	DebugMsg(inFormat, ...)	DebugPrintf("%17qd: " DebugPrintfThreadIDFormat " " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), pthread_self(), ## __VA_ARGS__) FlushRtn
+		#elif	CoreAudio_TimeStampMessages
+			#include "CAHostTimeBase.h"
+			#define	DebugMsg(inFormat, ...)	DebugPrintf("%17qd: " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), ## __VA_ARGS__) FlushRtn
+		#else
+			#define	DebugMsg(inFormat, ...)	DebugPrintf(inFormat, ## __VA_ARGS__) FlushRtn
+		#endif
+	#endif
+	void	DebugPrint(const char *fmt, ...);	// can be used like printf
+	#ifndef DEBUGPRINT
+		#define DEBUGPRINT(msg) DebugPrint msg		// have to double-parenthesize arglist (see Debugging.h)
+	#endif
+	#if VERBOSE
+		#define vprint(msg) DEBUGPRINT(msg)
+	#else
+		#define vprint(msg)
+	#endif
+	
+	// Original macro keeps its function of turning on and off use of CADebuggerStop() for both asserts and throws.
+	// For backwards compat, it overrides any setting of the two sub-macros.
+	#if	CoreAudio_StopOnFailure
+		#include "CADebugger.h"
+		#undef CoreAudio_StopOnAssert
+		#define CoreAudio_StopOnAssert 1
+		#undef CoreAudio_StopOnThrow
+		#define CoreAudio_StopOnThrow 1
+		#define STOP	CADebuggerStop()
+	#else
+		#define STOP
+	#endif
+
+	#if CoreAudio_StopOnAssert
+		#if !CoreAudio_StopOnFailure
+			#include "CADebugger.h"
+			#define STOP
+		#endif
+		#define __ASSERT_STOP CADebuggerStop()
+	#else
+		#define __ASSERT_STOP
+	#endif
+
+	#if CoreAudio_StopOnThrow
+		#if !CoreAudio_StopOnFailure
+			#include "CADebugger.h"
+			#define STOP
+		#endif
+		#define __THROW_STOP CADebuggerStop()
+	#else
+		#define __THROW_STOP
+	#endif
+
+#else
+	#define	DebugMsg(inFormat, ...)
+	#ifndef DEBUGPRINT
+		#define DEBUGPRINT(msg)
+	#endif
+	#define vprint(msg)
+	#define	STOP
+	#define __ASSERT_STOP
+	#define __THROW_STOP
+#endif
+
+//	Old-style numbered DebugMessage calls are implemented in terms of DebugMsg() now
+#define	DebugMessage(msg)										DebugMsg(msg)
+#define DebugMessageN1(msg, N1)									DebugMsg(msg, N1)
+#define DebugMessageN2(msg, N1, N2)								DebugMsg(msg, N1, N2)
+#define DebugMessageN3(msg, N1, N2, N3)							DebugMsg(msg, N1, N2, N3)
+#define DebugMessageN4(msg, N1, N2, N3, N4)						DebugMsg(msg, N1, N2, N3, N4)
+#define DebugMessageN5(msg, N1, N2, N3, N4, N5)					DebugMsg(msg, N1, N2, N3, N4, N5)
+#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6)				DebugMsg(msg, N1, N2, N3, N4, N5, N6)
+#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7)			DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7)
+#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8)		DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8)
+#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9)	DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9)
+
+void	LogError(const char *fmt, ...);			// writes to syslog (and stderr if debugging)
+void	LogWarning(const char *fmt, ...);		// writes to syslog (and stderr if debugging)
+
+#define	NO_ACTION	(void)0
+
+#if	DEBUG || CoreAudio_Debug
+
+#pragma mark	Debug Macros
+
+#define	Assert(inCondition, inMessage)													\
+			if(!(inCondition))															\
+			{																			\
+				DebugMessage(inMessage);												\
+				__ASSERT_STOP;																	\
+			}
+
+#define	AssertFileLine(inCondition, inMessage)											\
+			if(!(inCondition))															\
+			{																			\
+				DebugMessageN3("%s, line %d: %s", __FILE__, __LINE__, inMessage);		\
+				__ASSERT_STOP;															\
+			}
+
+#define	AssertNoError(inError, inMessage)												\
+			{																			\
+				SInt32 __Err = (inError);												\
+				if(__Err != 0)															\
+				{																		\
+					char __4CC[5] = CA4CCToCString(__Err);								\
+					DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC);		\
+					__ASSERT_STOP;														\
+				}																		\
+			}
+
+#define	AssertNoKernelError(inError, inMessage)											\
+			{																			\
+				unsigned int __Err = (unsigned int)(inError);							\
+				if(__Err != 0)															\
+				{																		\
+					DebugMessageN1(inMessage ", Error: 0x%X", __Err);					\
+					__ASSERT_STOP;														\
+				}																		\
+			}
+
+#define	AssertNotNULL(inPtr, inMessage)													\
+			{																			\
+				if((inPtr) == NULL)														\
+				{																		\
+					DebugMessage(inMessage);											\
+					__ASSERT_STOP;														\
+				}																		\
+			}
+
+#define	FailIf(inCondition, inHandler, inMessage)										\
+			if(inCondition)																\
+			{																			\
+				DebugMessage(inMessage);												\
+				STOP;																	\
+				goto inHandler;															\
+			}
+
+#define	FailWithAction(inCondition, inAction, inHandler, inMessage)						\
+			if(inCondition)																\
+			{																			\
+				DebugMessage(inMessage);												\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfNULL(inPointer, inAction, inHandler, inMessage)							\
+			if((inPointer) == NULL)														\
+			{																			\
+				DebugMessage(inMessage);												\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfKernelError(inKernelError, inAction, inHandler, inMessage)				\
+			{																			\
+				unsigned int __Err = (inKernelError);									\
+				if(__Err != 0)															\
+				{																		\
+					DebugMessageN1(inMessage ", Error: 0x%X", __Err);					\
+					STOP;																\
+					{ inAction; }														\
+					goto inHandler;														\
+				}																		\
+			}
+
+#define	FailIfError(inError, inAction, inHandler, inMessage)							\
+			{																			\
+				SInt32 __Err = (inError);												\
+				if(__Err != 0)															\
+				{																		\
+					char __4CC[5] = CA4CCToCString(__Err);								\
+					DebugMessageN2(inMessage ", Error: %ld (%s)", (long int)__Err, __4CC);	\
+					STOP;																\
+					{ inAction; }														\
+					goto inHandler;														\
+				}																		\
+			}
+
+#define	FailIfNoMessage(inCondition, inHandler, inMessage)								\
+			if(inCondition)																\
+			{																			\
+				STOP;																	\
+				goto inHandler;															\
+			}
+
+#define	FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage)			\
+			if(inCondition)																\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage)					\
+			if((inPointer) == NULL)														\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage)		\
+			{																			\
+				unsigned int __Err = (inKernelError);									\
+				if(__Err != 0)															\
+				{																		\
+					STOP;																\
+					{ inAction; }														\
+					goto inHandler;														\
+				}																		\
+			}
+
+#define	FailIfErrorNoMessage(inError, inAction, inHandler, inMessage)					\
+			{																			\
+				SInt32 __Err = (inError);												\
+				if(__Err != 0)															\
+				{																		\
+					STOP;																\
+					{ inAction; }														\
+					goto inHandler;														\
+				}																		\
+			}
+
+#if defined(__cplusplus)
+
+#define Throw(inException)  __THROW_STOP; throw (inException)
+
+#define	ThrowIf(inCondition, inException, inMessage)									\
+			if(inCondition)																\
+			{																			\
+				DebugMessage(inMessage);												\
+				Throw(inException);														\
+			}
+
+#define	ThrowIfNULL(inPointer, inException, inMessage)									\
+			if((inPointer) == NULL)														\
+			{																			\
+				DebugMessage(inMessage);												\
+				Throw(inException);														\
+			}
+
+#define	ThrowIfKernelError(inKernelError, inException, inMessage)						\
+			{																			\
+				int __Err = (inKernelError);											\
+				if(__Err != 0)															\
+				{																		\
+					DebugMessageN1(inMessage ", Error: 0x%X", __Err);					\
+					Throw(inException);													\
+				}																		\
+			}
+
+#define	ThrowIfError(inError, inException, inMessage)									\
+			{																			\
+				SInt32 __Err = (inError);												\
+				if(__Err != 0)															\
+				{																		\
+					char __4CC[5] = CA4CCToCString(__Err);								\
+					DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC);	\
+					Throw(inException);													\
+				}																		\
+			}
+
+#if TARGET_OS_WIN32
+#define	ThrowIfWinError(inError, inException, inMessage)								\
+			{																			\
+				HRESULT __Err = (inError);												\
+				if(FAILED(__Err))														\
+				{																		\
+					DebugMessageN2(inMessage ", Code: %d, Facility: 0x%X", HRESULT_CODE(__Err), HRESULT_FACILITY(__Err));			\
+					Throw(inException);													\
+				}																		\
+			}
+#endif
+
+#define	SubclassResponsibility(inMethodName, inException)								\
+			{																			\
+				DebugMessage(inMethodName": Subclasses must implement this method");	\
+				Throw(inException);														\
+			}
+
+#endif	//	defined(__cplusplus)
+
+#else
+
+#pragma mark	Release Macros
+
+#define	Assert(inCondition, inMessage)													\
+			if(!(inCondition))															\
+			{																			\
+				__ASSERT_STOP;															\
+			}
+
+#define AssertFileLine(inCondition, inMessage) Assert(inCondition, inMessage)
+
+#define	AssertNoError(inError, inMessage)												\
+			{																			\
+				SInt32 __Err = (inError);												\
+				if(__Err != 0)															\
+				{																		\
+					__ASSERT_STOP;														\
+				}																		\
+			}
+
+#define	AssertNoKernelError(inError, inMessage)											\
+			{																			\
+				unsigned int __Err = (unsigned int)(inError);							\
+				if(__Err != 0)															\
+				{																		\
+					__ASSERT_STOP;														\
+				}																		\
+			}
+
+#define	AssertNotNULL(inPtr, inMessage)													\
+			{																			\
+				if((inPtr) == NULL)														\
+				{																		\
+					__ASSERT_STOP;														\
+				}																		\
+			}
+
+#define	FailIf(inCondition, inHandler, inMessage)										\
+			if(inCondition)																\
+			{																			\
+				STOP;																	\
+				goto inHandler;															\
+			}
+
+#define	FailWithAction(inCondition, inAction, inHandler, inMessage)						\
+			if(inCondition)																\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfNULL(inPointer, inAction, inHandler, inMessage)							\
+			if((inPointer) == NULL)														\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfKernelError(inKernelError, inAction, inHandler, inMessage)				\
+			if((inKernelError) != 0)													\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfError(inError, inAction, inHandler, inMessage)							\
+			if((inError) != 0)															\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfNoMessage(inCondition, inHandler, inMessage)								\
+			if(inCondition)																\
+			{																			\
+				STOP;																	\
+				goto inHandler;															\
+			}
+
+#define	FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage)			\
+			if(inCondition)																\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage)					\
+			if((inPointer) == NULL)														\
+			{																			\
+				STOP;																	\
+				{ inAction; }															\
+				goto inHandler;															\
+			}
+
+#define	FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage)		\
+			{																			\
+				unsigned int __Err = (inKernelError);									\
+				if(__Err != 0)															\
+				{																		\
+					STOP;																\
+					{ inAction; }														\
+					goto inHandler;														\
+				}																		\
+			}
+
+#define	FailIfErrorNoMessage(inError, inAction, inHandler, inMessage)					\
+			{																			\
+				SInt32 __Err = (inError);												\
+				if(__Err != 0)															\
+				{																		\
+					STOP;																\
+					{ inAction; }														\
+					goto inHandler;														\
+				}																		\
+			}
+
+#if defined(__cplusplus)
+
+#define Throw(inException)  __THROW_STOP; throw (inException)
+
+#define	ThrowIf(inCondition, inException, inMessage)									\
+			if(inCondition)																\
+			{																			\
+				Throw(inException);														\
+			}
+
+#define	ThrowIfNULL(inPointer, inException, inMessage)									\
+			if((inPointer) == NULL)														\
+			{																			\
+				Throw(inException);														\
+			}
+
+#define	ThrowIfKernelError(inKernelError, inException, inMessage)						\
+			{																			\
+				int __Err = (inKernelError);											\
+				if(__Err != 0)															\
+				{																		\
+					Throw(inException);													\
+				}																		\
+			}
+
+#define	ThrowIfError(inError, inException, inMessage)									\
+			{																			\
+				SInt32 __Err = (inError);												\
+				if(__Err != 0)															\
+				{																		\
+					Throw(inException);													\
+				}																		\
+			}
+
+#if TARGET_OS_WIN32
+#define	ThrowIfWinError(inError, inException, inMessage)								\
+			{																			\
+				HRESULT __Err = (inError);												\
+				if(FAILED(__Err))														\
+				{																		\
+					Throw(inException);													\
+				}																		\
+			}
+#endif
+
+#define	SubclassResponsibility(inMethodName, inException)								\
+			{																			\
+				Throw(inException);														\
+			}
+
+#endif	//	defined(__cplusplus)
+
+#endif  //  DEBUG || CoreAudio_Debug
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp
new file mode 100644
index 0000000..d691de3
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp
@@ -0,0 +1,89 @@
+/*
+     File: CADebugPrintf.cpp
+ Abstract: CADebugPrintf.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CADebugPrintf.h"
+
+#if	DEBUG || CoreAudio_Debug
+
+	#if	TARGET_OS_WIN32
+		#include <stdarg.h>
+		#include <stdio.h>
+		#include <Windows.h>
+		extern "C"
+		int	CAWin32DebugPrintf(char* inFormat, ...)
+		{
+			char theMessage[1024];
+			va_list theArguments;
+			va_start(theArguments, inFormat);
+			_vsnprintf(theMessage, 1024, inFormat, theArguments);
+			va_end(theArguments);
+			OutputDebugString(theMessage);
+			return 0;
+		}
+	#endif
+	
+	#if defined(CoreAudio_UseSideFile)
+		#include <unistd.h>
+		FILE* sDebugPrintfSideFile = NULL;
+		extern "C"
+		void OpenDebugPrintfSideFile()
+		{
+			if(sDebugPrintfSideFile == NULL)
+			{
+				char theFileName[1024];
+				snprintf(theFileName, sizeof(theFileName), CoreAudio_UseSideFile, getpid());
+				sDebugPrintfSideFile = fopen(theFileName, "a+");
+				DebugPrintfRtn(DebugPrintfFileComma "\n------------------------------\n");
+			}
+		}
+	#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h
new file mode 100644
index 0000000..79aa15d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h
@@ -0,0 +1,115 @@
+/*
+     File: CADebugPrintf.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CADebugPrintf_h__)
+#define __CADebugPrintf_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+//	Macros to redirect debugging output to various logging services
+//=============================================================================
+
+//#define	CoreAudio_UseSysLog		1
+//#define	CoreAudio_UseSideFile	"/CoreAudio-%d.txt"
+
+#if	DEBUG || CoreAudio_Debug
+	
+	#if	TARGET_OS_WIN32
+		#if defined(__cplusplus)
+		extern "C"
+		#endif
+		extern int CAWin32DebugPrintf(char* inFormat, ...);
+		#define	DebugPrintfRtn			CAWin32DebugPrintf
+		#define	DebugPrintfFile			
+		#define	DebugPrintfLineEnding	"\n"
+		#define	DebugPrintfFileComma
+	#else
+		#if	CoreAudio_UseSysLog
+			#include <sys/syslog.h>
+			#define	DebugPrintfRtn	syslog
+			#define	DebugPrintfFile	LOG_NOTICE
+			#define	DebugPrintfLineEnding	""
+			#define	DebugPrintfFileComma	DebugPrintfFile,
+		#elif defined(CoreAudio_UseSideFile)
+			#include <stdio.h>
+			#if defined(__cplusplus)
+			extern "C"
+			#endif
+			void OpenDebugPrintfSideFile();
+			extern FILE* sDebugPrintfSideFile;
+			#define	DebugPrintfRtn	fprintf
+			#define	DebugPrintfFile	((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr)
+			#define	DebugPrintfLineEnding	"\n"
+			#define	DebugPrintfFileComma	DebugPrintfFile,
+		#else
+			#include <stdio.h>
+			#define	DebugPrintfRtn	fprintf
+			#define	DebugPrintfFile	stderr
+			#define	DebugPrintfLineEnding	"\n"
+			#define	DebugPrintfFileComma	DebugPrintfFile,
+		#endif
+	#endif
+
+	#define	DebugPrintf(inFormat, ...)	DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
+#else
+	#define	DebugPrintfRtn	
+	#define	DebugPrintfFile	
+	#define	DebugPrintfLineEnding	
+	#define	DebugPrintfFileComma
+	#define	DebugPrintf(inFormat, ...)
+#endif
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp
new file mode 100644
index 0000000..7f0141d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp
@@ -0,0 +1,103 @@
+/*
+     File: CADebugger.cpp
+ Abstract: CADebugger.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CADebugger.h"
+
+//=============================================================================
+//	CADebugger
+//=============================================================================
+
+#if TARGET_API_MAC_OSX
+
+#include <sys/sysctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+bool CAIsDebuggerAttached(void)
+{
+	int					mib[4];
+	struct kinfo_proc	info;
+	size_t				size;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	mib[2] = KERN_PROC_PID;
+	mib[3] = getpid();
+	size = sizeof(info);
+	info.kp_proc.p_flag = 0;
+
+	sysctl(mib, 4, &info, &size, NULL, 0);
+
+	return (info.kp_proc.p_flag & P_TRACED) == P_TRACED;
+}
+
+#endif
+
+void	CADebuggerStop(void)
+{
+	#if	CoreAudio_Debug
+		#if	TARGET_API_MAC_OSX
+			if(CAIsDebuggerAttached())
+			{
+				#if defined(__i386__) || defined(__x86_64__)
+					asm("int3");
+				#else
+					__builtin_trap();
+				#endif
+			}
+			else
+			{
+				abort();
+			}
+		#else
+			__debugbreak();
+		#endif
+	#endif
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h
new file mode 100644
index 0000000..9391f01
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h
@@ -0,0 +1,69 @@
+/*
+     File: CADebugger.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CADebugger_h__)
+#define __CADebugger_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+//=============================================================================
+//	CADebugger
+//=============================================================================
+
+#if	TARGET_API_MAC_OSX
+	extern bool CAIsDebuggerAttached(void);
+#endif
+extern void	CADebuggerStop(void);
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAException.h b/libs/appleutility/CoreAudio/PublicUtility/CAException.h
new file mode 100644
index 0000000..7217001
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAException.h
@@ -0,0 +1,83 @@
+/*
+     File: CAException.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAException_h__)
+#define __CAException_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+//	CAException
+//=============================================================================
+
+class CAException
+{
+
+public:
+					CAException(OSStatus inError) : mError(inError) {}
+					CAException(const CAException& inException) : mError(inException.mError) {}
+	CAException&	operator=(const CAException& inException) { mError = inException.mError; return *this; }
+					~CAException() {}
+
+	OSStatus		GetError() const { return mError; }
+	
+protected:
+	OSStatus		mError;
+};
+
+#define	CATry								try{
+#define CACatch								} catch(...) {}
+#define	CASwallowException(inExpression)	try { inExpression; } catch(...) {}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h
new file mode 100644
index 0000000..f1aa56f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h
@@ -0,0 +1,300 @@
+/*
+     File: CAExtAudioFile.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAExtAudioFile_h__
+#define __CAExtAudioFile_h__
+
+#include <TargetConditionals.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioToolbox/ExtendedAudioFile.h>
+	#include <AudioToolbox/AudioConverter.h>
+#else
+	#include "ExtendedAudioFile.h"
+	#include "AudioConverter.h"
+#endif
+#include "CAXException.h"
+//#include "CAAutoDisposer.h"
+#include "CAStreamBasicDescription.h"
+#include "CAAudioChannelLayout.h"
+#include "CACFObject.h"
+
+// A C++ wrapper for ExtAudioFile
+// Error returns throw CAXExceptions.
+class CAExtAudioFile {
+public:
+	// instances are not automatically associated with open files.
+	CAExtAudioFile() :
+		mExtAudioFile(NULL) { }
+
+	virtual ~CAExtAudioFile()
+	{
+		Close();
+	}
+	
+	bool IsValid() const { return mExtAudioFile != NULL; }
+	
+	void	Open(const char* filename)
+	{
+		Close();
+		CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)filename, strlen(filename), false);
+		XThrowIf(!url, -1, "couldn't convert path to CFURLRef");
+		OSStatus res = ExtAudioFileOpenURL(url, &mExtAudioFile);
+		if (res)
+			CFRelease(url);
+		Check(res, "ExtAudioFileOpenURL");
+		CFRelease (url);
+	}
+	
+	// this group of methods maps directly to the API other than OSStatus results translating into exceptions.
+	// you must explicitly open, wrap or create a file.
+	void	OpenURL(CFURLRef url)
+	{
+		Close();
+		Check(ExtAudioFileOpenURL(url, &mExtAudioFile), "ExtAudioFileOpenURL");
+	}
+		
+	void	WrapAudioFileID(AudioFileID inFileID, Boolean forWriting)
+	{
+		Close();
+		Check(ExtAudioFileWrapAudioFileID(inFileID, forWriting, &mExtAudioFile), "ExtAudioFileWrapAudioFileID");
+	}
+
+	void	Create(const char *filePath, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags)
+	{
+		CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)filePath, strlen(filePath), false);
+		XThrowIf(!url, -1, "couldn't convert path to CFURLRef");
+		Close();
+		OSStatus res = ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile);
+		if (res)
+			CFRelease(url);
+		Check(res, "ExtAudioFileCreateWithURL");
+		CFRelease(url);
+	}
+	
+	void	CreateWithURL(CFURLRef url, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags)
+	{
+		Close();
+		Check(ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile), "ExtAudioFileCreateWithURL");
+	}
+
+	// you may explicitly close a file, or have it closed automatically by the destructor.
+	void	Close()
+	{
+		if (mExtAudioFile != NULL) {
+			Check(ExtAudioFileDispose(mExtAudioFile), "ExtAudioFileClose");
+			mExtAudioFile = NULL;
+		}
+	}
+	
+	void	Read(UInt32 &ioNumberFrames, AudioBufferList *ioData)
+	{
+		Check(ExtAudioFileRead(mExtAudioFile, &ioNumberFrames, ioData), "ExtAudioFileRead");
+	}
+	
+	OSStatus	Write(UInt32 inNumberFrames, const AudioBufferList *ioData)
+	{
+		OSStatus err = ExtAudioFileWrite(mExtAudioFile, inNumberFrames, ioData);
+		switch (err) {
+			// noErr and certain special errors are returned without an exception
+		case noErr:
+			break;
+	#if TARGET_OS_IPHONE
+		case kExtAudioFileError_CodecUnavailableInputConsumed:
+		case kExtAudioFileError_CodecUnavailableInputNotConsumed:
+			break;
+	#endif
+		default:
+			// throw an exception
+			Check(err, "ExtAudioFileWrite");
+			break;
+		}
+		return err;
+	}
+	
+	void	WriteAsync(UInt32 inNumberFrames, const AudioBufferList *ioData)
+	{
+		Check(ExtAudioFileWriteAsync(mExtAudioFile, inNumberFrames, ioData), "ExtAudioFileWriteAsync");
+	}
+	
+	void	Seek(SInt64 inFrameOffset)
+	{
+		Check(ExtAudioFileSeek(mExtAudioFile, inFrameOffset), "ExtAudioFileSeek");
+	}
+	
+	SInt64	Tell() const
+	{
+		SInt64 pos;
+		Check(ExtAudioFileTell(mExtAudioFile, &pos), "ExtAudioFileTell");
+		return pos;
+	}
+	
+	UInt32	GetPropertyInfo(ExtAudioFilePropertyID propid, Boolean *outWritable) const
+	{
+		UInt32 size;
+		CheckProperty(ExtAudioFileGetPropertyInfo(mExtAudioFile, propid, &size, outWritable), "ExtAudioFileGetPropertyInfo", propid);
+		return size;
+	}
+	
+	void	GetProperty(ExtAudioFilePropertyID propid, UInt32 &ioSize, void *outData) const
+	{
+		CheckProperty(ExtAudioFileGetProperty(mExtAudioFile, propid, &ioSize, outData), "ExtAudioFileGetProperty", propid);
+	}
+	
+	void	SetProperty(ExtAudioFilePropertyID propid, UInt32 size, const void *inData)
+	{
+		CheckProperty(ExtAudioFileSetProperty(mExtAudioFile, propid, size, inData), "ExtAudioFileSetProperty", propid);
+	}
+	
+	const CAAudioChannelLayout &GetFileChannelLayout()
+	{
+		return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout);
+	}
+
+	void	SetFileChannelLayout(const CAAudioChannelLayout &layout) {
+		SetProperty(kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout());
+	}
+
+	const CAStreamBasicDescription &GetFileDataFormat()
+	{
+		UInt32 size = sizeof(mFileDataFormat);
+		GetProperty(kExtAudioFileProperty_FileDataFormat, size, &mFileDataFormat);
+		return mFileDataFormat;
+	}
+	
+	const CAStreamBasicDescription &GetClientDataFormat() {
+		UInt32 size = sizeof(mClientDataFormat);
+		GetProperty(kExtAudioFileProperty_ClientDataFormat, size, &mClientDataFormat);
+		return mClientDataFormat;
+	}
+	
+
+	void	SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL, UInt32 codecManuf=0) {
+		if (codecManuf != 0)
+			SetProperty('cman' /*kExtAudioFileProperty_CodecManufacturer*/, sizeof(codecManuf), &codecManuf);
+		SetProperty(kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat);
+		if (layout)
+			SetClientChannelLayout(*layout);
+	}
+	
+	void	SetClientChannelLayout(const CAAudioChannelLayout &layout) {
+		SetProperty(kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout());
+	}
+	
+	AudioConverterRef				GetConverter() const {
+		UInt32 size = sizeof(AudioConverterRef);
+		AudioConverterRef converter = NULL;
+		GetProperty(kExtAudioFileProperty_AudioConverter, size, &converter);
+		return converter;
+	}
+
+	bool	HasConverter() const { return GetConverter() != NULL; }
+	
+	OSStatus	SetConverterProperty(AudioConverterPropertyID inPropertyID,	UInt32 inPropertyDataSize, const void *inPropertyData, bool inCanFail=false)
+	{
+		OSStatus err = AudioConverterSetProperty(GetConverter(), inPropertyID, inPropertyDataSize, inPropertyData);
+		if (!inCanFail)
+			XThrowIfError(err, "Couldn't set audio converter property");
+		if (!err) {
+			// must tell the file that we have changed the converter; a NULL converter config is sufficient
+			CFPropertyListRef config = NULL;
+			SetProperty(kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config);
+		}
+		return err;
+	}
+	
+	SInt64		GetNumberFrames() {
+		SInt64 length;
+		UInt32 size = sizeof(SInt64);
+		GetProperty(kExtAudioFileProperty_FileLengthFrames, size, &length);
+		return length;
+	}
+	
+
+protected:
+	virtual void Check(OSStatus err, const char *func) const
+	{
+		if (err) {
+			char txt[128];
+			snprintf(txt, sizeof(txt), "%s failed", func);
+			throw CAXException(txt, err);
+		}
+	}
+	
+	virtual void CheckProperty(OSStatus err, const char *func, UInt32 propid) const
+	{
+		if (err) {
+			char txt[128];
+			char propstr[] = CA4CCToCString(propid);
+			snprintf(txt, sizeof(txt), "%s ('%s') failed", func, propstr);
+			throw CAXException(txt, err);
+		}
+	}
+
+	const CAAudioChannelLayout &	FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) {
+		UInt32 size = GetPropertyInfo(propID, NULL);
+		CAAutoFree<AudioChannelLayout> layout;
+		layout.allocBytes(size);
+		GetProperty(propID, size, layout);
+		layoutObj = layout;
+		return layoutObj;
+	}
+
+private:
+	CAExtAudioFile(const CAExtAudioFile &) { }	// prohibit
+	CAExtAudioFile & operator = (const CAExtAudioFile &) { return *this; } // prohibit
+
+private:
+	ExtAudioFileRef				mExtAudioFile;
+	
+	// for convenience to the client, it helps if we hold onto some storage for these
+	CAStreamBasicDescription	mFileDataFormat;
+	CAAudioChannelLayout		mFileChannelLayout;
+	CAStreamBasicDescription	mClientDataFormat;
+};
+
+
+#endif // __CAExtAudioFile_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp
new file mode 100644
index 0000000..124cb21
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp
@@ -0,0 +1,188 @@
+/*
+     File: CAFilePathUtils.cpp
+ Abstract: CAFilePathUtils.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAFilePathUtils.h"
+#include <string.h>
+
+#if !CA_NO_CORE_SERVICES
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreServices/CoreServices.h> // FSRef
+    #include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreServices.h>
+	#include <CoreAudioTypes.h>
+#endif
+
+OSStatus	PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName)
+{
+	// convert C string to CFString
+#if !TARGET_OS_WIN32
+	CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
+#else
+	CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingWindowsLatin1);
+#endif
+	// convert CF string to URL
+	CFURLRef fullurl = CFURLCreateWithFileSystemPath(NULL, cfFullPath, TARGET_OS_WIN32 ? kCFURLWindowsPathStyle : kCFURLPOSIXPathStyle, false);
+	CFRelease(cfFullPath);
+	// get the directory portion of the URL
+	CFURLRef dirurl = CFURLCreateCopyDeletingLastPathComponent(NULL, fullurl);
+	// get the directory's FSRef
+	OSStatus err = CFURLGetFSRef(dirurl, &outParentDir) ? OSStatus(noErr) : OSStatus(kAudio_FileNotFoundError);
+	CFRelease(dirurl);
+	
+	CFStringRef lastPathComponent = CFURLCopyLastPathComponent(fullurl);
+	CFRelease(fullurl);
+	CFMutableStringRef filename = CFStringCreateMutableCopy(NULL, 0, lastPathComponent);
+	CFRelease(lastPathComponent);
+	// convert colons (legal in POSIX paths, illegal in File Manager) to slashes
+	CFStringFindAndReplace(filename, CFSTR(":"), CFSTR("/"), CFRangeMake(0, CFStringGetLength(filename)), 0);
+	
+	outFileName = filename;
+	
+	return err;
+}
+#endif // !CA_NO_CORE_SERVICES
+
+
+#if TARGET_OS_WIN32
+
+char*	dirname(const char* inPath)
+{
+	static char sAnswer[1024];
+	
+	char* theAnswer = NULL;
+	SInt32 thePathLength = strlen(inPath);
+	if(thePathLength < 1023)
+	{
+		//	make a working copy
+		strlcpy(sAnswer, inPath, sizeof(sAnswer));
+		
+		//	start at the end of the string
+		SInt32 theIndex = thePathLength - 1;
+		
+		//	walk back over the '\' characters
+		while((theIndex > 0) && (sAnswer[theIndex] == '\\'))
+		{
+			--theIndex;
+		}
+		
+		//	now keep walking back until we get to a '\'
+		while((theIndex > 0) && (sAnswer[theIndex] != '\\'))
+		{
+			--theIndex;
+		}
+		
+		//	where we are now is either the first character of the path or the '\' that marks the end of the directory name
+		if(theIndex > 0)
+		{
+			//	we have a name so put a '\0' in place of the '\'
+			sAnswer[theIndex] = 0;
+		}
+		else
+		{
+			//	no name, so the answer is "."
+			sAnswer[0] = '.';
+			sAnswer[1] = 0;
+		}
+		
+		//	set the return value
+		theAnswer = sAnswer;
+	}
+	
+	return theAnswer;
+}
+
+char*	basename(const char* inPath)
+{
+	static char sAnswer[1024];
+	
+	char* theAnswer = NULL;
+	SInt32 thePathLength = strlen(inPath);
+	if(thePathLength < 1023)
+	{
+		//	make a working copy
+		strlcpy(sAnswer, inPath, sizeof(sAnswer));
+		
+		//	start at the end of the string
+		SInt32 theLastIndex = thePathLength - 1;
+		
+		//	walk back over the '\' characters
+		while((theLastIndex > 0) && (sAnswer[theLastIndex] == '\\'))
+		{
+			--theLastIndex;
+		}
+		
+		//	check to see if we're at the beginning now
+		if(theLastIndex > 0)
+		{
+			//	there's a name in there now, so start where we are and go back to the next '\'
+			UInt32 theFirstIndex = theLastIndex;
+			while((theFirstIndex > 0) && (sAnswer[theFirstIndex] != '\\'))
+			{
+				--theFirstIndex;
+			}
+			
+			//	we now have a string, so put a '\0' after the last character
+			sAnswer[theLastIndex + 1] = 0;
+			
+			//	and set the return value
+			theAnswer = &sAnswer[theFirstIndex];
+		}
+		else
+		{
+			//	the path was entirely '\' characters, so the return value is "\"
+			sAnswer[0] = '\\';
+			sAnswer[1] = 0;
+		
+			//	set the return value
+			theAnswer = sAnswer;
+		}
+	}
+	
+	return theAnswer;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h
new file mode 100644
index 0000000..41f1ee0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h
@@ -0,0 +1,70 @@
+/*
+     File: CAFilePathUtils.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAFilePathUtils_h__
+#define __CAFilePathUtils_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CoreFoundation.h>
+    #include <CoreAudio/CoreAudio.h>
+#else
+	#include <TargetConditionals.h>
+	#include <CoreFoundation.h>
+    #include <CoreAudio.h>
+#endif
+
+struct FSRef;
+
+OSStatus	PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName);
+
+#if !TARGET_OS_WIN32
+	#include <libgen.h>
+#else
+	char*	dirname(const char* inPath);
+	char*	basename(const char* inPath);
+#endif
+
+#endif // __CAFilePathUtils_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp
new file mode 100644
index 0000000..a1c83be
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp
@@ -0,0 +1,343 @@
+/*
+     File: CAGuard.cpp
+ Abstract: CAGuard.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAGuard.h"
+
+#if TARGET_OS_MAC
+	#include <errno.h>
+#endif
+
+//	PublicUtility Inludes
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAHostTimeBase.h"
+
+//==================================================================================================
+//	Logging
+//==================================================================================================
+
+#if CoreAudio_Debug
+//	#define	Log_Ownership		1
+//	#define	Log_WaitOwnership	1
+//	#define	Log_TimedWaits		1
+//	#define Log_Latency			1
+//	#define	Log_Errors			1
+#endif
+
+//#warning		Need a try-based Locker too
+//==================================================================================================
+//	CAGuard
+//==================================================================================================
+
+CAGuard::CAGuard(const char* inName)
+:
+	CAMutex(inName)
+#if	Log_Average_Latency
+	,mAverageLatencyAccumulator(0.0),
+	mAverageLatencyCount(0)
+#endif
+{
+#if TARGET_OS_MAC
+	OSStatus theError = pthread_cond_init(&mCondVar, NULL);
+	ThrowIf(theError != 0, CAException(theError), "CAGuard::CAGuard: Could not init the cond var");
+#elif TARGET_OS_WIN32
+	mEvent = CreateEvent(NULL, true, false, NULL);
+	ThrowIfNULL(mEvent, CAException(GetLastError()), "CAGuard::CAGuard: Could not create the event");
+#endif
+}
+
+CAGuard::~CAGuard()
+{
+#if TARGET_OS_MAC
+	pthread_cond_destroy(&mCondVar);
+#elif TARGET_OS_WIN32
+	if(mEvent != NULL)
+	{
+		CloseHandle(mEvent);
+	}
+#endif
+}
+
+void	CAGuard::Wait()
+{
+#if TARGET_OS_MAC
+	ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
+
+	mOwner = 0;
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+	#endif
+
+	OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex);
+	ThrowIf(theError != 0, CAException(theError), "CAGuard::Wait: Could not wait for a signal");
+	mOwner = pthread_self();
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+	#endif
+#elif TARGET_OS_WIN32
+	ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
+
+	mOwner = 0;
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+	#endif
+
+	ReleaseMutex(mMutex);
+	HANDLE theHandles[] = { mMutex, mEvent };
+	OSStatus theError = WaitForMultipleObjects(2, theHandles, true, INFINITE);
+	ThrowIfError(theError, CAException(GetLastError()), "CAGuard::Wait: Could not wait for the signal");
+	mOwner = GetCurrentThreadId();
+	ResetEvent(mEvent);
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+	#endif
+#endif
+}
+
+bool	CAGuard::WaitFor(UInt64 inNanos)
+{
+	bool theAnswer = false;
+
+#if TARGET_OS_MAC
+	ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
+
+	#if	Log_TimedWaits
+		DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
+	#endif
+
+	struct timespec	theTimeSpec;
+	static const UInt64	kNanosPerSecond = 1000000000ULL;
+	if(inNanos >= kNanosPerSecond)
+	{
+		theTimeSpec.tv_sec = static_cast<long>(inNanos / kNanosPerSecond);
+		theTimeSpec.tv_nsec = static_cast<long>(inNanos % kNanosPerSecond);
+	}
+	else
+	{
+		theTimeSpec.tv_sec = 0;
+		theTimeSpec.tv_nsec = static_cast<long>(inNanos);
+	}
+	
+	#if	Log_TimedWaits || Log_Latency || Log_Average_Latency
+		UInt64	theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+	#endif
+
+	mOwner = 0;
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+	#endif
+
+	OSStatus theError = pthread_cond_timedwait_relative_np(&mCondVar, &mMutex, &theTimeSpec);
+	ThrowIf((theError != 0) && (theError != ETIMEDOUT), CAException(theError), "CAGuard::WaitFor: Wait got an error");
+	mOwner = pthread_self();
+	
+	#if	Log_TimedWaits || Log_Latency || Log_Average_Latency
+		UInt64	theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+	#endif
+	
+	#if	Log_TimedWaits
+		DebugMessageN1("CAGuard::WaitFor: waited  %.0f", (Float64)(theEndNanos - theStartNanos));
+	#endif
+	
+	#if	Log_Latency
+		DebugMessageN1("CAGuard::WaitFor: latency  %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
+	#endif
+	
+	#if	Log_Average_Latency
+		++mAverageLatencyCount;
+		mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
+		if(mAverageLatencyCount >= 50)
+		{
+			DebugMessageN2("CAGuard::WaitFor: average latency  %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
+			mAverageLatencyCount = 0;
+			mAverageLatencyAccumulator = 0.0;
+		}
+	#endif
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+	#endif
+
+	theAnswer = theError == ETIMEDOUT;
+#elif TARGET_OS_WIN32
+	ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
+
+	#if	Log_TimedWaits
+		DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
+	#endif
+
+	//	the time out is specified in milliseconds(!)
+	UInt32 theWaitTime = static_cast<UInt32>(inNanos / 1000000ULL);
+
+	#if	Log_TimedWaits || Log_Latency || Log_Average_Latency
+		UInt64	theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+	#endif
+
+	mOwner = 0;
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::WaitFor: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+	#endif
+	
+	ReleaseMutex(mMutex);
+	HANDLE theHandles[] = { mMutex, mEvent };
+	OSStatus theError = WaitForMultipleObjects(2, theHandles, true, theWaitTime);
+	ThrowIf((theError != WAIT_OBJECT_0) && (theError != WAIT_TIMEOUT), CAException(GetLastError()), "CAGuard::WaitFor: Wait got an error");
+	mOwner = GetCurrentThreadId();
+	ResetEvent(mEvent);
+	// This mutex should be locked again when time out happens.rdar://12270555
+	if(theError == WAIT_TIMEOUT) {
+		DWORD dwError = WaitForSingleObject(mMutex, INFINITE);
+		ThrowIf((dwError != WAIT_OBJECT_0), CAException(GetLastError()), "CAGuard::WaitFor: failed to acquire the mutex back when timeout happened\n");
+	}
+	#if	Log_TimedWaits || Log_Latency || Log_Average_Latency
+		UInt64	theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+	#endif
+	
+	#if	Log_TimedWaits
+		DebugMessageN1("CAGuard::WaitFor: waited  %.0f", (Float64)(theEndNanos - theStartNanos));
+	#endif
+	
+	#if	Log_Latency
+		DebugMessageN1("CAGuard::WaitFor: latency  %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
+	#endif
+	
+	#if	Log_Average_Latency
+		++mAverageLatencyCount;
+		mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
+		if(mAverageLatencyCount >= 50)
+		{
+			DebugMessageN2("CAGuard::WaitFor: average latency  %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
+			mAverageLatencyCount = 0;
+			mAverageLatencyAccumulator = 0.0;
+		}
+	#endif
+
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::WaitFor: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+	#endif
+
+	theAnswer = theError == WAIT_TIMEOUT;
+#endif
+
+	return theAnswer;
+}
+
+bool	CAGuard::WaitUntil(UInt64 inNanos)
+{
+	bool	theAnswer = false;
+	UInt64	theCurrentNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+	
+#if	Log_TimedWaits
+	DebugMessageN2("CAGuard::WaitUntil: now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
+#endif
+	
+	if(inNanos > theCurrentNanos)
+	{
+#if Log_Errors
+		if((inNanos - theCurrentNanos) > 1000000000ULL)
+		{
+			DebugMessage("CAGuard::WaitUntil: about to wait for more than a second");
+		}
+#endif
+		theAnswer = WaitFor(inNanos - theCurrentNanos);
+	}
+	else
+	{
+#if	Log_Errors
+		DebugMessageN2("CAGuard::WaitUntil: Time has expired before waiting, now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
+#endif
+		theAnswer = true;
+	}
+
+	return theAnswer;
+}
+
+void	CAGuard::Notify()
+{
+#if TARGET_OS_MAC
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Notify: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+	#endif
+
+	OSStatus theError = pthread_cond_signal(&mCondVar);
+	ThrowIf(theError != 0, CAException(theError), "CAGuard::Notify: failed");
+#elif TARGET_OS_WIN32
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Notify: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+	#endif
+	
+	SetEvent(mEvent);
+#endif
+}
+
+void	CAGuard::NotifyAll()
+{
+#if TARGET_OS_MAC
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::NotifyAll: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+	#endif
+
+	OSStatus theError = pthread_cond_broadcast(&mCondVar);
+	ThrowIf(theError != 0, CAException(theError), "CAGuard::NotifyAll: failed");
+#elif TARGET_OS_WIN32
+	#if	Log_WaitOwnership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::NotifyAll: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+	#endif
+	
+	SetEvent(mEvent);
+#endif
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h
new file mode 100644
index 0000000..ffcb59d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h
@@ -0,0 +1,133 @@
+/*
+     File: CAGuard.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAGuard_h__)
+#define __CAGuard_h__
+
+//==================================================================================================
+//	Includes
+//=============================================================================
+
+//	Super Class Includes
+#include "CAMutex.h"
+
+#if CoreAudio_Debug
+//	#define	Log_Average_Latency	1
+#endif
+
+//==================================================================================================
+//	CAGuard
+//
+//	This is your typical mutex with signalling implemented via pthreads.
+//	Lock() will return true if and only if the guard is locked on that call.
+//	A thread that already has the guard will receive 'false' if it locks it
+//	again. Use of the stack-based CAGuard::Locker class is highly recommended
+//	to properly manage the recursive nesting. The Wait calls with timeouts
+//	will return true if and only if the timeout period expired. They will
+//	return false if they receive notification any other way.
+//==================================================================================================
+
+class	CAGuard : public CAMutex
+{
+
+//	Construction/Destruction
+public:
+					CAGuard(const char* inName);
+	virtual			~CAGuard();
+
+//	Actions
+public:
+	virtual void	Wait();
+	virtual bool	WaitFor(UInt64 inNanos);
+	virtual bool	WaitUntil(UInt64 inNanos);
+	
+	virtual void	Notify();
+	virtual void	NotifyAll();
+
+//	Implementation
+protected:
+#if TARGET_OS_MAC
+	pthread_cond_t	mCondVar;
+#else
+	HANDLE			mEvent;
+#endif
+#if	Log_Average_Latency
+	Float64			mAverageLatencyAccumulator;
+	UInt32			mAverageLatencyCount;
+#endif
+	
+//	Helper class to manage taking and releasing recursively
+public:
+	class			Locker
+	{
+	
+	//	Construction/Destruction
+	public:
+					Locker(CAGuard& inGuard) : mGuard(inGuard), mNeedsRelease(false) { mNeedsRelease = mGuard.Lock(); }
+					~Locker() { if(mNeedsRelease) { mGuard.Unlock(); } }
+	
+	private:
+					Locker(const Locker&);
+		Locker&		operator=(const Locker&);
+	
+	//	Actions
+	public:
+		void		Wait() { mGuard.Wait(); }
+		bool		WaitFor(UInt64 inNanos) { return mGuard.WaitFor(inNanos); }
+		bool		WaitUntil(UInt64 inNanos) { return mGuard.WaitUntil(inNanos); }
+		
+		void		Notify() { mGuard.Notify(); }
+		void		NotifyAll() { mGuard.NotifyAll(); }
+
+	//	Implementation
+	private:
+		CAGuard&	mGuard;
+		bool		mNeedsRelease;	
+	};
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp
new file mode 100644
index 0000000..9bce346
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp
@@ -0,0 +1,1156 @@
+/*
+     File: CAHALAudioDevice.cpp
+ Abstract: CAHALAudioDevice.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAHALAudioDevice.h"
+
+//	PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CAHALAudioStream.h"
+#include "CAHALAudioSystemObject.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+//	CAHALAudioDevice
+//==================================================================================================
+
+CAHALAudioDevice::CAHALAudioDevice(AudioObjectID inAudioDevice)
+:
+	CAHALAudioObject(inAudioDevice)
+{
+}
+
+CAHALAudioDevice::CAHALAudioDevice(CFStringRef inUID)
+:
+	CAHALAudioObject(CAHALAudioSystemObject().GetAudioDeviceForUID(inUID))
+{
+}
+
+CAHALAudioDevice::~CAHALAudioDevice()
+{
+}
+
+CFStringRef	CAHALAudioDevice::CopyDeviceUID() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDeviceUID);
+	return GetPropertyData_CFString(theAddress, 0, NULL);
+}
+
+bool	CAHALAudioDevice::HasModelUID() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyModelUID);
+	return HasProperty(theAddress);
+}
+
+CFStringRef	CAHALAudioDevice::CopyModelUID() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyModelUID);
+	return GetPropertyData_CFString(theAddress, 0, NULL);
+}
+
+CFStringRef	CAHALAudioDevice::CopyConfigurationApplicationBundleID() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyConfigurationApplication);
+	return GetPropertyData_CFString(theAddress, 0, NULL);
+}
+
+CFURLRef	CAHALAudioDevice::CopyIconLocation() const
+{
+	CFURLRef theAnswer = NULL;
+	CAPropertyAddress theAddress(kAudioDevicePropertyIcon);
+	UInt32 theSize = sizeof(CFURLRef);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	return theAnswer;
+}
+
+UInt32	CAHALAudioDevice::GetTransportType() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyTransportType);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool	CAHALAudioDevice::CanBeDefaultDevice(bool inIsInput, bool inIsSystem) const
+{
+	CAPropertyAddress theAddress(inIsSystem ? kAudioDevicePropertyDeviceCanBeDefaultSystemDevice : kAudioDevicePropertyDeviceCanBeDefaultDevice, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	return GetPropertyData_UInt32(theAddress, 0, NULL) != 0;
+}
+
+bool	CAHALAudioDevice::HasDevicePlugInStatus() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlugIn);
+	return HasProperty(theAddress);
+}
+
+OSStatus	CAHALAudioDevice::GetDevicePlugInStatus() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlugIn);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool	CAHALAudioDevice::IsAlive() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsAlive);
+	return GetPropertyData_UInt32(theAddress, 0, NULL) != 0;
+}
+
+bool	CAHALAudioDevice::IsHidden() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyIsHidden);
+	return GetPropertyData_UInt32(theAddress, 0, NULL) != 0;
+}
+
+pid_t	CAHALAudioDevice::GetHogModeOwner() const
+{
+	pid_t theAnswer = -1;
+	CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = sizeof(pid_t);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	return theAnswer;
+}
+
+bool	CAHALAudioDevice::IsHogModeSettable() const
+{
+	bool theAnswer = false;
+	CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+	if(HasProperty(theAddress))
+	{
+		theAnswer = IsPropertySettable(theAddress);
+	}
+	return theAnswer;
+}
+
+bool	CAHALAudioDevice::TakeHogMode()
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+	pid_t thePID = getpid();
+	if(HasProperty(theAddress))
+	{
+		SetPropertyData(theAddress, 0, NULL, sizeof(pid_t), &thePID);
+	}
+	return thePID == getpid();
+}
+
+void	CAHALAudioDevice::ReleaseHogMode()
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+	if(HasProperty(theAddress))
+	{
+		pid_t thePID = -1;
+		SetPropertyData(theAddress, 0, NULL, sizeof(pid_t), &thePID);
+	}
+}
+
+bool	CAHALAudioDevice::HasPreferredStereoChannels(bool inIsInput) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	return HasProperty(theAddress);
+}
+
+void	CAHALAudioDevice::GetPreferredStereoChannels(bool inIsInput, UInt32& outLeft, UInt32& outRight) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	UInt32 theStereoPair[2] = { 0, 0 };
+	UInt32 theSize = 2 * sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, theStereoPair);
+	outLeft = theStereoPair[0];
+	outRight = theStereoPair[1];
+}
+
+void	CAHALAudioDevice::SetPreferredStereoChannels(bool inIsInput, UInt32 inLeft, UInt32 inRight)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	UInt32 theStereoPair[2] = { inLeft, inRight };
+	SetPropertyData(theAddress, 0, NULL, 2 * sizeof(UInt32), theStereoPair);
+}
+
+bool	CAHALAudioDevice::HasPreferredChannelLayout(bool inIsInput) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	return HasProperty(theAddress);
+}
+
+void	CAHALAudioDevice::GetPreferredChannelLayout(bool inIsInput, AudioChannelLayout& outChannelLayout) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	UInt32 theSize = (SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription)) + GetTotalNumberChannels(inIsInput) * SizeOf32(AudioChannelDescription);
+	GetPropertyData(theAddress, 0, NULL, theSize, &outChannelLayout);
+}
+
+void	CAHALAudioDevice::SetPreferredStereoChannels(bool inIsInput, AudioChannelLayout& inChannelLayout)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	UInt32 theSize = (SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription)) + GetTotalNumberChannels(inIsInput) * SizeOf32(AudioChannelDescription);
+	SetPropertyData(theAddress, 0, NULL, theSize, &inChannelLayout);
+}
+
+UInt32	CAHALAudioDevice::GetNumberRelatedAudioDevices() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyRelatedDevices);
+	UInt32 theAnswer = 0;
+	if(HasProperty(theAddress))
+	{
+		theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+		theAnswer /= SizeOf32(AudioObjectID);
+	}
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::GetRelatedAudioDevices(UInt32& ioNumberRelatedDevices, AudioObjectID* outRelatedDevices) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyRelatedDevices);
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = ioNumberRelatedDevices * SizeOf32(AudioObjectID);
+		GetPropertyData(theAddress, 0, NULL, theSize, outRelatedDevices);
+		ioNumberRelatedDevices = theSize / SizeOf32(AudioObjectID);
+	}
+	else
+	{
+		UInt32 theSize = ioNumberRelatedDevices * SizeOf32(AudioObjectID);
+		memset(outRelatedDevices, 0, theSize);
+		ioNumberRelatedDevices = 0;
+	}
+}
+
+AudioObjectID	CAHALAudioDevice::GetRelatedAudioDeviceByIndex(UInt32 inIndex) const
+{
+	AudioObjectID theAnswer = kAudioObjectUnknown;
+	UInt32 theNumberRelatedDevices = GetNumberRelatedAudioDevices();
+	if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices))
+	{
+		CAAutoArrayDelete<AudioObjectID> theRelatedDeviceList(theNumberRelatedDevices);
+		GetRelatedAudioDevices(theNumberRelatedDevices, theRelatedDeviceList);
+		if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices))
+		{
+			theAnswer = theRelatedDeviceList[inIndex];
+		}
+	}
+	return theAnswer;
+}
+
+UInt32	CAHALAudioDevice::GetNumberStreams(bool inIsInput) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+	theAnswer /= SizeOf32(AudioObjectID);
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::GetStreams(bool inIsInput, UInt32& ioNumberStreams, AudioObjectID* outStreamList) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	UInt32 theSize = ioNumberStreams * SizeOf32(AudioObjectID);
+	GetPropertyData(theAddress, 0, NULL, theSize, outStreamList);
+	ioNumberStreams = theSize / SizeOf32(AudioObjectID);
+}
+
+AudioObjectID	CAHALAudioDevice::GetStreamByIndex(bool inIsInput, UInt32 inIndex) const
+{
+	AudioObjectID theAnswer = kAudioObjectUnknown;
+	UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+	if((theNumberStreams > 0) && (inIndex < theNumberStreams))
+	{
+		CAAutoArrayDelete<AudioObjectID> theStreamList(theNumberStreams);
+		GetStreams(inIsInput, theNumberStreams, theStreamList);
+		if((theNumberStreams > 0) && (inIndex < theNumberStreams))
+		{
+			theAnswer = theStreamList[inIndex];
+		}
+	}
+	return theAnswer;
+}
+
+UInt32	CAHALAudioDevice::GetTotalNumberChannels(bool inIsInput) const
+{
+	UInt32 theAnswer = 0;
+	CAPropertyAddress theAddress(kAudioDevicePropertyStreamConfiguration, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+	CAAutoFree<AudioBufferList> theBufferList(theSize);
+	GetPropertyData(theAddress, 0, NULL, theSize, theBufferList);
+	for(UInt32 theIndex = 0; theIndex < theBufferList->mNumberBuffers; ++theIndex)
+	{
+		theAnswer += theBufferList->mBuffers[theIndex].mNumberChannels;
+	}
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::GetCurrentVirtualFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const
+{
+	ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput));
+	for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex)
+	{
+		CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex));
+		theStream.GetCurrentVirtualFormat(outFormats[theIndex]);
+	}
+}
+
+void	CAHALAudioDevice::GetCurrentPhysicalFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const
+{
+	ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput));
+	for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex)
+	{
+		CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex));
+		theStream.GetCurrentPhysicalFormat(outFormats[theIndex]);
+	}
+}
+
+bool	CAHALAudioDevice::IsRunning() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunning);
+	UInt32 theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL);
+	return theAnswer != 0;
+}
+
+bool	CAHALAudioDevice::IsRunningSomewhere() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunningSomewhere);
+	UInt32 theAnswer = 0;
+	if(HasProperty(theAddress))
+	{
+		theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL);
+	}
+	return theAnswer != 0;
+}
+
+UInt32	CAHALAudioDevice::GetLatency(bool inIsInput) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyLatency, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32	CAHALAudioDevice::GetSafetyOffset(bool inIsInput) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySafetyOffset, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool	CAHALAudioDevice::HasClockDomain() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain);
+	return HasProperty(theAddress);
+}
+
+UInt32	CAHALAudioDevice::GetClockDomain() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+Float64	CAHALAudioDevice::GetActualSampleRate() const
+{
+	Float64 theAnswer = 0;
+	CAPropertyAddress theAddress(kAudioDevicePropertyActualSampleRate);
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = sizeof(Float64);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	else
+	{
+		theAnswer = GetNominalSampleRate();
+	}
+	return theAnswer;
+}
+
+Float64	CAHALAudioDevice::GetNominalSampleRate() const
+{
+	Float64 theAnswer = 0;
+	CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate);
+	UInt32 theSize = sizeof(Float64);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::SetNominalSampleRate(Float64 inSampleRate)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate);
+	SetPropertyData(theAddress, 0, NULL, sizeof(Float64), &inSampleRate);
+}
+
+UInt32	CAHALAudioDevice::GetNumberAvailableNominalSampleRateRanges() const
+{
+	UInt32 theAnswer = 0;
+	CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates);
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+		theAnswer = theSize / SizeOf32(AudioValueRange);
+	}
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::GetAvailableNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates);
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = ioNumberRanges * SizeOf32(AudioValueRange);
+		GetPropertyData(theAddress, 0, NULL, theSize, outRanges);
+		ioNumberRanges = theSize / SizeOf32(AudioValueRange);
+	}
+	else
+	{
+		ioNumberRanges = 0;
+	}
+}
+
+void	CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const
+{
+	UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges();
+	ThrowIf(inIndex >= theNumberRanges, CAException(kAudioHardwareIllegalOperationError), "CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex: index out of range");
+	CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges);
+	GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges);
+	outMinimum = theRanges[inIndex].mMinimum;
+	outMaximum = theRanges[inIndex].mMaximum;
+}
+
+bool	CAHALAudioDevice::IsValidNominalSampleRate(Float64 inSampleRate) const
+{
+	bool theAnswer = false;
+	UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges();
+	CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges);
+	GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges);
+	for(UInt32 theIndex = 0; !theAnswer && (theIndex < theNumberRanges); ++theIndex)
+	{
+		theAnswer = (inSampleRate >= theRanges[theIndex].mMinimum) && (inSampleRate <= theRanges[theIndex].mMinimum);
+	}
+	return theAnswer;
+}
+
+bool	CAHALAudioDevice::IsIOBufferSizeSettable() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+	return IsPropertySettable(theAddress);
+}
+
+UInt32	CAHALAudioDevice::GetIOBufferSize() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+void	CAHALAudioDevice::SetIOBufferSize(UInt32 inBufferSize)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+	SetPropertyData(theAddress, 0, NULL, sizeof(UInt32), &inBufferSize);
+}
+
+bool	CAHALAudioDevice::UsesVariableIOBufferSizes() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes);
+	return HasProperty(theAddress);
+}
+
+UInt32	CAHALAudioDevice::GetMaximumVariableIOBufferSize() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool	CAHALAudioDevice::HasIOBufferSizeRange() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange);
+	return HasProperty(theAddress);
+}
+
+void	CAHALAudioDevice::GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const
+{
+	AudioValueRange theAnswer = { 0, 0 };
+	CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange);
+	UInt32 theSize = sizeof(AudioValueRange);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	outMinimum = static_cast<UInt32>(theAnswer.mMinimum);
+	outMaximum = static_cast<UInt32>(theAnswer.mMaximum);
+}
+
+AudioDeviceIOProcID	CAHALAudioDevice::CreateIOProcID(AudioDeviceIOProc inIOProc, void* inClientData)
+{
+	AudioDeviceIOProcID theAnswer = NULL;
+	OSStatus theError = AudioDeviceCreateIOProcID(mObjectID, inIOProc, inClientData, &theAnswer);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::CreateIOProcID: got an error creating the IOProc ID");
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::DestroyIOProcID(AudioDeviceIOProcID inIOProcID)
+{
+	OSStatus theError = AudioDeviceDestroyIOProcID(mObjectID, inIOProcID);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::DestroyIOProcID: got an error destroying the IOProc ID");
+}
+
+void	CAHALAudioDevice::StartIOProc(AudioDeviceIOProcID inIOProcID)
+{
+	OSStatus theError = AudioDeviceStart(mObjectID, inIOProcID);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProc: got an error starting an IOProc");
+}
+
+void	CAHALAudioDevice::StartIOProcAtTime(AudioDeviceIOProcID inIOProcID, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware)
+{
+	UInt32 theFlags = 0;
+	if(inIsInput)
+	{
+		theFlags |= kAudioDeviceStartTimeIsInputFlag;
+	}
+	if(inIgnoreHardware)
+	{
+		theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag;
+	}
+	
+	OSStatus theError = AudioDeviceStartAtTime(mObjectID, inIOProcID, &ioStartTime, theFlags);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProcAtTime: got an error starting an IOProc");
+}
+
+void	CAHALAudioDevice::StopIOProc(AudioDeviceIOProcID inIOProcID)
+{
+	OSStatus theError = AudioDeviceStop(mObjectID, inIOProcID);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StopIOProc: got an error stopping an IOProc");
+}
+
+void	CAHALAudioDevice::GetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, bool* outStreamUsage) const
+{
+	//	make an AudioHardwareIOProcStreamUsage the right size
+	UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+	UInt32 theSize = SizeOf32(void*) + SizeOf32(UInt32) + (theNumberStreams * SizeOf32(UInt32));
+	CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize);
+	
+	//	set it up
+	theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID);
+	theStreamUsage->mNumberStreams = theNumberStreams;
+	
+	//	get the property
+	CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	GetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage);
+	
+	//	fill out the return value
+	for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex)
+	{
+		outStreamUsage[theIndex] = (theStreamUsage->mStreamIsOn[theIndex] != 0);
+	}
+}
+
+void	CAHALAudioDevice::SetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, const bool* inStreamUsage)
+{
+	//	make an AudioHardwareIOProcStreamUsage the right size
+	UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+	UInt32 theSize = SizeOf32(void*) + SizeOf32(UInt32) + (theNumberStreams * SizeOf32(UInt32));
+	CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize);
+	
+	//	set it up
+	theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID);
+	theStreamUsage->mNumberStreams = theNumberStreams;
+	for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex)
+	{
+		theStreamUsage->mStreamIsOn[theIndex] = (inStreamUsage[theIndex] ? 1 : 0);
+	}
+	
+	//	set the property
+	CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+	SetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage);
+}
+
+Float32	CAHALAudioDevice::GetIOCycleUsage() const
+{
+	Float32 theAnswer = 0;
+	CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage);
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::SetIOCycleUsage(Float32 inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage);
+	SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void	CAHALAudioDevice::GetCurrentTime(AudioTimeStamp& outTime)
+{
+	OSStatus theError = AudioDeviceGetCurrentTime(mObjectID, &outTime);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetCurrentTime: got an error getting the current time");
+}
+
+void	CAHALAudioDevice::TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime)
+{
+	OSStatus theError = AudioDeviceTranslateTime(mObjectID, &inTime, &outTime);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::TranslateTime: got an error translating time");
+}
+
+void	CAHALAudioDevice::GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware)
+{
+	UInt32 theFlags = 0;
+	if(inIsInput)
+	{
+		theFlags |= kAudioDeviceStartTimeIsInputFlag;
+	}
+	if(inIgnoreHardware)
+	{
+		theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag;
+	}
+	
+	OSStatus theError = AudioDeviceGetNearestStartTime(mObjectID, &ioTime, theFlags);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetNearestStartTime: got an error getting the start time");
+}
+
+bool	CAHALAudioDevice::HasVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::VolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+Float32	CAHALAudioDevice::GetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+	Float32 theValue = 0.0f;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+Float32	CAHALAudioDevice::GetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel);
+	Float32 theValue = 0.0f;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+void	CAHALAudioDevice::SetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+	SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void	CAHALAudioDevice::SetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel);
+	SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+Float32	CAHALAudioDevice::GetVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibelsToScalar, inScope, inChannel);
+	Float32 theValue = inValue;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+Float32	CAHALAudioDevice::GetVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalarToDecibels, inScope, inChannel);
+	Float32 theValue = inValue;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+bool	CAHALAudioDevice::HasSubVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::SubVolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+Float32	CAHALAudioDevice::GetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+	Float32 theValue = 0.0f;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+Float32	CAHALAudioDevice::GetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel);
+	Float32 theValue = 0.0f;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+void	CAHALAudioDevice::SetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+	SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void	CAHALAudioDevice::SetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel);
+	SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+Float32	CAHALAudioDevice::GetSubVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibelsToScalar, inScope, inChannel);
+	Float32 theValue = inValue;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+Float32	CAHALAudioDevice::GetSubVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalarToDecibels, inScope, inChannel);
+	Float32 theValue = inValue;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+bool	CAHALAudioDevice::HasMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::MuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+bool	CAHALAudioDevice::GetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+	UInt32 theValue = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue != 0;
+}
+
+void	CAHALAudioDevice::SetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+	UInt32 theValue = (inValue ? 1 : 0);
+	UInt32 theSize = sizeof(UInt32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool	CAHALAudioDevice::HasSoloControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::SoloControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+bool	CAHALAudioDevice::GetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+	UInt32 theValue = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue != 0;
+}
+
+void	CAHALAudioDevice::SetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+	UInt32 theValue = (inValue ? 1 : 0);
+	UInt32 theSize = sizeof(UInt32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool	CAHALAudioDevice::HasStereoPanControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::StereoPanControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+Float32	CAHALAudioDevice::GetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+	Float32 theValue = 0.0f;
+	UInt32 theSize = sizeof(Float32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue;
+}
+
+void	CAHALAudioDevice::SetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+	UInt32 theSize = sizeof(Float32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &inValue);
+}
+
+void	CAHALAudioDevice::GetStereoPanControlChannels(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& outLeftChannel, UInt32& outRightChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyStereoPanChannels, inScope, inChannel);
+	UInt32 theValue[2] = { 0, 0 };
+	UInt32 theSize = 2 * sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, theValue);
+	outLeftChannel = theValue[0];
+	outRightChannel = theValue[1];
+}
+
+bool	CAHALAudioDevice::HasJackControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyJackIsConnected, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::GetJackControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyJackIsConnected, inScope, inChannel);
+	UInt32 theValue = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue != 0;
+}
+
+bool	CAHALAudioDevice::HasSubMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::SubMuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+bool	CAHALAudioDevice::GetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+	UInt32 theValue = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue != 0;
+}
+
+void	CAHALAudioDevice::SetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+	UInt32 theValue = (inValue ? 1 : 0);
+	UInt32 theSize = sizeof(UInt32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool	CAHALAudioDevice::HasiSubOwnerControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::iSubOwnerControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+bool	CAHALAudioDevice::GetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+	UInt32 theValue = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theValue != 0;
+}
+
+void	CAHALAudioDevice::SetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+	UInt32 theValue = (inValue ? 1 : 0);
+	UInt32 theSize = sizeof(UInt32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool	CAHALAudioDevice::HasDataSourceControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::DataSourceControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+UInt32	CAHALAudioDevice::GetCurrentDataSourceID(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+	UInt32 theAnswer = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::SetCurrentDataSourceByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+	UInt32 theSize = sizeof(UInt32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32	CAHALAudioDevice::GetNumberAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDataSources, inScope, inChannel);
+	UInt32 theAnswer = 0;
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+		theAnswer = theSize / SizeOf32(UInt32);
+	}
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::GetAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberSources, UInt32* outSources) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDataSources, inScope, inChannel);
+	UInt32 theNumberSources = std::min(GetNumberAvailableDataSources(inScope, inChannel), ioNumberSources);
+	UInt32 theSize = theNumberSources * SizeOf32(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, outSources);
+	ioNumberSources = theSize / SizeOf32(UInt32);
+}
+
+UInt32	CAHALAudioDevice::GetAvailableDataSourceByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const
+{
+	AudioStreamID theAnswer = 0;
+	UInt32 theNumberSources = GetNumberAvailableDataSources(inScope, inChannel);
+	if((theNumberSources > 0) && (inIndex < theNumberSources))
+	{
+		CAAutoArrayDelete<UInt32> theSourceList(theNumberSources);
+		GetAvailableDataSources(inScope, inChannel, theNumberSources, theSourceList);
+		theAnswer = theSourceList[inIndex];
+	}
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioDevice::CopyDataSourceNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyDataSourceNameForIDCFString, inScope, inChannel);
+	CFStringRef theAnswer = NULL;
+	AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+	UInt32 theSize = sizeof(AudioValueTranslation);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+	return theAnswer;
+}
+
+bool	CAHALAudioDevice::HasDataDestinationControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::DataDestinationControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+	return IsPropertySettable(theAddress);
+}
+
+UInt32	CAHALAudioDevice::GetCurrentDataDestinationID(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+	UInt32 theAnswer = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::SetCurrentDataDestinationByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+	UInt32 theSize = sizeof(UInt32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32	CAHALAudioDevice::GetNumberAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinations, inScope, inChannel);
+	UInt32 theAnswer = 0;
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+		theAnswer = theSize / SizeOf32(UInt32);
+	}
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::GetAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberDestinations, UInt32* outDestinations) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinations, inScope, inChannel);
+	UInt32 theNumberDestinations = std::min(GetNumberAvailableDataDestinations(inScope, inChannel), ioNumberDestinations);
+	UInt32 theSize = theNumberDestinations * SizeOf32(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, outDestinations);
+	ioNumberDestinations = theSize / SizeOf32(UInt32);
+}
+
+UInt32	CAHALAudioDevice::GetAvailableDataDestinationByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const
+{
+	AudioStreamID theAnswer = 0;
+	UInt32 theNumberDestinations = GetNumberAvailableDataDestinations(inScope, inChannel);
+	if((theNumberDestinations > 0) && (inIndex < theNumberDestinations))
+	{
+		CAAutoArrayDelete<UInt32> theDestinationList(theNumberDestinations);
+		GetAvailableDataDestinations(inScope, inChannel, theNumberDestinations, theDestinationList);
+		theAnswer = theDestinationList[inIndex];
+	}
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioDevice::CopyDataDestinationNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinationNameForIDCFString, inScope, inChannel);
+	CFStringRef theAnswer = NULL;
+	AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+	UInt32 theSize = sizeof(AudioValueTranslation);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+	return theAnswer;
+}
+
+bool	CAHALAudioDevice::HasClockSourceControl() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+	return HasProperty(theAddress);
+}
+
+bool	CAHALAudioDevice::ClockSourceControlIsSettable() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+	return IsPropertySettable(theAddress);
+}
+
+UInt32	CAHALAudioDevice::GetCurrentClockSourceID() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+	UInt32 theAnswer = 0;
+	UInt32 theSize = sizeof(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::SetCurrentClockSourceByID(UInt32 inID)
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+	UInt32 theSize = sizeof(UInt32);
+	SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32	CAHALAudioDevice::GetNumberAvailableClockSources() const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSources);
+	UInt32 theAnswer = 0;
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+		theAnswer = theSize / SizeOf32(UInt32);
+	}
+	return theAnswer;
+}
+
+void	CAHALAudioDevice::GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSources);
+	UInt32 theNumberSources = std::min(GetNumberAvailableClockSources(), ioNumberSources);
+	UInt32 theSize = theNumberSources * SizeOf32(UInt32);
+	GetPropertyData(theAddress, 0, NULL, theSize, outSources);
+	ioNumberSources = theSize / SizeOf32(UInt32);
+}
+
+UInt32	CAHALAudioDevice::GetAvailableClockSourceByIndex(UInt32 inIndex) const
+{
+	AudioStreamID theAnswer = 0;
+	UInt32 theNumberSources = GetNumberAvailableClockSources();
+	if((theNumberSources > 0) && (inIndex < theNumberSources))
+	{
+		CAAutoArrayDelete<UInt32> theSourceList(theNumberSources);
+		GetAvailableClockSources(theNumberSources, theSourceList);
+		theAnswer = theSourceList[inIndex];
+	}
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioDevice::CopyClockSourceNameForID(UInt32 inID) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceNameForIDCFString);
+	CFStringRef theAnswer = NULL;
+	AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+	UInt32 theSize = sizeof(AudioValueTranslation);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+	return theAnswer;
+}
+
+UInt32	CAHALAudioDevice::GetClockSourceKindForID(UInt32 inID) const
+{
+	CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceKindForID);
+	UInt32 theAnswer = 0;
+	AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(UInt32) };
+	UInt32 theSize = sizeof(AudioValueTranslation);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+	return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h
new file mode 100644
index 0000000..8cfb466
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h
@@ -0,0 +1,238 @@
+/*
+     File: CAHALAudioDevice.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAHALAudioDevice_h__)
+#define __CAHALAudioDevice_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Super Class Includes
+#include "CAHALAudioObject.h"
+
+//	PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//==================================================================================================
+//	CAHALAudioDevice
+//==================================================================================================
+
+class CAHALAudioDevice
+:
+	public	CAHALAudioObject
+{
+
+//	Construction/Destruction
+public:
+						CAHALAudioDevice(AudioObjectID inAudioDevice);
+						CAHALAudioDevice(CFStringRef inUID);
+	virtual				~CAHALAudioDevice();
+
+//	General Stuff
+public:
+	CFStringRef			CopyDeviceUID() const;
+	bool				HasModelUID() const;
+	CFStringRef			CopyModelUID() const;
+	CFStringRef			CopyConfigurationApplicationBundleID() const;
+	CFURLRef			CopyIconLocation() const;
+	UInt32				GetTransportType() const;
+	bool				CanBeDefaultDevice(bool inIsInput, bool inIsSystem) const;
+	bool				HasDevicePlugInStatus() const;
+	OSStatus			GetDevicePlugInStatus() const;
+	bool				IsAlive() const;
+	bool				IsHidden() const;
+	pid_t				GetHogModeOwner() const;
+	bool				IsHogModeSettable() const;
+	bool				TakeHogMode();
+	void				ReleaseHogMode();
+	bool				HasPreferredStereoChannels(bool inIsInput) const;
+	void				GetPreferredStereoChannels(bool inIsInput, UInt32& outLeft, UInt32& outRight) const;
+	void				SetPreferredStereoChannels(bool inIsInput, UInt32 inLeft, UInt32 inRight);
+	bool				HasPreferredChannelLayout(bool inIsInput) const;
+	void				GetPreferredChannelLayout(bool inIsInput, AudioChannelLayout& outChannelLayout) const;
+	void				SetPreferredStereoChannels(bool inIsInput, AudioChannelLayout& inChannelLayout);
+	UInt32				GetNumberRelatedAudioDevices() const;
+	void				GetRelatedAudioDevices(UInt32& ioNumberRelatedDevices, AudioObjectID* outRelatedDevices) const;
+	AudioObjectID		GetRelatedAudioDeviceByIndex(UInt32 inIndex) const;
+
+//	Stream Stuff
+public:
+	UInt32				GetNumberStreams(bool inIsInput) const;
+	void				GetStreams(bool inIsInput, UInt32& ioNumberStreams, AudioObjectID* outStreamList) const;
+	AudioObjectID		GetStreamByIndex(bool inIsInput, UInt32 inIndex) const;
+	UInt32				GetTotalNumberChannels(bool inIsInput) const;
+	void				GetCurrentVirtualFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const;
+	void				GetCurrentPhysicalFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const;
+	
+//	IO Stuff
+public:
+	bool				IsRunning() const;
+	bool				IsRunningSomewhere() const;
+	UInt32				GetLatency(bool inIsInput) const;
+	UInt32				GetSafetyOffset(bool inIsInput) const;
+	bool				HasClockDomain() const;
+	UInt32				GetClockDomain() const;
+	Float64				GetActualSampleRate() const;
+	Float64				GetNominalSampleRate() const;
+	void				SetNominalSampleRate(Float64 inSampleRate);
+	UInt32				GetNumberAvailableNominalSampleRateRanges() const;
+	void				GetAvailableNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const;
+	void				GetAvailableNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const;
+	bool				IsValidNominalSampleRate(Float64 inSampleRate) const;
+	bool				IsIOBufferSizeSettable() const;
+	UInt32				GetIOBufferSize() const;
+	void				SetIOBufferSize(UInt32 inBufferSize);
+	bool				UsesVariableIOBufferSizes() const;
+	UInt32				GetMaximumVariableIOBufferSize() const;
+	bool				HasIOBufferSizeRange() const;
+	void				GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const;
+	AudioDeviceIOProcID	CreateIOProcID(AudioDeviceIOProc inIOProc, void* inClientData);
+	AudioDeviceIOProcID	CreateIOProcIDWithBlock(dispatch_queue_t inDispatchQueue, AudioDeviceIOBlock inIOBlock);
+	void				DestroyIOProcID(AudioDeviceIOProcID inIOProcID);
+	void				StartIOProc(AudioDeviceIOProcID inIOProcID);
+	void				StartIOProcAtTime(AudioDeviceIOProcID inIOProcID, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware);
+	void				StopIOProc(AudioDeviceIOProcID inIOProcID);
+	void				GetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, bool* outStreamUsage) const;
+	void				SetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, const bool* inStreamUsage);
+	Float32				GetIOCycleUsage() const;
+	void				SetIOCycleUsage(Float32 inValue);
+	
+//	Time Operations
+public:
+	void				GetCurrentTime(AudioTimeStamp& outTime);
+	void				TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime);
+	void				GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware);
+
+//	Controls
+public:
+	bool				HasVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				VolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	Float32				GetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	Float32				GetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+	void				SetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+	Float32				GetVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+	Float32				GetVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+	
+	bool				HasSubVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				SubVolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	Float32				GetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	Float32				GetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+	void				SetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+	Float32				GetSubVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+	Float32				GetSubVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+	
+	bool				HasMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				MuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				GetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+	
+	bool				HasSoloControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				SoloControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				GetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+	
+	bool				HasStereoPanControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				StereoPanControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	Float32				GetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+	void				GetStereoPanControlChannels(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& outLeftChannel, UInt32& outRightChannel) const;
+	
+	bool				HasJackControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				GetJackControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	
+	bool				HasSubMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				SubMuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				GetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+	
+	bool				HasiSubOwnerControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				iSubOwnerControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				GetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+
+	bool				HasDataSourceControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				DataSourceControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	UInt32				GetCurrentDataSourceID(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetCurrentDataSourceByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID);
+	UInt32				GetNumberAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				GetAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberSources, UInt32* outSources) const;
+	UInt32				GetAvailableDataSourceByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const;
+	CFStringRef			CopyDataSourceNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const;
+
+	bool				HasDataDestinationControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	bool				DataDestinationControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	UInt32				GetCurrentDataDestinationID(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				SetCurrentDataDestinationByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID);
+	UInt32				GetNumberAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+	void				GetAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberDestinations, UInt32* outDestinations) const;
+	UInt32				GetAvailableDataDestinationByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const;
+	CFStringRef			CopyDataDestinationNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const;
+
+	bool				HasClockSourceControl() const;
+	bool				ClockSourceControlIsSettable() const;
+	UInt32				GetCurrentClockSourceID() const;
+	void				SetCurrentClockSourceByID(UInt32 inID);
+	UInt32				GetNumberAvailableClockSources() const;
+	void				GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const;
+	UInt32				GetAvailableClockSourceByIndex(UInt32 inIndex) const;
+	CFStringRef			CopyClockSourceNameForID(UInt32 inID) const;
+	UInt32				GetClockSourceKindForID(UInt32 inID) const;
+	
+};
+
+inline AudioDeviceIOProcID	CAHALAudioDevice::CreateIOProcIDWithBlock(dispatch_queue_t inDispatchQueue, AudioDeviceIOBlock inIOBlock)
+{
+	AudioDeviceIOProcID theAnswer = NULL;
+	OSStatus theError = AudioDeviceCreateIOProcIDWithBlock(&theAnswer, mObjectID, inDispatchQueue, inIOBlock);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::CreateIOProcIDWithBlock: got an error creating the IOProc ID");
+	return theAnswer;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp
new file mode 100644
index 0000000..c8f16b4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp
@@ -0,0 +1,370 @@
+/*
+     File: CAHALAudioObject.cpp
+ Abstract: CAHALAudioObject.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAHALAudioObject.h"
+
+//	PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+//	CAHALAudioObject
+//==================================================================================================
+
+CAHALAudioObject::CAHALAudioObject(AudioObjectID inObjectID)
+:
+	mObjectID(inObjectID)
+{
+}
+
+CAHALAudioObject::~CAHALAudioObject()
+{
+}
+
+AudioObjectID	CAHALAudioObject::GetObjectID() const
+{
+	return mObjectID;
+}
+
+void	CAHALAudioObject::SetObjectID(AudioObjectID inObjectID)
+{
+	mObjectID = inObjectID;
+}
+
+AudioClassID	CAHALAudioObject::GetClassID() const
+{
+	//	set up the return value
+	AudioClassID theAnswer = 0;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyClass);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		UInt32 theSize = sizeof(AudioClassID);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+AudioObjectID	CAHALAudioObject::GetOwnerObjectID() const
+{
+	//	set up the return value
+	AudioObjectID theAnswer = 0;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyOwner);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		//	get the property data
+		UInt32 theSize = sizeof(AudioObjectID);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioObject::CopyOwningPlugInBundleID() const
+{
+	//	set up the return value
+	CFStringRef theAnswer = NULL;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyCreator);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		//	get the property data
+		UInt32 theSize = sizeof(CFStringRef);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioObject::CopyName() const
+{
+	//	set up the return value
+	CFStringRef theAnswer = NULL;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyName);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		//	get the property data
+		UInt32 theSize = sizeof(CFStringRef);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioObject::CopyManufacturer() const
+{
+	//	set up the return value
+	CFStringRef theAnswer = NULL;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyManufacturer);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		//	get the property data
+		UInt32 theSize = sizeof(CFStringRef);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioObject::CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
+{
+	//	set up the return value
+	CFStringRef theAnswer = NULL;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyElementName, inScope, inElement);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		//	get the property data
+		UInt32 theSize = sizeof(CFStringRef);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioObject::CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
+{
+	//	set up the return value
+	CFStringRef theAnswer = NULL;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyElementCategoryName, inScope, inElement);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		//	get the property data
+		UInt32 theSize = sizeof(CFStringRef);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+CFStringRef	CAHALAudioObject::CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
+{
+	//	set up the return value
+	CFStringRef theAnswer = NULL;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyElementNumberName, inScope, inElement);
+	
+	//	make sure the property exists
+	if(HasProperty(theAddress))
+	{
+		//	get the property data
+		UInt32 theSize = sizeof(CFStringRef);
+		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+bool	CAHALAudioObject::ObjectExists(AudioObjectID inObjectID)
+{
+	Boolean isSettable;
+	CAPropertyAddress theAddress(kAudioObjectPropertyClass);
+	return (inObjectID == 0) || (AudioObjectIsPropertySettable(inObjectID, &theAddress, &isSettable) != 0);
+}
+
+UInt32	CAHALAudioObject::GetNumberOwnedObjects(AudioClassID inClass) const
+{
+	//	set up the return value
+	UInt32 theAnswer = 0;
+	
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
+	
+	//	figure out the qualifier
+	UInt32 theQualifierSize = 0;
+	void* theQualifierData = NULL;
+	if(inClass != 0)
+	{
+		theQualifierSize = sizeof(AudioObjectID);
+		theQualifierData = &inClass;
+	}
+	
+	//	get the property data size
+	theAnswer = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData);
+	
+	//	calculate the number of object IDs
+	theAnswer /= SizeOf32(AudioObjectID);
+	
+	return theAnswer;
+}
+
+void	CAHALAudioObject::GetAllOwnedObjects(AudioClassID inClass, UInt32& ioNumberObjects, AudioObjectID* ioObjectIDs) const
+{
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
+	
+	//	figure out the qualifier
+	UInt32 theQualifierSize = 0;
+	void* theQualifierData = NULL;
+	if(inClass != 0)
+	{
+		theQualifierSize = sizeof(AudioObjectID);
+		theQualifierData = &inClass;
+	}
+	
+	//	get the property data
+	UInt32 theDataSize = ioNumberObjects * SizeOf32(AudioClassID);
+	GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, ioObjectIDs);
+	
+	//	set the number of object IDs being returned
+	ioNumberObjects = theDataSize / SizeOf32(AudioObjectID);
+}
+
+AudioObjectID	CAHALAudioObject::GetOwnedObjectByIndex(AudioClassID inClass, UInt32 inIndex)
+{
+	//	set up the property address
+	CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
+	
+	//	figure out the qualifier
+	UInt32 theQualifierSize = 0;
+	void* theQualifierData = NULL;
+	if(inClass != 0)
+	{
+		theQualifierSize = sizeof(AudioObjectID);
+		theQualifierData = &inClass;
+	}
+	
+	//	figure out how much space to allocate
+	UInt32 theDataSize = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData);
+	UInt32 theNumberObjectIDs = theDataSize / SizeOf32(AudioObjectID);
+	
+	//	set up the return value
+	AudioObjectID theAnswer = 0;
+	
+	//	maker sure the index is in range
+	if(inIndex < theNumberObjectIDs)
+	{
+		//	allocate it
+		CAAutoArrayDelete<AudioObjectID> theObjectList(theDataSize / sizeof(AudioObjectID));
+		
+		//	get the property data
+		GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, theObjectList);
+		
+		//	get the return value
+		theAnswer = theObjectList[inIndex];
+	}
+	
+	return theAnswer;
+}
+
+bool	CAHALAudioObject::HasProperty(const AudioObjectPropertyAddress& inAddress) const
+{
+	return AudioObjectHasProperty(mObjectID, &inAddress);
+}
+
+bool	CAHALAudioObject::IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const
+{
+	Boolean isSettable = false;
+	OSStatus theError = AudioObjectIsPropertySettable(mObjectID, &inAddress, &isSettable);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::IsPropertySettable: got an error getting info about a property");
+	return isSettable != 0;
+}
+
+UInt32	CAHALAudioObject::GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const
+{
+	UInt32 theDataSize = 0;
+	OSStatus theError = AudioObjectGetPropertyDataSize(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &theDataSize);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyDataSize: got an error getting the property data size");
+	return theDataSize;
+}
+
+void	CAHALAudioObject::GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const
+{
+	OSStatus theError = AudioObjectGetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &ioDataSize, outData);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyData: got an error getting the property data");
+}
+
+void	CAHALAudioObject::SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData)
+{
+	OSStatus theError = AudioObjectSetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::SetPropertyData: got an error setting the property data");
+}
+
+void	CAHALAudioObject::AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
+{
+	OSStatus theError = AudioObjectAddPropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListener: got an error adding a property listener");
+}
+
+void	CAHALAudioObject::RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
+{
+	OSStatus theError = AudioObjectRemovePropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener");
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h
new file mode 100644
index 0000000..d99ab0d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h
@@ -0,0 +1,155 @@
+/*
+     File: CAHALAudioObject.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAHALAudioObject_h__)
+#define __CAHALAudioObject_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudio.h>
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include <CoreAudio.h>
+	#include <CoreFoundation.h>
+#endif
+
+//==================================================================================================
+//	CAHALAudioObject
+//==================================================================================================
+
+class CAHALAudioObject
+{
+
+//	Construction/Destruction
+public:
+								CAHALAudioObject(AudioObjectID inObjectID);
+	virtual						~CAHALAudioObject();
+
+//	Attributes
+public:
+	AudioObjectID				GetObjectID() const;
+	void						SetObjectID(AudioObjectID inObjectID);
+	AudioClassID				GetClassID() const;
+	AudioObjectID				GetOwnerObjectID() const;
+	CFStringRef					CopyOwningPlugInBundleID() const;
+	CFStringRef					CopyName() const;
+	CFStringRef					CopyManufacturer() const;
+	CFStringRef					CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+	CFStringRef					CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+	CFStringRef					CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+	
+	static bool					ObjectExists(AudioObjectID inObjectID);
+
+//	Owned Objects
+public:
+	UInt32						GetNumberOwnedObjects(AudioClassID inClass) const;
+	void						GetAllOwnedObjects(AudioClassID inClass, UInt32& ioNumberObjects, AudioObjectID* ioObjectIDs) const;
+	AudioObjectID				GetOwnedObjectByIndex(AudioClassID inClass, UInt32 inIndex);
+	
+//	Property Operations
+public:
+	bool						HasProperty(const AudioObjectPropertyAddress& inAddress) const;
+	bool						IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const;
+	UInt32						GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const;
+	
+	void						GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const;
+	void						SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData);
+	
+	UInt32						GetPropertyData_UInt32(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const										{ UInt32 theAnswer = 0; UInt32 theDataSize = SizeOf32(UInt32); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+	void						SetPropertyData_UInt32(const AudioObjectPropertyAddress& inAddress, UInt32 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL)								{ SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(UInt32), &inValue); }
+
+	Float32						GetPropertyData_Float32(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const										{ Float32 theAnswer = 0; UInt32 theDataSize = SizeOf32(Float32); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+	void						SetPropertyData_Float32(const AudioObjectPropertyAddress& inAddress, Float32 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL)							{ SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(Float32), &inValue); }
+
+	Float64						GetPropertyData_Float64(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const										{ Float64 theAnswer = 0; UInt32 theDataSize = SizeOf32(Float64); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+	void						SetPropertyData_Float64(const AudioObjectPropertyAddress& inAddress, Float64 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL)							{ SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(Float64), &inValue); }
+
+	CFTypeRef					GetPropertyData_CFType(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const										{ CFTypeRef theAnswer = NULL; UInt32 theDataSize = SizeOf32(CFTypeRef); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+	void						SetPropertyData_CFType(const AudioObjectPropertyAddress& inAddress, CFTypeRef inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL)								{ SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(CFTypeRef), &inValue); }
+
+	CFStringRef					GetPropertyData_CFString(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const										{ CFStringRef theAnswer = NULL; UInt32 theDataSize = SizeOf32(CFStringRef); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+	void						SetPropertyData_CFString(const AudioObjectPropertyAddress& inAddress, CFStringRef inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL)							{ SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(CFStringRef), &inValue); }
+
+	template <class T> void		GetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& outStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const							{ UInt32 theDataSize = SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &outStruct); }
+	template <class T> void		SetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& inStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL)								{ SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(T), &inStruct); }
+
+	template <class T> UInt32	GetPropertyData_ArraySize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const									{ return GetPropertyDataSize(inAddress, inQualifierDataSize, inQualifierData) / SizeOf32(T); }
+	template <class T> void		GetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32& ioNumberItems, T* outArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const	{ UInt32 theDataSize = ioNumberItems * SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, outArray); ioNumberItems = theDataSize / SizeOf32(T); }
+	template <class T> void		SetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32 inNumberItems, T* inArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL)			{ SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, inNumberItems * SizeOf32(T), inArray); }
+	
+	void						AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData);
+	void						RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData);
+
+	void						AddPropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock);
+	void						RemovePropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock);
+
+//	Implementation
+protected:
+	AudioObjectID				mObjectID;
+
+};
+
+inline void	CAHALAudioObject::AddPropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock)
+{
+	OSStatus theError = AudioObjectAddPropertyListenerBlock(mObjectID, &inAddress, inDispatchQueue, inListenerBlock);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListenerBlock: got an error adding a property listener");
+}
+
+inline void	CAHALAudioObject::RemovePropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock)
+{
+	OSStatus theError = AudioObjectRemovePropertyListenerBlock(mObjectID, &inAddress, inDispatchQueue, inListenerBlock);
+	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener");
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp
new file mode 100644
index 0000000..62b9b3c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp
@@ -0,0 +1,182 @@
+/*
+     File: CAHALAudioStream.cpp
+ Abstract: CAHALAudioStream.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAHALAudioStream.h"
+
+//	PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+//	CAHALAudioStream
+//==================================================================================================
+
+CAHALAudioStream::CAHALAudioStream(AudioObjectID inAudioStream)
+:
+	CAHALAudioObject(inAudioStream)
+{
+}
+
+CAHALAudioStream::~CAHALAudioStream()
+{
+}
+
+UInt32	CAHALAudioStream::GetDirection() const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyDirection);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32	CAHALAudioStream::GetTerminalType() const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyTerminalType);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32	CAHALAudioStream::GetStartingChannel() const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyStartingChannel);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32	CAHALAudioStream::GetLatency() const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyLatency);
+	return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+void	CAHALAudioStream::GetCurrentVirtualFormat(AudioStreamBasicDescription& outFormat) const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyVirtualFormat);
+	UInt32 theSize = sizeof(AudioStreamBasicDescription);
+	GetPropertyData(theAddress, 0, NULL, theSize, &outFormat);
+}
+
+void	CAHALAudioStream::SetCurrentVirtualFormat(const AudioStreamBasicDescription& inFormat)
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyVirtualFormat);
+	SetPropertyData(theAddress, 0, NULL, sizeof(AudioStreamBasicDescription), &inFormat);
+}
+
+UInt32	CAHALAudioStream::GetNumberAvailableVirtualFormats() const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyAvailableVirtualFormats);
+	UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+	theAnswer /= SizeOf32(AudioStreamRangedDescription);
+	return theAnswer;
+}
+
+void	CAHALAudioStream::GetAvailableVirtualFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyAvailableVirtualFormats);
+	UInt32 theSize = ioNumberFormats * SizeOf32(AudioStreamRangedDescription);
+	GetPropertyData(theAddress, 0, NULL, theSize, outFormats);
+	ioNumberFormats = theSize / SizeOf32(AudioStreamRangedDescription);
+}
+
+void	CAHALAudioStream::GetAvailableVirtualFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const
+{
+	UInt32 theNumberFormats = GetNumberAvailableVirtualFormats();
+	if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+	{
+		CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats);
+		GetAvailableVirtualFormats(theNumberFormats, theFormats);
+		if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+		{
+			outFormat = theFormats[inIndex];
+		}
+	}
+}
+
+void	CAHALAudioStream::GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat);
+	UInt32 theSize = sizeof(AudioStreamBasicDescription);
+	GetPropertyData(theAddress, 0, NULL, theSize, &outFormat);
+}
+
+void	CAHALAudioStream::SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat)
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat);
+	SetPropertyData(theAddress, 0, NULL, sizeof(AudioStreamBasicDescription), &inFormat);
+}
+
+UInt32	CAHALAudioStream::GetNumberAvailablePhysicalFormats() const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats);
+	UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+	theAnswer /= SizeOf32(AudioStreamRangedDescription);
+	return theAnswer;
+}
+
+void	CAHALAudioStream::GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const
+{
+	CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats);
+	UInt32 theSize = ioNumberFormats * SizeOf32(AudioStreamRangedDescription);
+	GetPropertyData(theAddress, 0, NULL, theSize, outFormats);
+	ioNumberFormats = theSize / SizeOf32(AudioStreamRangedDescription);
+}
+
+void	CAHALAudioStream::GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const
+{
+	UInt32 theNumberFormats = GetNumberAvailablePhysicalFormats();
+	if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+	{
+		CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats);
+		GetAvailablePhysicalFormats(theNumberFormats, theFormats);
+		if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+		{
+			outFormat = theFormats[inIndex];
+		}
+	}
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h
new file mode 100644
index 0000000..0c6cb55
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h
@@ -0,0 +1,94 @@
+/*
+     File: CAHALAudioStream.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAHALAudioStream_h__)
+#define __CAHALAudioStream_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Super Class Includes
+#include "CAHALAudioObject.h"
+
+//==================================================================================================
+//	CAHALAudioStream
+//==================================================================================================
+
+class CAHALAudioStream
+:
+	public	CAHALAudioObject
+{
+
+//	Construction/Destruction
+public:
+					CAHALAudioStream(AudioObjectID inAudioStream);
+	virtual			~CAHALAudioStream();
+
+//	Attributes
+public:
+	UInt32			GetDirection() const;
+	UInt32			GetTerminalType() const;
+	UInt32			GetStartingChannel() const;
+	UInt32			GetLatency() const;
+
+//	Format Info
+public:
+	void			GetCurrentVirtualFormat(AudioStreamBasicDescription& outFormat) const;
+	void			SetCurrentVirtualFormat(const AudioStreamBasicDescription& inFormat);
+	UInt32			GetNumberAvailableVirtualFormats() const;
+	void			GetAvailableVirtualFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const;
+	void			GetAvailableVirtualFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const;
+
+	void			GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const;
+	void			SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat);
+	UInt32			GetNumberAvailablePhysicalFormats() const;
+	void			GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const;
+	void			GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp
new file mode 100644
index 0000000..404dd98
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp
@@ -0,0 +1,181 @@
+/*
+     File: CAHALAudioSystemObject.cpp
+ Abstract: CAHALAudioSystemObject.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAHALAudioSystemObject.h"
+
+//	PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CACFString.h"
+#include "CAHALAudioDevice.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+//	CAHALAudioSystemObject
+//==================================================================================================
+
+CAHALAudioSystemObject::CAHALAudioSystemObject()
+:
+	CAHALAudioObject(kAudioObjectSystemObject)
+{
+}
+
+CAHALAudioSystemObject::~CAHALAudioSystemObject()
+{
+}
+
+UInt32	CAHALAudioSystemObject::GetNumberAudioDevices() const
+{
+	CAPropertyAddress theAddress(kAudioHardwarePropertyDevices);
+	UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+	theAnswer /= SizeOf32(AudioObjectID);
+	return theAnswer;
+}
+
+void	CAHALAudioSystemObject::GetAudioDevices(UInt32& ioNumberAudioDevices, AudioObjectID* outAudioDevices) const
+{
+	CAPropertyAddress theAddress(kAudioHardwarePropertyDevices);
+	UInt32 theSize = ioNumberAudioDevices * SizeOf32(AudioObjectID);
+	GetPropertyData(theAddress, 0, NULL, theSize, outAudioDevices);
+	ioNumberAudioDevices = theSize / SizeOf32(AudioObjectID);
+}
+
+AudioObjectID	CAHALAudioSystemObject::GetAudioDeviceAtIndex(UInt32 inIndex) const
+{
+	AudioObjectID theAnswer = kAudioObjectUnknown;
+	UInt32 theNumberDevices = GetNumberAudioDevices();
+	if((theNumberDevices > 0) && (inIndex < theNumberDevices))
+	{
+		CAAutoArrayDelete<AudioObjectID> theDeviceList(theNumberDevices);
+		GetAudioDevices(theNumberDevices, theDeviceList);
+		if((theNumberDevices > 0) && (inIndex < theNumberDevices))
+		{
+			theAnswer = theDeviceList[inIndex];
+		}
+	}
+	return theAnswer;
+}
+
+AudioObjectID	CAHALAudioSystemObject::GetAudioDeviceForUID(CFStringRef inUID) const
+{
+	AudioObjectID theAnswer = kAudioObjectUnknown;
+	AudioValueTranslation theValue = { &inUID, sizeof(CFStringRef), &theAnswer, sizeof(AudioObjectID) };
+	CAPropertyAddress theAddress(kAudioHardwarePropertyDeviceForUID);
+	UInt32 theSize = sizeof(AudioValueTranslation);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theAnswer;
+}
+
+void	CAHALAudioSystemObject::LogBasicDeviceInfo()
+{
+	UInt32 theNumberDevices = GetNumberAudioDevices();
+	CAAutoArrayDelete<AudioObjectID> theDeviceList(theNumberDevices);
+	GetAudioDevices(theNumberDevices, theDeviceList);
+	DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: %d devices", (int)theNumberDevices);
+	for(UInt32 theDeviceIndex = 0; theDeviceIndex < theNumberDevices; ++theDeviceIndex)
+	{
+		char theCString[256];
+		UInt32 theCStringSize = sizeof(theCString);
+		DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: Device %d", (int)theDeviceIndex);
+		
+		CAHALAudioDevice theDevice(theDeviceList[theDeviceIndex]);
+		DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo:   Object ID: %d", (int)theDeviceList[theDeviceIndex]);
+		
+		CACFString theDeviceName(theDevice.CopyName());
+		theCStringSize = sizeof(theCString);
+		theDeviceName.GetCString(theCString, theCStringSize);
+		DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo:   Name:      %s", theCString);
+		
+		CACFString theDeviceUID(theDevice.CopyDeviceUID());
+		theCStringSize = sizeof(theCString);
+		theDeviceUID.GetCString(theCString, theCStringSize);
+		DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo:   UID:       %s", theCString);
+	}
+}
+
+static inline AudioObjectPropertySelector	CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(bool inIsInput, bool inIsSystem)
+{
+	AudioObjectPropertySelector theAnswer = kAudioHardwarePropertyDefaultOutputDevice;
+	if(inIsInput)
+	{
+		theAnswer = kAudioHardwarePropertyDefaultInputDevice;
+	}
+	else if(inIsSystem)
+	{
+		theAnswer = kAudioHardwarePropertyDefaultSystemOutputDevice;
+	}
+	return theAnswer;
+}
+
+AudioObjectID	CAHALAudioSystemObject::GetDefaultAudioDevice(bool inIsInput, bool inIsSystem) const
+{
+	AudioObjectID theAnswer = kAudioObjectUnknown;
+	CAPropertyAddress theAddress(CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(inIsInput, inIsSystem));
+	UInt32 theSize = sizeof(AudioObjectID);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+	return theAnswer;
+}
+
+void	CAHALAudioSystemObject::SetDefaultAudioDevice(bool inIsInput, bool inIsSystem, AudioObjectID inNewDefaultDevice)
+{
+	CAPropertyAddress theAddress(CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(inIsInput, inIsSystem));
+	UInt32 theSize = sizeof(AudioObjectID);
+	SetPropertyData(theAddress, 0, NULL, theSize, &inNewDefaultDevice);
+}
+
+AudioObjectID	CAHALAudioSystemObject::GetAudioPlugInForBundleID(CFStringRef inUID) const
+{
+	AudioObjectID theAnswer = kAudioObjectUnknown;
+	AudioValueTranslation theValue = { &inUID, sizeof(CFStringRef), &theAnswer, sizeof(AudioObjectID) };
+	CAPropertyAddress theAddress(kAudioHardwarePropertyPlugInForBundleID);
+	UInt32 theSize = sizeof(AudioValueTranslation);
+	GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+	return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h
new file mode 100644
index 0000000..0ade7a5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h
@@ -0,0 +1,90 @@
+/*
+     File: CAHALAudioSystemObject.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAHALAudioSystemObject_h__)
+#define __CAHALAudioSystemObject_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Super Class Includes
+#include "CAHALAudioObject.h"
+
+//==================================================================================================
+//	CAHALAudioSystemObject
+//==================================================================================================
+
+class CAHALAudioSystemObject
+:
+	public	CAHALAudioObject
+{
+
+//	Construction/Destruction
+public:
+					CAHALAudioSystemObject();
+	virtual			~CAHALAudioSystemObject();
+
+//	Audio Device List Management
+public:
+	UInt32			GetNumberAudioDevices() const;
+	void			GetAudioDevices(UInt32& ioNumberAudioDevices, AudioObjectID* outAudioDevices) const;
+	AudioObjectID	GetAudioDeviceAtIndex(UInt32 inIndex) const;
+	AudioObjectID	GetAudioDeviceForUID(CFStringRef inUID) const;
+	void			LogBasicDeviceInfo();
+
+//	Default Device Management
+public:
+	AudioObjectID	GetDefaultAudioDevice(bool inIsInput, bool inIsSystem) const;
+	void			SetDefaultAudioDevice(bool inIsInput, bool inIsSystem, AudioObjectID inNewDefaultDevice);
+	
+//	PlugIns
+public:
+	AudioObjectID	GetAudioPlugInForBundleID(CFStringRef inBundleID) const;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp
new file mode 100644
index 0000000..db78a4a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp
@@ -0,0 +1,99 @@
+/*
+     File: CAHostTimeBase.cpp
+ Abstract: CAHostTimeBase.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CAHostTimeBase.h"
+
+Float64			CAHostTimeBase::sFrequency = 0;
+Float64			CAHostTimeBase::sInverseFrequency = 0;
+UInt32			CAHostTimeBase::sMinDelta = 0;
+UInt32			CAHostTimeBase::sToNanosNumerator = 0;
+UInt32			CAHostTimeBase::sToNanosDenominator = 0;
+pthread_once_t	CAHostTimeBase::sIsInited = PTHREAD_ONCE_INIT;
+#if Track_Host_TimeBase
+UInt64			CAHostTimeBase::sLastTime = 0;
+#endif
+
+//=============================================================================
+//	CAHostTimeBase
+//
+//	This class provides platform independent access to the host's time base.
+//=============================================================================
+
+void	CAHostTimeBase::Initialize()
+{
+	//	get the info about Absolute time
+	#if TARGET_OS_MAC
+		struct mach_timebase_info	theTimeBaseInfo;
+		mach_timebase_info(&theTimeBaseInfo);
+		sMinDelta = 1;
+		sToNanosNumerator = theTimeBaseInfo.numer;
+		sToNanosDenominator = theTimeBaseInfo.denom;
+
+		//	the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9
+		sFrequency = static_cast<Float64>(sToNanosDenominator) / static_cast<Float64>(sToNanosNumerator);
+		sFrequency *= 1000000000.0;
+	#elif TARGET_OS_WIN32
+		LARGE_INTEGER theFrequency;
+		QueryPerformanceFrequency(&theFrequency);
+		sMinDelta = 1;
+		sToNanosNumerator = 1000000000ULL;
+		sToNanosDenominator = *((UInt64*)&theFrequency);
+		sFrequency = static_cast<Float64>(*((UInt64*)&theFrequency));
+	#endif
+	sInverseFrequency = 1.0 / sFrequency;
+	
+	#if	Log_Host_Time_Base_Parameters
+		DebugPrintf("Host Time Base Parameters");
+		DebugPrintf(" Minimum Delta:          %lu", (unsigned long)sMinDelta);
+		DebugPrintf(" Frequency:              %f", sFrequency);
+		DebugPrintf(" To Nanos Numerator:     %lu", (unsigned long)sToNanosNumerator);
+		DebugPrintf(" To Nanos Denominator:   %lu", (unsigned long)sToNanosDenominator);
+	#endif
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h
new file mode 100644
index 0000000..50e3507
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h
@@ -0,0 +1,234 @@
+/*
+     File: CAHostTimeBase.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAHostTimeBase_h__)
+#define __CAHostTimeBase_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+#if TARGET_OS_MAC
+	#include <mach/mach_time.h>
+	#include <pthread.h>
+#elif TARGET_OS_WIN32
+	#include <windows.h>
+	#include "WinPThreadDefs.h"
+#else
+	#error	Unsupported operating system
+#endif
+
+#include "CADebugPrintf.h"
+
+//=============================================================================
+//	CAHostTimeBase
+//
+//	This class provides platform independent access to the host's time base.
+//=============================================================================
+
+#if CoreAudio_Debug
+//	#define Log_Host_Time_Base_Parameters	1
+//	#define Track_Host_TimeBase				1
+#endif
+
+class	CAHostTimeBase
+{
+
+public:
+	static UInt64			ConvertToNanos(UInt64 inHostTime);
+	static UInt64			ConvertFromNanos(UInt64 inNanos);
+
+	static UInt64			GetTheCurrentTime();
+#if TARGET_OS_MAC
+	static UInt64			GetCurrentTime() { return GetTheCurrentTime(); }
+#endif
+	static UInt64			GetCurrentTimeInNanos();
+
+	static Float64			GetFrequency() { pthread_once(&sIsInited, Initialize); return sFrequency; }
+	static Float64			GetInverseFrequency() { pthread_once(&sIsInited, Initialize); return sInverseFrequency; }
+	static UInt32			GetMinimumDelta() { pthread_once(&sIsInited, Initialize); return sMinDelta; }
+
+	static UInt64			AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
+	static SInt64			HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
+
+	static UInt64			MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator);
+	
+private:
+	static void				Initialize();
+	
+	static pthread_once_t	sIsInited;
+	
+	static Float64			sFrequency;
+	static Float64			sInverseFrequency;
+	static UInt32			sMinDelta;
+	static UInt32			sToNanosNumerator;
+	static UInt32			sToNanosDenominator;
+#if Track_Host_TimeBase
+	static UInt64			sLastTime;
+#endif
+};
+
+inline UInt64	CAHostTimeBase::GetTheCurrentTime()
+{
+	UInt64 theTime = 0;
+
+	#if TARGET_OS_MAC
+		theTime = mach_absolute_time();
+	#elif TARGET_OS_WIN32
+		LARGE_INTEGER theValue;
+		QueryPerformanceCounter(&theValue);
+		theTime = *((UInt64*)&theValue);
+	#endif
+	
+	#if	Track_Host_TimeBase
+		if(sLastTime != 0)
+		{
+			if(theTime <= sLastTime)
+			{
+				DebugPrintf("CAHostTimeBase::GetTheCurrentTime: the current time is earlier than the last time, now: %qd, then: %qd", theTime, sLastTime);
+			}
+			sLastTime = theTime;
+		}
+		else
+		{
+			sLastTime = theTime;
+		}
+	#endif
+
+	return theTime;
+}
+
+inline UInt64	CAHostTimeBase::ConvertToNanos(UInt64 inHostTime)
+{
+	pthread_once(&sIsInited, Initialize);
+	
+	UInt64 theAnswer = MultiplyByRatio(inHostTime, sToNanosNumerator, sToNanosDenominator);
+	#if CoreAudio_Debug
+		if(((sToNanosNumerator > sToNanosDenominator) && (theAnswer < inHostTime)) || ((sToNanosDenominator > sToNanosNumerator) && (theAnswer > inHostTime)))
+		{
+			DebugPrintf("CAHostTimeBase::ConvertToNanos: The conversion wrapped");
+		}
+	#endif
+	
+	return theAnswer;
+}
+
+inline UInt64	CAHostTimeBase::ConvertFromNanos(UInt64 inNanos)
+{
+	pthread_once(&sIsInited, Initialize);
+
+	UInt64 theAnswer = MultiplyByRatio(inNanos, sToNanosDenominator, sToNanosNumerator);
+	#if CoreAudio_Debug
+		if(((sToNanosDenominator > sToNanosNumerator) && (theAnswer < inNanos)) || ((sToNanosNumerator > sToNanosDenominator) && (theAnswer > inNanos)))
+		{
+			DebugPrintf("CAHostTimeBase::ConvertFromNanos: The conversion wrapped");
+		}
+	#endif
+
+	return theAnswer;
+}
+
+inline UInt64	CAHostTimeBase::GetCurrentTimeInNanos()
+{
+	return ConvertToNanos(GetTheCurrentTime());
+}
+
+inline UInt64	CAHostTimeBase::AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
+{
+	UInt64 theAnswer;
+	
+	if(inStartTime <= inEndTime)
+	{
+		theAnswer = inEndTime - inStartTime;
+	}
+	else
+	{
+		theAnswer = inStartTime - inEndTime;
+	}
+	
+	return ConvertToNanos(theAnswer);
+}
+
+inline SInt64	CAHostTimeBase::HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
+{
+	SInt64 theAnswer;
+	SInt64 theSign = 1;
+	
+	if(inStartTime <= inEndTime)
+	{
+		theAnswer = static_cast<SInt64>(inEndTime - inStartTime);
+	}
+	else
+	{
+		theAnswer = static_cast<SInt64>(inStartTime - inEndTime);
+		theSign = -1;
+	}
+	
+	return theSign * static_cast<SInt64>(ConvertToNanos(static_cast<UInt64>(theAnswer)));
+}
+
+inline UInt64	CAHostTimeBase::MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator)
+{
+#if TARGET_OS_MAC && TARGET_RT_64_BIT
+	__uint128_t theAnswer = inMuliplicand;
+#else
+	long double theAnswer = inMuliplicand;
+#endif
+	if(inNumerator != inDenominator)
+	{
+		theAnswer *= inNumerator;
+		theAnswer /= inDenominator;
+	}
+	return static_cast<UInt64>(theAnswer);
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h b/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h
new file mode 100644
index 0000000..7fd4ac4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h
@@ -0,0 +1,140 @@
+/*
+     File: CALogMacros.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CALogMacros_h__)
+#define __CALogMacros_h__
+
+//=============================================================================
+//	Log Macros
+//=============================================================================
+
+#if	CoreAudio_Debug
+
+	#include "CADebugMacros.h"
+	#include "CADebugPrintf.h"
+	#include <stdio.h>
+	#include <string.h>
+	
+	#define	PrintLine(msg)						DebugPrintfRtn(DebugPrintfFileComma "%s\n", (msg))
+	
+	#define PrintBool(msg, b)					DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "true" : "false")
+	#define PrintIndexedBool(msg, i, b)			DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: %s\n", (msg), (long)(i), (b) ? "true" : "false")
+	
+	#define PrintToggle(msg, b)					DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "on" : "off")
+	#define PrintIndexedToggle(msg, i, b)		DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: %s\n", (msg), (long)(i), (b) ? "on" : "off")
+	
+	#define PrintInt(msg, n)					DebugPrintfRtn(DebugPrintfFileComma "%s%ld\n", (msg), (long)(n))
+	#define PrintIndexedInt(msg, i, n)			DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: %ld\n", (msg), (long)(i), (long)(n))
+	
+	#define PrintHex(msg, n)					DebugPrintfRtn(DebugPrintfFileComma "%s0x%lX\n", (msg), (unsigned long)(n))
+	#define PrintIndexedHex(msg, i, n)			DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: 0x%lX\n", (msg), (long)(i), (unsigned long)(n))
+	
+	#define PrintFloat(msg, f)					DebugPrintfRtn(DebugPrintfFileComma "%s%.6f\n", (msg), (f))
+	#define PrintIndexedFloat(msg, i, f)		DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: %.6f\n", (msg), (long)(i), (f))
+	#define PrintFloatIndexedFloat(msg, i, f)	DebugPrintfRtn(DebugPrintfFileComma "  %s %.6f: %.6f\n", (msg), (i), (f))
+	
+	#define	PrintString(msg, s)					DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (s))
+	#define PrintIndexedString(msg, i, s)		DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: %s\n", (msg), (long)(i), (s))
+	
+	#define PrintPointer(msg, p)				DebugPrintfRtn(DebugPrintfFileComma "%s%p\n", (msg), (p))
+	#define PrintIndexedPointer(msg, i, p)		DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: %p\n", (msg), (long)(i), (p))
+	
+	#define	Print4CharCode(msg, c)				{																								\
+													UInt32 __4CC_number = (c);																	\
+													char __4CC_string[5] = CA4CCToCString(__4CC_number);										\
+													DebugPrintfRtn(DebugPrintfFileComma "%s'%s'\n", (msg), __4CC_string);							\
+												}
+	#define PrintIndexed4CharCode(msg, i, c)	{																								\
+													UInt32 __4CC_number = (c);																	\
+													char __4CC_string[5] = CA4CCToCString(__4CC_number);										\
+													DebugPrintfRtn(DebugPrintfFileComma "  %s %ld: '%s'\n", (msg), (long)(i), __4CC_string);		\
+												}
+	
+	#define	ErrorLine(s)						DebugPrintfRtn(DebugPrintfFileComma "%s\n", (s))
+	#define	OSErrorLine(s, e)					{																								\
+													OSStatus __err_number = (e);																\
+													char __err_string[5] = CA4CCToCString(__err_number);										\
+													DebugPrintfRtn(DebugPrintfFileComma "%s, OSStatus code: %s\n", (s), __err_string);				\
+												}
+	
+	#define	MessageIfOSError(e, s)				if((e) != 0) { OSErrorLine(s, e); }
+	#define	MessageIfNULL(p, s)					if((p) == 0) { ErrorLine(s); }
+
+#else
+
+	#define	PrintLine(msg)					
+	
+	#define PrintBool(msg, b)					(b)
+	#define PrintIndexedBool(msg, i, b)			(b)
+	
+	#define PrintInt(msg, n)					(n)
+	#define PrintIndexedInt(msg, i, n)			(n)
+	
+	#define PrintHex(msg, n)					(n)
+	#define PrintIndexedHex(msg, i, n)			(n)
+	
+	#define PrintFloat(msg, f)					(f)
+	#define PrintIndexedFloat(msg, i, f)		(f)
+	#define PrintFloatIndexedFloat(msg, i, f)	(f)
+	
+	#define	PrintString(msg, s)					(s)
+	#define PrintIndexedString(msg, i, s)		(s)
+	
+	#define PrintPointer(msg, p)				(p)
+	#define PrintIndexedPointer(msg, i, p)		(p)
+	
+	#define	Print4CharCode(msg, c)				(c)
+	#define PrintIndexed4CharCode(msg, i, c)	(c)
+	
+	#define	ErrorLine(s)						(s)
+	#define	OSErrorLine(s, e)					(e)
+	
+	#define	MessageIfOSError(e, s)				(e)
+	#define	MessageIfNULL(p, s)					(p)
+
+#endif	//	CoreAudio_Debug
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMath.h b/libs/appleutility/CoreAudio/PublicUtility/CAMath.h
new file mode 100644
index 0000000..eb81f26
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMath.h
@@ -0,0 +1,68 @@
+/*
+     File: CAMath.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAMath_h__
+#define __CAMath_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+inline bool fiszero(Float64 f) { return (f == 0.); }
+inline bool fiszero(Float32 f) { return (f == 0.f); }
+
+inline bool fnonzero(Float64 f) { return !fiszero(f); }
+inline bool fnonzero(Float32 f) { return !fiszero(f); }
+
+inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; }
+inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; }
+
+inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); }
+inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); }
+
+#endif // __CAMath_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h b/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h
new file mode 100644
index 0000000..62e95d4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h
@@ -0,0 +1,157 @@
+/*
+     File: CAMixMap.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAMixMap_h__
+#define __CAMixMap_h__
+
+	// manages the setting of mix map volumes
+	
+class CAMixMap {
+public:
+				CAMixMap ()
+					: mIns(0), mOuts (0), mMixMap(NULL)
+					{}
+					
+				CAMixMap (const CAMixMap &mm) 
+					: mIns(0), mOuts (0), mMixMap(NULL)
+					{ *this = mm; }
+				
+				CAMixMap (UInt32 numIns, UInt32 numOuts) 
+					: mIns(numIns), mOuts (numOuts), mMixMap(NULL)
+					{ 
+						mMixMap = new Float32[numIns * numOuts]; 
+						memset (mMixMap, 0, ByteSize());
+					}
+								
+				~CAMixMap () { delete [] mMixMap; }
+	
+	CAMixMap&	operator=(const CAMixMap& mm) 
+				{ 
+					if (mMixMap) { delete [] mMixMap; mMixMap = NULL; }
+					mIns = mm.mIns; mOuts = mm.mOuts;
+					if (NumIns() && NumOuts()) { 
+						mMixMap = new Float32 [ NumIns() * NumOuts() ];
+						memcpy (mMixMap, mm.mMixMap, ByteSize());
+					}
+					return *this;
+				}
+				
+	UInt32		NumIns () const { return mIns; }
+	UInt32		NumOuts () const { return mOuts; }
+
+	void		SetCrossPoint (UInt32 inputChan, UInt32 outputChan, Float32 val)
+				{
+					if (inputChan < NumIns() && outputChan < NumOuts())
+						mMixMap[inputChan * NumOuts() + outputChan] = val;
+				}
+	Float32		GetCrossPoint (UInt32 inputChan, UInt32 outputChan) const
+				{
+					return (inputChan < NumIns() && outputChan < NumOuts())
+							? mMixMap[inputChan * NumOuts() + outputChan]
+							: 0;
+				}
+
+	void		SetDiagonal (Float32 val)
+				{
+					for (UInt32 i = 0; i < NumIns() && i < NumOuts(); ++i) {
+						mMixMap[i * NumOuts() + i] = val;
+					}
+				}
+	
+	void		Clear () { memset (mMixMap, 0, ByteSize()); }
+	
+	
+	Float32*	MM() { return mMixMap; }
+	const Float32*	MM() const { return mMixMap; }
+	UInt32		ByteSize () const { return NumIns() * NumOuts() * sizeof(Float32); }
+
+	UInt32		CountActiveInputs(UInt32 inOutputChannel)
+				{
+					UInt32 sum = 0;
+					for (UInt32 i = 0, k = inOutputChannel; i < mIns; ++i, k+=mOuts) {
+						if (mMixMap[k] != 0.f) sum++;
+					}
+					return sum;
+				}
+				
+	void		Normalize()
+				{
+					// ensure that no output channel will sum over unity.
+					Float32* mixmap = mMixMap;
+					Float32 maxsum = 0.f;
+					for (UInt32 j = 0; j < mOuts; ++j) {
+						Float32 sum = 0.f;
+						for (UInt32 i = 0, k = j; i < mIns; ++i, k+=mOuts) {
+							sum += mixmap[k];
+						}
+						if (sum > maxsum) maxsum = sum;
+					}
+					
+					if (maxsum == 0.f) return;
+					Float32 scale = 1.f / maxsum;
+					for (UInt32 i = 0; i < mIns * mOuts; ++i) {
+						mixmap[i] *= scale;
+					}
+				}
+	
+	void		Print ()
+				{
+					printf ("Num Ins: %d, Num Outs: %d\n", (int)mIns, (int)mOuts);
+					for (unsigned int ins = 0; ins < mIns; ++ins) {
+						printf ("\t%d: ", ins);
+						for (unsigned int outs = 0; outs < mOuts; ++outs)
+							printf ("(%.3f) ", mMixMap[ins * NumOuts() + outs]); 
+						printf("\n");
+					}
+				}
+				
+private:
+	UInt32	mIns;
+	UInt32	mOuts;
+	Float32 *mMixMap;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp
new file mode 100644
index 0000000..88cf9b0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp
@@ -0,0 +1,345 @@
+/*
+     File: CAMutex.cpp
+ Abstract: CAMutex.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAMutex.h"
+
+#if TARGET_OS_MAC
+	#include <errno.h>
+#endif
+
+//	PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAHostTimeBase.h"
+
+//==================================================================================================
+//	Logging
+//==================================================================================================
+
+#if CoreAudio_Debug
+//	#define	Log_Ownership		1
+//	#define	Log_Errors			1
+//	#define Log_LongLatencies	1
+//	#define LongLatencyThreshholdNS	1000000ULL	// nanoseconds
+#endif
+
+//==================================================================================================
+//	CAMutex
+//==================================================================================================
+
+CAMutex::CAMutex(const char* inName)
+:
+	mName(inName),
+	mOwner(0)
+{
+#if TARGET_OS_MAC
+	OSStatus theError = pthread_mutex_init(&mMutex, NULL);
+	ThrowIf(theError != 0, CAException(theError), "CAMutex::CAMutex: Could not init the mutex");
+	
+	#if	Log_Ownership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::CAMutex: creating %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+	#endif
+#elif TARGET_OS_WIN32
+	mMutex = CreateMutex(NULL, false, NULL);
+	ThrowIfNULL(mMutex, CAException(GetLastError()), "CAMutex::CAMutex: could not create the mutex.");
+	
+	#if	Log_Ownership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::CAMutex: creating %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+	#endif
+#endif
+}
+
+CAMutex::~CAMutex()
+{
+#if TARGET_OS_MAC
+	#if	Log_Ownership
+		DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::~CAMutex: destroying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+	#endif
+	pthread_mutex_destroy(&mMutex);
+#elif TARGET_OS_WIN32
+	#if	Log_Ownership
+		DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::~CAMutex: destroying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+	#endif
+	if(mMutex != NULL)
+	{
+		CloseHandle(mMutex);
+	}
+#endif
+}
+
+bool	CAMutex::Lock()
+{
+	bool theAnswer = false;
+	
+#if TARGET_OS_MAC
+	pthread_t theCurrentThread = pthread_self();
+	if(!pthread_equal(theCurrentThread, mOwner))
+	{
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p is locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+		#endif
+		
+		#if Log_LongLatencies
+			UInt64 lockTryTime = CAHostTimeBase::GetCurrentTimeInNanos();
+		#endif
+		
+		OSStatus theError = pthread_mutex_lock(&mMutex);
+		ThrowIf(theError != 0, CAException(theError), "CAMutex::Lock: Could not lock the mutex");
+		mOwner = theCurrentThread;
+		theAnswer = true;
+	
+		#if Log_LongLatencies
+			UInt64 lockAcquireTime = CAHostTimeBase::GetCurrentTimeInNanos();
+			if (lockAcquireTime - lockTryTime >= LongLatencyThresholdNS)
+				DebugPrintfRtn(DebugPrintfFileComma "Thread %p took %.6fs to acquire the lock %s\n", theCurrentThread, (lockAcquireTime - lockTryTime) * 1.0e-9 /* nanos to seconds */, mName);
+		#endif
+		
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p has locked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+		#endif
+	}
+#elif TARGET_OS_WIN32
+	if(mOwner != GetCurrentThreadId())
+	{
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu is locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+		#endif
+
+		OSStatus theError = WaitForSingleObject(mMutex, INFINITE);
+		ThrowIfError(theError, CAException(theError), "CAMutex::Lock: could not lock the mutex");
+		mOwner = GetCurrentThreadId();
+		theAnswer = true;
+	
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+		#endif
+	}
+#endif
+
+	return theAnswer;
+}
+
+void	CAMutex::Unlock()
+{
+#if TARGET_OS_MAC
+	if(pthread_equal(pthread_self(), mOwner))
+	{
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p is unlocking %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+		#endif
+
+		mOwner = 0;
+		OSStatus theError = pthread_mutex_unlock(&mMutex);
+		ThrowIf(theError != 0, CAException(theError), "CAMutex::Unlock: Could not unlock the mutex");
+	
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p has unlocked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+		#endif
+	}
+	else
+	{
+		DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
+	}
+#elif TARGET_OS_WIN32
+	if(mOwner == GetCurrentThreadId())
+	{
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu is unlocking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+		#endif
+
+		mOwner = 0;
+		bool wasReleased = ReleaseMutex(mMutex);
+		ThrowIf(!wasReleased, CAException(GetLastError()), "CAMutex::Unlock: Could not unlock the mutex");
+	
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu has unlocked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+		#endif
+	}
+	else
+	{
+		DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
+	}
+#endif
+}
+
+bool	CAMutex::Try(bool& outWasLocked)
+{
+	bool theAnswer = false;
+	outWasLocked = false;
+
+#if TARGET_OS_MAC
+	pthread_t theCurrentThread = pthread_self();
+	if(!pthread_equal(theCurrentThread, mOwner))
+	{
+		//	this means the current thread doesn't already own the lock
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p is try-locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+		#endif
+
+		//	go ahead and call trylock to see if we can lock it.
+		int theError = pthread_mutex_trylock(&mMutex);
+		if(theError == 0)
+		{
+			//	return value of 0 means we successfully locked the lock
+			mOwner = theCurrentThread;
+			theAnswer = true;
+			outWasLocked = true;
+	
+			#if	Log_Ownership
+				DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p has locked %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+			#endif
+		}
+		else if(theError == EBUSY)
+		{
+			//	return value of EBUSY means that the lock was already locked by another thread
+			theAnswer = false;
+			outWasLocked = false;
+	
+			#if	Log_Ownership
+				DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p failed to lock %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+			#endif
+		}
+		else
+		{
+			//	any other return value means something really bad happenned
+			ThrowIfError(theError, CAException(theError), "CAMutex::Try: call to pthread_mutex_trylock failed");
+		}
+	}
+	else
+	{
+		//	this means the current thread already owns the lock
+		theAnswer = true;
+		outWasLocked = false;
+	}
+#elif TARGET_OS_WIN32
+	if(mOwner != GetCurrentThreadId())
+	{
+		//	this means the current thread doesn't own the lock
+		#if	Log_Ownership
+			DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu is try-locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+		#endif
+		
+		//	try to acquire the mutex
+		OSStatus theError = WaitForSingleObject(mMutex, 0);
+		if(theError == WAIT_OBJECT_0)
+		{
+			//	this means we successfully locked the lock
+			mOwner = GetCurrentThreadId();
+			theAnswer = true;
+			outWasLocked = true;
+	
+			#if	Log_Ownership
+				DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+			#endif
+		}
+		else if(theError == WAIT_TIMEOUT)
+		{
+			//	this means that the lock was already locked by another thread
+			theAnswer = false;
+			outWasLocked = false;
+	
+			#if	Log_Ownership
+				DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu failed to lock %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+			#endif
+		}
+		else
+		{
+			//	any other return value means something really bad happenned
+			ThrowIfError(theError, CAException(GetLastError()), "CAMutex::Try: call to lock the mutex failed");
+		}
+	}
+	else
+	{
+		//	this means the current thread already owns the lock
+		theAnswer = true;
+		outWasLocked = false;
+	}
+#endif
+	
+	return theAnswer;
+}
+
+bool	CAMutex::IsFree() const
+{
+	return mOwner == 0;
+}
+
+bool	CAMutex::IsOwnedByCurrentThread() const
+{
+	bool theAnswer = true;
+	
+#if TARGET_OS_MAC
+	theAnswer = pthread_equal(pthread_self(), mOwner);
+#elif TARGET_OS_WIN32
+	theAnswer = (mOwner == GetCurrentThreadId());
+#endif
+
+	return theAnswer;
+}
+
+
+CAMutex::Unlocker::Unlocker(CAMutex& inMutex)
+:	mMutex(inMutex),
+	mNeedsLock(false)
+{
+	Assert(mMutex.IsOwnedByCurrentThread(), "Major problem: Unlocker attempted to unlock a mutex not owned by the current thread!");
+
+	mMutex.Unlock();
+	mNeedsLock = true;
+}
+
+CAMutex::Unlocker::~Unlocker()
+{
+	if(mNeedsLock)
+	{
+		mMutex.Lock();
+	}
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h
new file mode 100644
index 0000000..093066b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h
@@ -0,0 +1,163 @@
+/*
+     File: CAMutex.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAMutex_h__
+#define __CAMutex_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+#if TARGET_OS_MAC
+	#include <pthread.h>
+#elif TARGET_OS_WIN32
+	#include <windows.h>
+#else
+	#error	Unsupported operating system
+#endif
+
+//==================================================================================================
+//	A recursive mutex.
+//==================================================================================================
+
+class	CAMutex
+{
+//	Construction/Destruction
+public:
+					CAMutex(const char* inName);
+	virtual			~CAMutex();
+
+//	Actions
+public:
+	virtual bool	Lock();
+	virtual void	Unlock();
+	virtual bool	Try(bool& outWasLocked);	// returns true if lock is free, false if not
+	
+	virtual bool	IsFree() const;
+	virtual bool	IsOwnedByCurrentThread() const;
+		
+//	Implementation
+protected:
+	const char*		mName;
+#if TARGET_OS_MAC
+	pthread_t		mOwner;
+	pthread_mutex_t	mMutex;
+#elif TARGET_OS_WIN32
+	UInt32			mOwner;
+	HANDLE			mMutex;
+#endif
+
+//	Helper class to manage taking and releasing recursively
+public:
+	class			Locker
+	{
+	
+	//	Construction/Destruction
+	public:
+					Locker(CAMutex& inMutex) : mMutex(&inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex->Lock(); }
+					Locker(CAMutex* inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = (mMutex != NULL && mMutex->Lock()); }
+						// in this case the mutex can be null
+					~Locker() { if(mNeedsRelease) { mMutex->Unlock(); } }
+	
+	
+	private:
+					Locker(const Locker&);
+		Locker&		operator=(const Locker&);
+	
+	//	Implementation
+	private:
+		CAMutex*	mMutex;
+		bool		mNeedsRelease;
+	
+	};
+
+// Unlocker
+	class Unlocker
+	{
+	public:
+						Unlocker(CAMutex& inMutex);
+						~Unlocker();
+		
+	private:
+		CAMutex&	mMutex;
+		bool		mNeedsLock;
+		
+		// Hidden definitions of copy ctor, assignment operator
+		Unlocker(const Unlocker& copy);				// Not implemented
+		Unlocker& operator=(const Unlocker& copy);	// Not implemented
+	};
+	
+// you can use this with Try - if you take the lock in try, pass in the outWasLocked var
+	class Tryer {
+	
+	//	Construction/Destruction
+	public:
+		Tryer (CAMutex &mutex) : mMutex(mutex), mNeedsRelease(false), mHasLock(false) { mHasLock = mMutex.Try (mNeedsRelease); }
+		~Tryer () { if (mNeedsRelease) mMutex.Unlock(); }
+		
+		bool HasLock () const { return mHasLock; }
+
+	private:
+					Tryer(const Tryer&);
+		Tryer&		operator=(const Tryer&);
+
+	//	Implementation
+	private:
+		CAMutex &		mMutex;
+		bool			mNeedsRelease;
+		bool			mHasLock;
+	};
+};
+
+
+#endif // __CAMutex_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp
new file mode 100644
index 0000000..3da1058
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp
@@ -0,0 +1,450 @@
+/*
+     File: CAPThread.cpp
+ Abstract: CAPThread.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	Self Include
+#include "CAPThread.h"
+
+//	PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//	System Includes
+#if	TARGET_OS_MAC
+	#include <mach/mach.h>
+#endif
+
+//	Standard Library Includes
+#include <stdio.h>
+
+//==================================================================================================
+//	CAPThread
+//==================================================================================================
+
+// returns the thread's priority as it was last set by the API
+#define CAPTHREAD_SET_PRIORITY				0
+// returns the thread's priority as it was last scheduled by the Kernel
+#define CAPTHREAD_SCHEDULED_PRIORITY		1
+
+//#define	Log_SetPriority						1
+
+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority, bool inFixedPriority, bool inAutoDelete, const char* inThreadName)
+:
+#if TARGET_OS_MAC
+	mPThread(0),
+    mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
+#elif TARGET_OS_WIN32
+	mThreadHandle(NULL),
+	mThreadID(0),
+#endif
+	mThreadRoutine(inThreadRoutine),
+	mThreadParameter(inParameter),
+	mPriority(inPriority),
+	mPeriod(0),
+	mComputation(0),
+	mConstraint(0),
+	mIsPreemptible(true),
+	mTimeConstraintSet(false),
+	mFixedPriority(inFixedPriority),
+	mAutoDelete(inAutoDelete)
+{
+	if(inThreadName != NULL)
+	{
+		strlcpy(mThreadName, inThreadName, kMaxThreadNameLength);
+	}
+	else
+	{
+		memset(mThreadName, 0, kMaxThreadNameLength);
+	}
+}
+
+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete, const char* inThreadName)
+:
+#if TARGET_OS_MAC
+	mPThread(0),
+    mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
+#elif TARGET_OS_WIN32
+	mThreadHandle(NULL),
+	mThreadID(0),
+#endif
+	mThreadRoutine(inThreadRoutine),
+	mThreadParameter(inParameter),
+	mPriority(kDefaultThreadPriority),
+	mPeriod(inPeriod),
+	mComputation(inComputation),
+	mConstraint(inConstraint),
+	mIsPreemptible(inIsPreemptible),
+	mTimeConstraintSet(true),
+	mFixedPriority(false),
+	mAutoDelete(inAutoDelete)
+{
+	if(inThreadName != NULL)
+	{
+		strlcpy(mThreadName, inThreadName, kMaxThreadNameLength);
+	}
+	else
+	{
+		memset(mThreadName, 0, kMaxThreadNameLength);
+	}
+}
+
+CAPThread::~CAPThread()
+{
+}
+
+UInt32	CAPThread::GetScheduledPriority()
+{
+#if TARGET_OS_MAC
+    return CAPThread::getScheduledPriority( mPThread, CAPTHREAD_SCHEDULED_PRIORITY );
+#elif TARGET_OS_WIN32
+	UInt32 theAnswer = 0;
+	if(mThreadHandle != NULL)
+	{
+		theAnswer = GetThreadPriority(mThreadHandle);
+	}
+	return theAnswer;
+#endif
+}
+
+UInt32	CAPThread::GetScheduledPriority(NativeThread thread)
+{
+#if TARGET_OS_MAC
+    return getScheduledPriority( thread, CAPTHREAD_SCHEDULED_PRIORITY );
+#elif TARGET_OS_WIN32
+	return 0;	// ???
+#endif
+}
+
+void	CAPThread::SetPriority(UInt32 inPriority, bool inFixedPriority)
+{
+	mPriority = inPriority;
+	mTimeConstraintSet = false;
+	mFixedPriority = inFixedPriority;
+#if TARGET_OS_MAC
+	if(mPThread != 0)
+	{
+		SetPriority(mPThread, mPriority, mFixedPriority);
+    } 
+#elif TARGET_OS_WIN32
+	if(mThreadID != NULL)
+	{
+		SetPriority(mThreadID, mPriority, mFixedPriority);
+	}
+#endif
+}
+
+void	CAPThread::SetPriority(NativeThread inThread, UInt32 inPriority, bool inFixedPriority)
+{
+#if TARGET_OS_MAC
+	if(inThread != 0)
+	{
+		kern_return_t theError = 0;
+		
+		//	set whether or not this is a fixed priority thread
+		if (inFixedPriority)
+		{
+			thread_extended_policy_data_t theFixedPolicy = { false };
+			theError = thread_policy_set(pthread_mach_thread_np(inThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
+			AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the fixed-priority policy");
+		}
+		
+		//	set the thread's absolute priority which is relative to the priority on which thread_policy_set() is called
+		UInt32 theCurrentThreadPriority = getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY);
+        thread_precedence_policy_data_t thePrecedencePolicy = { static_cast<integer_t>(inPriority - theCurrentThreadPriority) };
+		theError = thread_policy_set(pthread_mach_thread_np(inThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
+        AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the precedence policy");
+		
+		#if	Log_SetPriority
+			DebugMessageN4("CAPThread::SetPriority: requsted: %lu spawning: %lu current: %lu assigned: %d", mPriority, mSpawningThreadPriority, theCurrentThreadPriority, thePrecedencePolicy.importance);
+		#endif
+    } 
+#elif TARGET_OS_WIN32
+	if(inThread != NULL)
+	{
+		HANDLE hThread = OpenThread(NULL, FALSE, inThread);
+		if(hThread != NULL) {
+			SetThreadPriority(hThread, inPriority);
+			CloseHandle(hThread);
+		}
+	}
+#endif
+}
+
+void	CAPThread::SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible)
+{
+	mPeriod = inPeriod;
+	mComputation = inComputation;
+	mConstraint = inConstraint;
+	mIsPreemptible = inIsPreemptible;
+	mTimeConstraintSet = true;
+#if TARGET_OS_MAC
+	if(mPThread != 0)
+	{
+		thread_time_constraint_policy_data_t thePolicy;
+		thePolicy.period = mPeriod;
+		thePolicy.computation = mComputation;
+		thePolicy.constraint = mConstraint;
+		thePolicy.preemptible = mIsPreemptible;
+		AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&thePolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT), "CAPThread::SetTimeConstraints: thread_policy_set failed");
+	}
+#elif TARGET_OS_WIN32
+	if(mThreadHandle != NULL)
+	{
+		SetThreadPriority(mThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);
+	}
+#endif
+}
+
+void	CAPThread::Start()
+{
+#if TARGET_OS_MAC
+	Assert(mPThread == 0, "CAPThread::Start: can't start because the thread is already running");
+	if(mPThread == 0)
+	{
+		OSStatus			theResult;
+		pthread_attr_t		theThreadAttributes;
+		
+		theResult = pthread_attr_init(&theThreadAttributes);
+		ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: Thread attributes could not be created.");
+		
+		theResult = pthread_attr_setdetachstate(&theThreadAttributes, PTHREAD_CREATE_DETACHED);
+		ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: A thread could not be created in the detached state.");
+		
+		theResult = pthread_create(&mPThread, &theThreadAttributes, (ThreadRoutine)CAPThread::Entry, this);
+		ThrowIf(theResult != 0 || !mPThread, CAException(theResult), "CAPThread::Start: Could not create a thread.");
+		
+		pthread_attr_destroy(&theThreadAttributes);
+		
+	}
+#elif TARGET_OS_WIN32
+	Assert(mThreadID == 0, "CAPThread::Start: can't start because the thread is already running");
+	if(mThreadID == 0)
+	{
+		//	clean up the existing thread handle
+		if(mThreadHandle != NULL)
+		{
+			CloseHandle(mThreadHandle);
+			mThreadHandle = NULL;
+		}
+		
+		//	create a new thread
+		mThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Entry, this, 0, &mThreadID);
+		ThrowIf(mThreadHandle == NULL, CAException(GetLastError()), "CAPThread::Start: Could not create a thread.");
+	}
+#endif
+}
+
+#if TARGET_OS_MAC
+
+void*	CAPThread::Entry(CAPThread* inCAPThread)
+{
+	void* theAnswer = NULL;
+
+#if TARGET_OS_MAC
+	inCAPThread->mPThread = pthread_self();
+#elif TARGET_OS_WIN32
+	// do we need to do something here?
+#endif
+	
+#if	!TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+	if(inCAPThread->mThreadName[0] != 0)
+	{
+		pthread_setname_np(inCAPThread->mThreadName);
+	}
+#endif
+
+	try 
+	{
+		if(inCAPThread->mTimeConstraintSet)
+		{
+			inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
+		}
+		else
+		{
+			inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
+		}
+
+		if(inCAPThread->mThreadRoutine != NULL)
+		{
+			theAnswer = inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter);
+		}
+	}
+	catch (...)
+	{
+		// what should be done here?
+	}
+	inCAPThread->mPThread = 0;
+	if (inCAPThread->mAutoDelete)
+		delete inCAPThread;
+	return theAnswer;
+}
+
+UInt32 CAPThread::getScheduledPriority(pthread_t inThread, int inPriorityKind)
+{
+    thread_basic_info_data_t			threadInfo;
+	policy_info_data_t					thePolicyInfo;
+	unsigned int						count;
+
+	if (inThread == NULL)
+		return 0;
+    
+    // get basic info
+    count = THREAD_BASIC_INFO_COUNT;
+    thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
+    
+	switch (threadInfo.policy) {
+		case POLICY_TIMESHARE:
+			count = POLICY_TIMESHARE_INFO_COUNT;
+			thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
+            if (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) {
+                return static_cast<UInt32>(thePolicyInfo.ts.cur_priority);
+            }
+            return static_cast<UInt32>(thePolicyInfo.ts.base_priority);
+            break;
+            
+        case POLICY_FIFO:
+			count = POLICY_FIFO_INFO_COUNT;
+			thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
+            if ( (thePolicyInfo.fifo.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
+                return static_cast<UInt32>(thePolicyInfo.fifo.depress_priority);
+            }
+            return static_cast<UInt32>(thePolicyInfo.fifo.base_priority);
+            break;
+            
+		case POLICY_RR:
+			count = POLICY_RR_INFO_COUNT;
+			thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
+			if ( (thePolicyInfo.rr.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
+                return static_cast<UInt32>(thePolicyInfo.rr.depress_priority);
+            }
+            return static_cast<UInt32>(thePolicyInfo.rr.base_priority);
+            break;
+	}
+    
+    return 0;
+}
+
+#elif TARGET_OS_WIN32
+
+UInt32 WINAPI	CAPThread::Entry(CAPThread* inCAPThread)
+{
+	UInt32 theAnswer = 0;
+
+	try 
+	{
+		if(inCAPThread->mTimeConstraintSet)
+		{
+			inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
+		}
+		else
+		{
+			inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
+		}
+
+		if(inCAPThread->mThreadRoutine != NULL)
+		{
+			theAnswer = reinterpret_cast<UInt32>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter));
+		}
+		inCAPThread->mThreadID = 0;
+	}
+	catch (...)
+	{
+		// what should be done here?
+	}
+	CloseHandle(inCAPThread->mThreadHandle);
+	inCAPThread->mThreadHandle = NULL;
+	if (inCAPThread->mAutoDelete)
+		delete inCAPThread;
+	return theAnswer;
+}
+
+extern "C"
+Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr)
+{
+	return InterlockedCompareExchange((volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue;
+}
+
+#endif
+
+void	CAPThread::SetName(const char* inThreadName)
+{
+	if(inThreadName != NULL)
+	{
+		strlcpy(mThreadName, inThreadName, kMaxThreadNameLength);
+	}
+	else
+	{
+		memset(mThreadName, 0, kMaxThreadNameLength);
+	}
+}
+
+#if CoreAudio_Debug
+void	CAPThread::DebugPriority(const char *label)
+{
+#if !TARGET_OS_WIN32
+	if (mTimeConstraintSet)
+		printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this, 
+		(int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1);
+	else
+		printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "", 
+		(int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1);
+#else
+	if (mTimeConstraintSet)
+	{
+		printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this, 
+		(int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1);
+	}
+	else
+	{
+		printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "", 
+		(int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1);
+	}
+#endif
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h
new file mode 100644
index 0000000..4145125
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h
@@ -0,0 +1,191 @@
+/*
+     File: CAPThread.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAPThread_h__)
+#define __CAPThread_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CFBase.h>
+#else
+	#include <CFBase.h>
+#endif
+
+#if TARGET_OS_MAC
+	#include <pthread.h>
+	#include <unistd.h>
+#elif TARGET_OS_WIN32
+	#include <windows.h>
+#else
+	#error	Unsupported operating system
+#endif
+
+//==================================================================================================
+//	CAPThread
+//
+//	This class wraps a pthread and a Win32 thread.
+//	caution: long-running fixed priority threads can make the system unresponsive
+//==================================================================================================
+
+class	CAPThread
+{
+
+//	Types
+public:
+	typedef void*			(*ThreadRoutine)(void* inParameter);
+
+//	Constants
+public:
+	enum
+	{
+#if	TARGET_OS_MAC
+							kMinThreadPriority = 1,
+							kMaxThreadPriority = 63,
+							kDefaultThreadPriority = 31,
+							kMaxThreadNameLength = 64
+#elif TARGET_OS_WIN32
+							kMinThreadPriority = 1,
+							kMaxThreadPriority = 31,
+							kDefaultThreadPriority = THREAD_PRIORITY_NORMAL,
+							kMaxThreadNameLength = 256
+#endif
+	};
+
+//	Construction/Destruction
+public:
+							CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority = kDefaultThreadPriority, bool inFixedPriority=false, bool inAutoDelete=false, const char* inThreadName = NULL);
+							CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete=false, const char* inThreadName = NULL);
+	virtual					~CAPThread();
+
+//	Properties
+public:
+#if TARGET_OS_MAC
+	typedef pthread_t		NativeThread;
+
+	NativeThread			GetNativeThread() { return mPThread; }
+	static NativeThread		GetCurrentThread() { return pthread_self(); }
+	static bool				IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); }
+
+	bool					operator==(NativeThread b) { return pthread_equal(mPThread,b); }
+
+	pthread_t				GetPThread() const { return mPThread; }
+	bool					IsCurrentThread() const { return (0 != mPThread) && (pthread_self() == mPThread); }
+	bool					IsRunning() const { return 0 != mPThread; }
+    static UInt32			getScheduledPriority(pthread_t inThread, int inPriorityKind);
+#elif TARGET_OS_WIN32
+	typedef unsigned long	NativeThread;
+	
+	NativeThread			GetNativeThread() { return mThreadID; }
+	static NativeThread		GetCurrentThread() { return GetCurrentThreadId(); }
+	static bool				IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); }
+
+	bool					operator ==(NativeThread b) { return (mThreadID==b); }
+
+	HANDLE					GetThreadHandle() const { return mThreadHandle; }
+	UInt32					GetThreadID() const { return mThreadID; }
+	bool					IsCurrentThread() const { return (0 != mThreadID) && (GetCurrentThreadId() == mThreadID); }
+	bool					IsRunning() const { return 0 != mThreadID; }
+#endif
+
+	bool					IsTimeShareThread() const { return !mTimeConstraintSet; }
+	bool					IsTimeConstraintThread() const { return mTimeConstraintSet; }
+
+	UInt32					GetPriority() const { return mPriority; }
+    UInt32					GetScheduledPriority();
+	static UInt32			GetScheduledPriority(NativeThread thread);
+    void					SetPriority(UInt32 inPriority, bool inFixedPriority=false);
+	static void				SetPriority(NativeThread inThread, UInt32 inPriority, bool inFixedPriority = false);
+
+	void					GetTimeConstraints(UInt32& outPeriod, UInt32& outComputation, UInt32& outConstraint, bool& outIsPreemptible) const { outPeriod = mPeriod; outComputation = mComputation; outConstraint = mConstraint; outIsPreemptible = mIsPreemptible; }
+	void					SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible);
+	void					ClearTimeConstraints() { SetPriority(mPriority); }
+	
+	bool					WillAutoDelete() const { return mAutoDelete; }
+	void					SetAutoDelete(bool b) { mAutoDelete = b; }
+	
+	void					SetName(const char* inThreadName);
+
+#if CoreAudio_Debug	
+	void					DebugPriority(const char *label);
+#endif
+
+//	Actions
+public:
+	virtual void			Start();
+
+//	Implementation
+protected:
+#if TARGET_OS_MAC
+	static void*			Entry(CAPThread* inCAPThread);
+#elif TARGET_OS_WIN32
+	static UInt32 WINAPI	Entry(CAPThread* inCAPThread);
+#endif
+
+#if	TARGET_OS_MAC
+	pthread_t				mPThread;
+    UInt32					mSpawningThreadPriority;
+#elif TARGET_OS_WIN32
+	HANDLE					mThreadHandle;
+	unsigned long			mThreadID;
+#endif
+	ThreadRoutine			mThreadRoutine;
+	void*					mThreadParameter;
+	char					mThreadName[kMaxThreadNameLength];
+	UInt32					mPriority;
+	UInt32					mPeriod;
+	UInt32					mComputation;
+	UInt32					mConstraint;
+	bool					mIsPreemptible;
+	bool					mTimeConstraintSet;
+    bool					mFixedPriority;
+	bool					mAutoDelete;		// delete self when thread terminates
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp
new file mode 100644
index 0000000..d3fe008
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp
@@ -0,0 +1,468 @@
+/*
+     File: CAPersistence.cpp
+ Abstract: CAPersistence.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CACFArray.h"
+#include "CACFDictionary.h"
+
+#include "CAAudioUnit.h"
+#include "CACFString.h"
+#include "CAAudioChannelLayout.h"
+#include "CAAUParameter.h"
+#include "CAAUMIDIMap.h"
+
+#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
+
+#pragma mark __CAStreamBasicDescription
+
+static const CFStringRef kSampleRate = CFSTR("sample rate");
+static const CFStringRef kFormat = CFSTR("format");
+static const CFStringRef kFormatFlags = CFSTR("format flags");
+static const CFStringRef kPacketBytes = CFSTR("packet bytes");
+static const CFStringRef kFramePackets = CFSTR("frame packets");
+static const CFStringRef kFrameBytes = CFSTR("frame bytes");
+static const CFStringRef kFrameChannels = CFSTR("frame channels");
+static const CFStringRef kChannelBits = CFSTR("channel bits");
+
+		// This will return a value that should be used as the key for this struct
+		// and a CFData object that contains the current state of this object
+OSStatus	CAStreamBasicDescription::Save (CFPropertyListRef *outData) const
+{
+	CACFDictionary dict(false);
+
+	if (!dict.AddFloat64 (kSampleRate, mSampleRate)) goto error;
+	if (!dict.AddUInt32 (kFormat, mFormatID)) goto error;
+	if (!dict.AddUInt32 (kFormatFlags, mFormatFlags)) goto error;
+	if (!dict.AddUInt32 (kPacketBytes, mBytesPerPacket)) goto error;
+	if (!dict.AddUInt32 (kFramePackets, mFramesPerPacket)) goto error;
+	if (!dict.AddUInt32 (kFrameBytes, mBytesPerFrame)) goto error;
+	if (!dict.AddUInt32 (kFrameChannels, mChannelsPerFrame)) goto error;
+	if (!dict.AddUInt32 (kChannelBits, mBitsPerChannel)) goto error;
+	
+	*outData = dict.GetDict();
+
+	return noErr;
+
+error:
+	dict.ShouldRelease (true);
+	return paramErr;
+}
+
+	
+		// Given a CFData object generated by the save command, this will re-establish
+		// the CAStreamBasicDescription
+OSStatus	CAStreamBasicDescription::Restore (CFPropertyListRef& inData)
+{
+	if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+	CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+	
+	if (!dict.GetFloat64 (kSampleRate, mSampleRate)) return paramErr;
+	if (!dict.GetUInt32 (kFormat, mFormatID)) return paramErr;
+	if (!dict.GetUInt32 (kFormatFlags, mFormatFlags)) return paramErr;
+	if (!dict.GetUInt32 (kPacketBytes, mBytesPerPacket)) return paramErr;
+	if (!dict.GetUInt32 (kFramePackets, mFramesPerPacket)) return paramErr;
+	if (!dict.GetUInt32 (kFrameBytes, mBytesPerFrame)) return paramErr;
+	if (!dict.GetUInt32 (kFrameChannels, mChannelsPerFrame)) return paramErr;
+	if (!dict.GetUInt32 (kChannelBits, mBitsPerChannel)) return paramErr;
+
+	return noErr;
+}
+
+#pragma mark __CAComponentDescription
+
+static const CFStringRef kType = CFSTR("type");
+static const CFStringRef kSubType = CFSTR("subtype");
+static const CFStringRef kManu = CFSTR("manufacturer");
+
+OSStatus		CAComponentDescription::Save (CFPropertyListRef *outData) const
+{
+	CACFDictionary dict(false);
+	if (!dict.AddUInt32 (kType, componentType)) goto error;
+	if (!dict.AddUInt32 (kSubType, componentSubType)) goto error;
+	if (!dict.AddUInt32 (kManu, componentManufacturer)) goto error;
+	
+	*outData = dict.GetDict();
+	
+	return 0;
+error:
+	dict.ShouldRelease (true);
+	return paramErr;
+}
+
+OSStatus		CAComponentDescription::Restore (CFPropertyListRef &inData)
+{
+	if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+	CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+		
+	if (!dict.GetUInt32 (kType, componentType)) return paramErr;
+	if (!dict.GetUInt32 (kSubType, componentSubType)) return paramErr;
+	if (!dict.GetUInt32 (kManu, componentManufacturer)) return paramErr;
+
+	componentFlags = 0;
+	componentFlagsMask = 0;
+	
+	return 0;
+}
+
+#pragma mark __CAComponent
+
+OSStatus		CAComponent::Save (CFPropertyListRef *outData) const
+{
+	OSStatus result = mDesc.Save (outData);
+	if (result) return result;
+	
+	//add the name string of the component for a human readable name...
+	// this name string is *not* restored when restoring the component
+	CFStringRef	name = GetCompName ();
+	if (name && *outData)
+		CFDictionarySetValue ((CFMutableDictionaryRef)(*outData), CFSTR("name"), name);
+	
+	return noErr;
+}
+
+OSStatus		CAComponent::Restore (CFPropertyListRef &inData)
+{
+	if (mDesc.Restore (inData)) return paramErr;
+
+	Clear();
+
+	mComp = AudioComponentFindNext (NULL, &mDesc);
+		// this will restore the current flags...
+	if (mComp)
+		AudioComponentGetDescription (Comp(), &mDesc);
+
+	return noErr;
+}
+
+
+#pragma mark __CAAudioChannelLayout
+
+static const CFStringRef kACLTagKey = CFSTR("acl tag");
+static const CFStringRef kACLBitmapKey = CFSTR("chan bitmap");
+static const CFStringRef kACLLabelKey = CFSTR("label");
+static const CFStringRef kACLFlagsKey = CFSTR("flags");
+static const CFStringRef kACLCoords0Key = CFSTR("coords 0");
+static const CFStringRef kACLCoords1Key = CFSTR("coords 1");
+static const CFStringRef kACLCoords2Key = CFSTR("coords 2");
+static const CFStringRef kACLDescsKey = CFSTR("descriptions");
+	
+OSStatus	CAAudioChannelLayout::Save (CFPropertyListRef *outData) const 
+{
+	const AudioChannelLayout& layout = Layout();
+
+	CACFDictionary dict (false);
+	if (!dict.AddUInt32 (kACLTagKey, layout.mChannelLayoutTag))
+		goto badadd;
+	if (layout.mChannelBitmap && !dict.AddUInt32 (kACLBitmapKey, layout.mChannelBitmap))
+		goto badadd;
+	
+	if (layout.mNumberChannelDescriptions)
+	{	
+		CFMutableArrayRef descs = CFArrayCreateMutable (NULL, layout.mNumberChannelDescriptions, &kCFTypeArrayCallBacks);
+		
+		const AudioChannelDescription *desc = layout.mChannelDescriptions;
+		for (unsigned int i = 0; i < layout.mNumberChannelDescriptions; ++i, ++desc) 
+		{
+			CACFDictionary descDict (true);
+			if (!descDict.AddUInt32 (kACLLabelKey, desc->mChannelLabel))
+				{ CFRelease (descs); goto badadd; }
+			if (!descDict.AddUInt32 (kACLFlagsKey, desc->mChannelFlags))
+				{ CFRelease (descs); goto badadd; }
+			if (!descDict.AddFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
+				{ CFRelease (descs); goto badadd; }
+			if (!descDict.AddFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
+				{ CFRelease (descs); goto badadd; }
+			if (!descDict.AddFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
+				{ CFRelease (descs); goto badadd; }
+			
+			CFArrayAppendValue (descs, descDict.AsPropertyList());
+		}
+		dict.AddArray (kACLDescsKey, descs);
+		
+		CFRelease (descs);
+	}
+	
+	*outData = dict.GetDict();	
+	
+	return noErr;
+	
+badadd:
+	dict.ShouldRelease(true);
+	return paramErr;
+}
+
+OSStatus	CAAudioChannelLayout::Restore (CFPropertyListRef &inData) 
+{
+	if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+	CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+	RefCountedLayout *temp = NULL;
+	AudioChannelLayout* layout;
+	
+	CFArrayRef descs = NULL;
+	UInt32 numDescs = 0;
+
+	if (dict.GetArray (kACLDescsKey, descs)) {
+		numDescs = static_cast<OSStatus>(CFArrayGetCount (descs));
+	}
+	
+	temp = RefCountedLayout::CreateWithNumberChannelDescriptions(numDescs);
+	layout = temp->GetLayout();
+		
+	if (!dict.GetUInt32 (kACLTagKey, layout->mChannelLayoutTag))
+		goto badget;
+	if (dict.HasKey (kACLBitmapKey)) {
+		if (!dict.GetUInt32 (kACLBitmapKey, layout->mChannelBitmap))
+			goto badget;
+	} else
+		layout->mChannelBitmap = 0;
+		
+	layout->mNumberChannelDescriptions = numDescs;
+	
+	if (numDescs)
+	{
+		AudioChannelDescription *desc = layout->mChannelDescriptions;
+		for (unsigned int i = 0; i < numDescs; ++i, ++desc)
+		{
+			CFDictionaryRef descDict = (CFDictionaryRef)CFArrayGetValueAtIndex (descs, i);			
+			CACFDictionary theDesc (descDict, false);
+			
+			if (!theDesc.GetUInt32 (kACLLabelKey, desc->mChannelLabel))
+				goto badget;
+			if (!theDesc.GetUInt32 (kACLFlagsKey, desc->mChannelFlags))
+				goto badget;
+			if (!theDesc.GetFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
+				goto badget;
+			if (!theDesc.GetFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
+				goto badget;
+			if (!theDesc.GetFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
+				goto badget;
+		}
+	}
+	if (mLayout)
+		mLayout->release();
+
+	mLayout = temp;
+	
+	return noErr;
+
+badget:
+	delete temp;
+	return paramErr;
+}
+
+#pragma mark __AudioUnitParameter
+
+static const CFStringRef kAUScopeStr = CFSTR("scope");
+static const CFStringRef kAUElementIDStr = CFSTR("element ID");
+static const CFStringRef kAUParameterIDStr = CFSTR("paramID");
+
+void		CAAUParameter::Save (CFPropertyListRef &outData) const 
+{ 
+	return CAAUParameter::Save (*this, outData); 
+}
+
+// static functions to save/restore AudioUnitParameter
+void		CAAUParameter::Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData)
+{
+	CACFDictionary dict(false);
+	dict.AddUInt32 (kAUScopeStr, inParam.mScope);
+	dict.AddUInt32 (kAUElementIDStr, inParam.mElement);
+	dict.AddUInt32 (kAUParameterIDStr, inParam.mParameterID);
+
+	outData = dict.AsPropertyList();
+}
+
+OSStatus	CAAUParameter::Restore	(const CFPropertyListRef inData, AudioUnitParameter &outParam)
+{
+	if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+	CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+	if (!dict.GetUInt32 (kAUScopeStr, outParam.mScope)) return paramErr;
+	if (!dict.GetUInt32 (kAUElementIDStr, outParam.mElement)) return paramErr;
+	if (!dict.GetUInt32 (kAUParameterIDStr, outParam.mParameterID)) return paramErr;
+	return noErr;
+}
+
+
+#pragma mark __MIDIMap
+
+const CFStringRef kParamMIDIStr = CFSTR("param maps");
+
+const CFStringRef kMIDIFlagsStr = CFSTR("flags");
+const CFStringRef kMIDISubMinStr = CFSTR("sub min");
+const CFStringRef kMIDISubMaxStr = CFSTR("sub max");
+const CFStringRef kMIDIStatusStr = CFSTR("midi status byte");
+const CFStringRef kMIDIDataByteStr = CFSTR("midi data1 byte");
+const CFStringRef kAUStr = CFSTR("unit");
+
+static const CFStringRef kLocalElementIDStr = CFSTR("element ID");
+static const CFStringRef kLocalScopeStr = CFSTR("scope");
+static const CFStringRef kLocalParameterIDStr = CFSTR("paramID");
+
+void CAAUMIDIMap::Save(CFPropertyListRef &outData) const
+{
+	CACFDictionary paramDict(false);
+
+	paramDict.AddUInt32 (kLocalScopeStr, mScope);
+	paramDict.AddUInt32 (kLocalElementIDStr, mElement);
+	paramDict.AddUInt32 (kLocalParameterIDStr, mParameterID);
+	paramDict.AddUInt32 (kMIDIFlagsStr, mFlags);
+	paramDict.AddFloat32 (kMIDISubMinStr, mSubRangeMin);
+	paramDict.AddFloat32 (kMIDISubMaxStr, mSubRangeMax);
+
+	UInt32 data = mStatus;
+	paramDict.AddUInt32 (kMIDIStatusStr, data);
+
+	data = mData1;
+	paramDict.AddUInt32 (kMIDIDataByteStr, data);
+
+	outData = paramDict.GetCFDictionary();
+}
+
+void CAAUMIDIMap::Restore(CFDictionaryRef inData)
+{	
+	CACFDictionary paramDict (inData, false);
+
+	if (!paramDict.GetUInt32 (kLocalScopeStr, mScope)) return; 
+	if (!paramDict.GetUInt32 (kLocalElementIDStr, mElement)) return; 
+	if (!paramDict.GetUInt32 (kLocalParameterIDStr, mParameterID)) return; 
+	if (!paramDict.GetUInt32 (kMIDIFlagsStr, mFlags)) return;
+	if (!paramDict.GetFloat32 (kMIDISubMinStr, mSubRangeMin)) return; 
+	if (!paramDict.GetFloat32 (kMIDISubMaxStr, mSubRangeMax)) return; 
+	UInt32 data;		
+	if (!paramDict.GetUInt32 (kMIDIStatusStr, data)) return;
+	mStatus = data;
+	if (!paramDict.GetUInt32 (kMIDIDataByteStr, data)) return; 
+	mData1 = data;
+}
+
+void		CAAUMIDIMap::SaveAsMapPList (AudioUnit inUnit, const AUParameterMIDIMapping* inMappings, UInt32 inNumMappings, CFPropertyListRef &outData, CFStringRef inName)
+{
+
+	CACFDictionary mappingDict (false);	
+	CACFArray maps (true);
+	
+	for (UInt32 i = 0; i< inNumMappings; ++i) 
+	{
+		CFPropertyListRef data;
+		CAAUMIDIMap paramMap(inMappings[i]);
+		paramMap.Save (data);
+		if (data) 
+		{
+			maps.AppendCFType (data); 
+			CFRelease(data); 
+		}				
+	}
+
+	if (maps.GetNumberItems()) {
+		mappingDict.AddCFType (kParamMIDIStr, maps.GetCFArray());
+		
+		// Add the AU info here - where this map came from
+		CAAudioUnit au (inUnit);
+		CFPropertyListRef data;
+		au.Comp().Save (&data);
+		
+		mappingDict.AddCFType (kAUStr, data);
+		CFRelease(data);
+		
+		if (!inName) inName = CFSTR("Untitled");
+		mappingDict.AddString (CFSTR("name"), inName);
+		
+		mappingDict.AddUInt32 (CFSTR("version"), 1);
+		
+		outData = mappingDict.AsPropertyList();
+	} else {
+		mappingDict.ShouldRelease(true);
+		outData = NULL;
+	}
+}
+
+UInt32		CAAUMIDIMap::NumberOfMaps (const CFDictionaryRef inData)
+{
+	CACFDictionary dict (inData, false);
+	
+	if (dict.HasKey (kParamMIDIStr)) 
+	{
+		CFArrayRef cfArray;
+		dict.GetArray (kParamMIDIStr, cfArray); 
+		
+		CACFArray array (cfArray, false);
+		
+		return array.GetNumberItems();
+	}
+	return 0;
+}
+	
+void		CAAUMIDIMap::RestoreFromMapPList (const CFDictionaryRef inData, AUParameterMIDIMapping* outMappings, UInt32 inNumMappings)
+{
+
+	CACFDictionary dict (inData, false);
+	
+	if (dict.HasKey (kParamMIDIStr)) 
+	{
+		CFArrayRef cfArray;
+		dict.GetArray (kParamMIDIStr, cfArray); 
+		
+		CACFArray array (cfArray, false);
+		
+		UInt32 count = array.GetNumberItems();
+		if (count > inNumMappings)
+			count = inNumMappings;
+		
+		for (unsigned int i = 0; i < count; ++i)
+		{
+			CFDictionaryRef paramsDictRef;
+			if (!array.GetDictionary(i, paramsDictRef)) 
+				return;
+			
+			CAAUMIDIMap parameterMap;
+			parameterMap.Restore(paramsDictRef);
+			outMappings[i] = parameterMap;
+		}
+	}
+}
+
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp
new file mode 100644
index 0000000..23ad2c0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp
@@ -0,0 +1,92 @@
+/*
+     File: CAProcess.cpp
+ Abstract: CAProcess.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CAProcess.h"
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+
+//=============================================================================
+//	CAProcess
+//=============================================================================
+
+bool	CAProcess::ProcessExists(pid_t inPID)
+{
+	//	pids <= 0 are reserved for special purposes and -1 is
+	//	used as a sentinel value by the HAL.
+	bool theAnswer = inPID > 0;
+	
+	if(theAnswer)
+	{
+		//	according to kill(2), the process exists if kill(pid, 0) returns 0
+		int wasKilled = kill(inPID, 0);
+		if(wasKilled != 0)
+		{
+			//	The kill call failed for some reason, but there is only one error code that
+			//	that indicates that the process doesn't exist.
+			theAnswer = errno != ESRCH;
+		}
+	}
+
+	
+	return theAnswer;
+}
+
+pid_t	CAProcess::GetPID()
+{
+	if(sPID == -1)
+	{
+		sPID = getpid();
+	}
+	
+	return sPID;
+}
+
+pid_t	CAProcess::sPID = -1;
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h
new file mode 100644
index 0000000..e512d91
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h
@@ -0,0 +1,75 @@
+/*
+     File: CAProcess.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAProcess_h__)
+#define __CAProcess_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include <sys/types.h>
+
+//=============================================================================
+//	CAProcess
+//
+//	Wrapper for utilities for dealing with Unix Processes.
+//=============================================================================
+
+class CAProcess
+{
+
+//	operations
+public:
+	static bool		ProcessExists(pid_t inPID);
+	static pid_t	GetPID();
+
+private:
+	static pid_t	sPID;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h b/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h
new file mode 100644
index 0000000..6df444b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h
@@ -0,0 +1,312 @@
+/*
+     File: CAPropertyAddress.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAPropertyAddress_h__)
+#define __CAPropertyAddress_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	PublicUtility Includes
+#include "CADebugMacros.h"
+
+//	System Includes
+#include <CoreAudio/AudioHardware.h>
+
+//  Standard Library Includes
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+//==================================================================================================
+//	CAPropertyAddress
+//
+//  CAPropertyAddress extends the AudioObjectPropertyAddress structure to C++ including constructors
+//  and other utility operations. Note that there is no defined operator< or operator== because the
+//  presence of wildcards for the fields make comparisons ambiguous without specifying whether or
+//  not to take the wildcards into account. Consequently, if you want to use this struct in an STL
+//  data structure, you'll need to specify the approriate function object explicitly in the template
+//  declaration.
+//==================================================================================================
+
+struct CAPropertyAddress
+:
+	public AudioObjectPropertyAddress
+{
+
+//	Construction/Destruction
+public:
+						CAPropertyAddress()																													: AudioObjectPropertyAddress() { mSelector = 0; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
+						CAPropertyAddress(AudioObjectPropertySelector inSelector)																			: AudioObjectPropertyAddress() { mSelector = inSelector; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
+						CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope)											: AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = kAudioObjectPropertyElementMaster; }
+						CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement)   : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = inElement; }
+						CAPropertyAddress(const AudioObjectPropertyAddress& inAddress)																		: AudioObjectPropertyAddress(inAddress){}
+						CAPropertyAddress(const CAPropertyAddress& inAddress)																				: AudioObjectPropertyAddress(inAddress){}
+	CAPropertyAddress&  operator=(const AudioObjectPropertyAddress& inAddress)																				{ AudioObjectPropertyAddress::operator=(inAddress); return *this; }
+	CAPropertyAddress&  operator=(const CAPropertyAddress& inAddress)																						{ AudioObjectPropertyAddress::operator=(inAddress); return *this; }
+	
+//  Operations
+public:
+	static bool			IsSameAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)							{ return (inAddress1.mScope == inAddress2.mScope) && (inAddress1.mSelector == inAddress2.mSelector) && (inAddress1.mElement == inAddress2.mElement); }
+	static bool			IsLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)						{ bool theAnswer = false; if(inAddress1.mScope != inAddress2.mScope) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(inAddress1.mSelector != inAddress2.mSelector) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
+	static bool			IsCongruentSelector(AudioObjectPropertySelector inSelector1, AudioObjectPropertySelector inSelector2)								{ return (inSelector1 == inSelector2) || (inSelector1 == kAudioObjectPropertySelectorWildcard) || (inSelector2 == kAudioObjectPropertySelectorWildcard); }
+	static bool			IsCongruentScope(AudioObjectPropertyScope inScope1, AudioObjectPropertyScope inScope2)												{ return (inScope1 == inScope2) || (inScope1 == kAudioObjectPropertyScopeWildcard) || (inScope2 == kAudioObjectPropertyScopeWildcard); }
+	static bool			IsCongruentElement(AudioObjectPropertyElement inElement1, AudioObjectPropertyElement inElement2)									{ return (inElement1 == inElement2) || (inElement1 == kAudioObjectPropertyElementWildcard) || (inElement2 == kAudioObjectPropertyElementWildcard); }
+	static bool			IsCongruentAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)						{ return IsCongruentScope(inAddress1.mScope, inAddress2.mScope) && IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector) && IsCongruentElement(inAddress1.mElement, inAddress2.mElement); }
+	static bool			IsCongruentLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)				{ bool theAnswer = false; if(!IsCongruentScope(inAddress1.mScope, inAddress2.mScope)) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(!IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector)) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else if(!IsCongruentElement(inAddress1.mElement, inAddress2.mElement)) { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
+
+//  STL Helpers
+public:
+	struct EqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+	{
+		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsSameAddress(inAddress1, inAddress2); }
+	};
+
+	struct LessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+	{
+		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsLessThanAddress(inAddress1, inAddress2); }
+	};
+
+	struct CongruentEqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+	{
+		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsCongruentAddress(inAddress1, inAddress2); }
+	};
+
+	struct CongruentLessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+	{
+		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsCongruentLessThanAddress(inAddress1, inAddress2); }
+	};
+
+};
+
+//==================================================================================================
+//  CAPropertyAddressList
+//
+//  An auto-resizing array of CAPropertyAddress structures.
+//==================================================================================================
+
+class   CAPropertyAddressList
+{
+
+//	Construction/Destruction
+public:
+											CAPropertyAddressList()																	: mAddressList(), mToken(NULL) {}
+	explicit								CAPropertyAddressList(void* inToken)													: mAddressList(), mToken(inToken) {}
+	explicit								CAPropertyAddressList(uintptr_t inToken)												: mAddressList(), mToken(reinterpret_cast<void*>(inToken)) {}
+											CAPropertyAddressList(const CAPropertyAddressList& inAddressList)						: mAddressList(inAddressList.mAddressList), mToken(inAddressList.mToken) {}
+	CAPropertyAddressList&					operator=(const CAPropertyAddressList& inAddressList)									{ mAddressList = inAddressList.mAddressList; mToken = inAddressList.mToken; return *this; }
+											~CAPropertyAddressList()																{}
+
+//	Operations
+public:
+	void*									GetToken() const																		{ return mToken; }
+	void									SetToken(void* inToken)																	{ mToken = inToken; }
+	
+	uintptr_t								GetIntToken() const																		{ return reinterpret_cast<uintptr_t>(mToken); }
+	void									SetIntToken(uintptr_t inToken)															{ mToken = reinterpret_cast<void*>(inToken); }
+	
+	AudioObjectID							GetAudioObjectIDToken() const															{ return static_cast<AudioObjectID>(reinterpret_cast<uintptr_t>(mToken)); }
+	
+	bool									IsEmpty() const																			{ return mAddressList.empty(); }
+	UInt32									GetNumberItems() const																	{ return ToUInt32(mAddressList.size()); }
+	void									GetItemByIndex(UInt32 inIndex, AudioObjectPropertyAddress& outAddress) const			{ if(inIndex < mAddressList.size()) { outAddress = mAddressList.at(inIndex); } }
+	const AudioObjectPropertyAddress*		GetItems() const																		{ return &(*mAddressList.begin()); }
+	AudioObjectPropertyAddress*				GetItems()																				{ return &(*mAddressList.begin()); }
+	
+	bool									HasItem(const AudioObjectPropertyAddress& inAddress) const								{ AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::CongruentEqualTo(), inAddress)); return theIterator != mAddressList.end(); }
+	bool									HasExactItem(const AudioObjectPropertyAddress& inAddress) const							{ AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); return theIterator != mAddressList.end(); }
+
+	void									AppendItem(const AudioObjectPropertyAddress& inAddress)									{ mAddressList.push_back(inAddress); }
+	void									AppendUniqueItem(const AudioObjectPropertyAddress& inAddress)							{ if(!HasItem(inAddress)) { mAddressList.push_back(inAddress); } }
+	void									AppendUniqueExactItem(const AudioObjectPropertyAddress& inAddress)						{ if(!HasExactItem(inAddress)) { mAddressList.push_back(inAddress); } }
+	void									InsertItemAtIndex(UInt32 inIndex, const AudioObjectPropertyAddress& inAddress)			{ if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.insert(theIterator, inAddress); } else { mAddressList.push_back(inAddress); } }
+	void									EraseExactItem(const AudioObjectPropertyAddress& inAddress)								{ AddressList::iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); if(theIterator != mAddressList.end()) { mAddressList.erase(theIterator); } }
+	void									EraseItemAtIndex(UInt32 inIndex)														{ if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.erase(theIterator); } }
+	void									EraseAllItems()																			{ mAddressList.clear(); }
+
+//  Implementation
+private:
+	typedef std::vector<CAPropertyAddress>  AddressList;
+
+	AddressList								mAddressList;
+	void*									mToken;
+	
+};
+
+//==================================================================================================
+//  CAPropertyAddressListVector
+//
+//  An auto-resizing array of CAPropertyAddressList objects.
+//==================================================================================================
+
+class	CAPropertyAddressListVector
+{
+
+//	Construction/Destruction
+public:
+												CAPropertyAddressListVector()														: mAddressListVector() {}
+												CAPropertyAddressListVector(const CAPropertyAddressListVector& inAddressListVector)	: mAddressListVector(inAddressListVector.mAddressListVector) {}
+	CAPropertyAddressListVector&				operator=(const CAPropertyAddressListVector& inAddressListVector)					{ mAddressListVector = inAddressListVector.mAddressListVector; return *this; }
+												~CAPropertyAddressListVector()														{}
+
+//	Operations
+public:
+	bool										IsEmpty() const																		{ return mAddressListVector.empty(); }
+	bool										HasAnyNonEmptyItems() const;
+	bool										HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const;
+	bool										HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const;
+
+	UInt32										GetNumberItems() const																{ return ToUInt32(mAddressListVector.size()); }
+	const CAPropertyAddressList&				GetItemByIndex(UInt32 inIndex) const												{ return mAddressListVector.at(inIndex); }
+	CAPropertyAddressList&						GetItemByIndex(UInt32 inIndex)														{ return mAddressListVector.at(inIndex); }
+	const CAPropertyAddressList*				GetItemByToken(void* inToken) const;
+	CAPropertyAddressList*						GetItemByToken(void* inToken);
+	const CAPropertyAddressList*				GetItemByIntToken(uintptr_t inToken) const;
+	CAPropertyAddressList*						GetItemByIntToken(uintptr_t inToken);
+	
+	void										AppendItem(const CAPropertyAddressList& inAddressList)								{ mAddressListVector.push_back(inAddressList); }
+	void										EraseAllItems()																		{ mAddressListVector.clear(); }
+	
+//  Implementation
+private:
+	typedef std::vector<CAPropertyAddressList>	AddressListVector;
+
+	AddressListVector							mAddressListVector;
+
+};
+
+inline bool	CAPropertyAddressListVector::HasAnyNonEmptyItems() const
+{
+	bool theAnswer = false;
+	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
+	{
+		theAnswer = !theIterator->IsEmpty();
+	}
+	return theAnswer;
+}
+
+inline bool	CAPropertyAddressListVector::HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const
+{
+	bool theAnswer = false;
+	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
+	{
+		theAnswer = theIterator->HasItem(inAddress);
+	}
+	return theAnswer;
+}
+
+inline bool	CAPropertyAddressListVector::HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const
+{
+	bool theAnswer = false;
+	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
+	{
+		theAnswer = theIterator->HasExactItem(inAddress);
+	}
+	return theAnswer;
+}
+
+inline const CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByToken(void* inToken) const
+{
+	const CAPropertyAddressList* theAnswer = NULL;
+	bool wasFound = false;
+	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+	{
+		if(theIterator->GetToken() == inToken)
+		{
+			wasFound = true;
+			theAnswer = &(*theIterator);
+		}
+	}
+	return theAnswer;
+}
+
+inline CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByToken(void* inToken)
+{
+	CAPropertyAddressList* theAnswer = NULL;
+	bool wasFound = false;
+	for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+	{
+		if(theIterator->GetToken() == inToken)
+		{
+			wasFound = true;
+			theAnswer = &(*theIterator);
+		}
+	}
+	return theAnswer;
+}
+
+inline const CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken) const
+{
+	const CAPropertyAddressList* theAnswer = NULL;
+	bool wasFound = false;
+	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+	{
+		if(theIterator->GetIntToken() == inToken)
+		{
+			wasFound = true;
+			theAnswer = &(*theIterator);
+		}
+	}
+	return theAnswer;
+}
+
+inline CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken)
+{
+	CAPropertyAddressList* theAnswer = NULL;
+	bool wasFound = false;
+	for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+	{
+		if(theIterator->GetIntToken() == inToken)
+		{
+			wasFound = true;
+			theAnswer = &(*theIterator);
+		}
+	}
+	return theAnswer;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h b/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h
new file mode 100644
index 0000000..f00fc61
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h
@@ -0,0 +1,97 @@
+/*
+     File: CAReferenceCounted.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAReferenceCounted_h__
+#define __CAReferenceCounted_h__
+
+#include "CAAtomic.h"
+
+// base class for reference-counted objects
+class CAReferenceCounted {
+public:
+	CAReferenceCounted() : mRefCount(1) {}
+	
+	void	retain() { CAAtomicIncrement32(&mRefCount); }
+	
+	void	release() 
+			{ 
+				SInt32 rc = CAAtomicDecrement32(&mRefCount);
+				if (rc == 0) {
+					releaseObject();
+				}
+			}
+
+
+	class Retainer {
+	public:
+		Retainer(CAReferenceCounted *obj) : mObject(obj) { mObject->retain(); }
+		~Retainer() { mObject->release(); }
+	
+	private:
+		CAReferenceCounted *	mObject;
+	};
+
+protected:
+    virtual	~CAReferenceCounted() { }
+	
+	virtual void releaseObject () 
+			{ 
+				delete this; 
+			}
+
+#if DEBUG
+public:
+#endif
+	SInt32	GetReferenceCount() const { return mRefCount; }
+private:
+	SInt32		mRefCount;
+
+	CAReferenceCounted(const CAReferenceCounted &a);
+	CAReferenceCounted &operator=(const CAReferenceCounted &a);
+};
+
+
+#endif // __CAReferenceCounted_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp
new file mode 100644
index 0000000..c78acd2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp
@@ -0,0 +1,319 @@
+/*
+     File: CARingBuffer.cpp
+ Abstract: CARingBuffer.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CARingBuffer.h"
+#include "CABitOperations.h"
+#include "CAAutoDisposer.h"
+#include "CAAtomic.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <libkern/OSAtomic.h>
+
+CARingBuffer::CARingBuffer() :
+	mBuffers(NULL), mNumberChannels(0), mCapacityFrames(0), mCapacityBytes(0)
+{
+
+}
+
+CARingBuffer::~CARingBuffer()
+{
+	Deallocate();
+}
+
+
+void	CARingBuffer::Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames)
+{
+	Deallocate();
+	
+	capacityFrames = NextPowerOfTwo(capacityFrames);
+	
+	mNumberChannels = nChannels;
+	mBytesPerFrame = bytesPerFrame;
+	mCapacityFrames = capacityFrames;
+	mCapacityFramesMask = capacityFrames - 1;
+	mCapacityBytes = bytesPerFrame * capacityFrames;
+
+	// put everything in one memory allocation, first the pointers, then the deinterleaved channels
+	UInt32 allocSize = (mCapacityBytes + sizeof(Byte *)) * nChannels;
+	Byte *p = (Byte *)CA_malloc(allocSize);
+	memset(p, 0, allocSize);
+	mBuffers = (Byte **)p;
+	p += nChannels * sizeof(Byte *);
+	for (int i = 0; i < nChannels; ++i) {
+		mBuffers[i] = p;
+		p += mCapacityBytes;
+	}
+	
+	for (UInt32 i = 0; i<kGeneralRingTimeBoundsQueueSize; ++i)
+	{
+		mTimeBoundsQueue[i].mStartTime = 0;
+		mTimeBoundsQueue[i].mEndTime = 0;
+		mTimeBoundsQueue[i].mUpdateCounter = 0;
+	}
+	mTimeBoundsQueuePtr = 0;
+}
+
+void	CARingBuffer::Deallocate()
+{
+	if (mBuffers) {
+		free(mBuffers);
+		mBuffers = NULL;
+	}
+	mNumberChannels = 0;
+	mCapacityBytes = 0;
+	mCapacityFrames = 0;
+}
+
+inline void ZeroRange(Byte **buffers, int nchannels, int offset, int nbytes)
+{
+	while (--nchannels >= 0) {
+		memset(*buffers + offset, 0, nbytes);
+		++buffers;
+	}
+}
+
+inline void StoreABL(Byte **buffers, int destOffset, const AudioBufferList *abl, int srcOffset, int nbytes)
+{
+	int nchannels = abl->mNumberBuffers;
+	const AudioBuffer *src = abl->mBuffers;
+	while (--nchannels >= 0) {
+		if (srcOffset > (int)src->mDataByteSize) continue;
+		memcpy(*buffers + destOffset, (Byte *)src->mData + srcOffset, std::min(nbytes, (int)src->mDataByteSize - srcOffset));
+		++buffers;
+		++src;
+	}
+}
+
+inline void FetchABL(AudioBufferList *abl, int destOffset, Byte **buffers, int srcOffset, int nbytes)
+{
+	int nchannels = abl->mNumberBuffers;
+	AudioBuffer *dest = abl->mBuffers;
+	while (--nchannels >= 0) {
+		if (destOffset > (int)dest->mDataByteSize) continue;
+		memcpy((Byte *)dest->mData + destOffset, *buffers + srcOffset, std::min(nbytes, (int)dest->mDataByteSize - destOffset));
+		++buffers;
+		++dest;
+	}
+}
+
+inline void ZeroABL(AudioBufferList *abl, int destOffset, int nbytes)
+{
+	int nBuffers = abl->mNumberBuffers;
+	AudioBuffer *dest = abl->mBuffers;
+	while (--nBuffers >= 0) {
+		if (destOffset > (int)dest->mDataByteSize) continue;
+		memset((Byte *)dest->mData + destOffset, 0, std::min(nbytes, (int)dest->mDataByteSize - destOffset));
+		++dest;
+	}
+}
+
+
+CARingBufferError	CARingBuffer::Store(const AudioBufferList *abl, UInt32 framesToWrite, SampleTime startWrite)
+{
+	if (framesToWrite == 0)
+		return kCARingBufferError_OK;
+	
+	if (framesToWrite > mCapacityFrames)
+		return kCARingBufferError_TooMuch;		// too big!
+
+	SampleTime endWrite = startWrite + framesToWrite;
+	
+	if (startWrite < EndTime()) {
+		// going backwards, throw everything out
+		SetTimeBounds(startWrite, startWrite);
+	} else if (endWrite - StartTime() <= mCapacityFrames) {
+		// the buffer has not yet wrapped and will not need to
+	} else {
+		// advance the start time past the region we are about to overwrite
+		SampleTime newStart = endWrite - mCapacityFrames;	// one buffer of time behind where we're writing
+		SampleTime newEnd = std::max(newStart, EndTime());
+		SetTimeBounds(newStart, newEnd);
+	}
+	
+	// write the new frames
+	Byte **buffers = mBuffers;
+	int nchannels = mNumberChannels;
+	int offset0, offset1, nbytes;
+	SampleTime curEnd = EndTime();
+	
+	if (startWrite > curEnd) {
+		// we are skipping some samples, so zero the range we are skipping
+		offset0 = FrameOffset(curEnd);
+		offset1 = FrameOffset(startWrite);
+		if (offset0 < offset1)
+			ZeroRange(buffers, nchannels, offset0, offset1 - offset0);
+		else {
+			ZeroRange(buffers, nchannels, offset0, mCapacityBytes - offset0);
+			ZeroRange(buffers, nchannels, 0, offset1);
+		}
+		offset0 = offset1;
+	} else {
+		offset0 = FrameOffset(startWrite);
+	}
+
+	offset1 = FrameOffset(endWrite);
+	if (offset0 < offset1)
+		StoreABL(buffers, offset0, abl, 0, offset1 - offset0);
+	else {
+		nbytes = mCapacityBytes - offset0;
+		StoreABL(buffers, offset0, abl, 0, nbytes);
+		StoreABL(buffers, 0, abl, nbytes, offset1);
+	}
+	
+	// now update the end time
+	SetTimeBounds(StartTime(), endWrite);
+	
+	return kCARingBufferError_OK;	// success
+}
+
+void	CARingBuffer::SetTimeBounds(SampleTime startTime, SampleTime endTime)
+{
+	UInt32 nextPtr = mTimeBoundsQueuePtr + 1;
+	UInt32 index = nextPtr & kGeneralRingTimeBoundsQueueMask;
+	
+	mTimeBoundsQueue[index].mStartTime = startTime;
+	mTimeBoundsQueue[index].mEndTime = endTime;
+	mTimeBoundsQueue[index].mUpdateCounter = nextPtr;
+	CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr);
+}
+
+CARingBufferError	CARingBuffer::GetTimeBounds(SampleTime &startTime, SampleTime &endTime)
+{
+	for (int i=0; i<8; ++i) // fail after a few tries.
+	{
+		UInt32 curPtr = mTimeBoundsQueuePtr;
+		UInt32 index = curPtr & kGeneralRingTimeBoundsQueueMask;
+		CARingBuffer::TimeBounds* bounds = mTimeBoundsQueue + index;
+		
+		startTime = bounds->mStartTime;
+		endTime = bounds->mEndTime;
+		UInt32 newPtr = bounds->mUpdateCounter;
+		
+		if (newPtr == curPtr) 
+			return kCARingBufferError_OK;
+	}
+	return kCARingBufferError_CPUOverload;
+}
+
+CARingBufferError	CARingBuffer::ClipTimeBounds(SampleTime& startRead, SampleTime& endRead)
+{
+	SampleTime startTime, endTime;
+	
+	CARingBufferError err = GetTimeBounds(startTime, endTime);
+	if (err) return err;
+	
+	if (startRead > endTime || endRead < startTime) {
+		endRead = startRead;
+		return kCARingBufferError_OK;
+	}
+	
+	startRead = std::max(startRead, startTime);
+	endRead = std::min(endRead, endTime);
+	endRead = std::max(endRead, startRead);
+		
+	return kCARingBufferError_OK;	// success
+}
+
+CARingBufferError	CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead)
+{
+	if (nFrames == 0)
+		return kCARingBufferError_OK;
+		
+	startRead = std::max(0LL, startRead);
+	
+	SampleTime endRead = startRead + nFrames;
+
+	SampleTime startRead0 = startRead;
+	SampleTime endRead0 = endRead;
+
+	CARingBufferError err = ClipTimeBounds(startRead, endRead);
+	if (err) return err;
+
+	if (startRead == endRead) {
+		ZeroABL(abl, 0, nFrames * mBytesPerFrame);
+		return kCARingBufferError_OK;
+	}
+	
+	SInt32 byteSize = (SInt32)((endRead - startRead) * mBytesPerFrame);
+	
+	SInt32 destStartByteOffset = std::max((SInt32)0, (SInt32)((startRead - startRead0) * mBytesPerFrame)); 
+		
+	if (destStartByteOffset > 0) {
+		ZeroABL(abl, 0, std::min((SInt32)(nFrames * mBytesPerFrame), destStartByteOffset));
+	}
+
+	SInt32 destEndSize = std::max((SInt32)0, (SInt32)(endRead0 - endRead)); 
+	if (destEndSize > 0) {
+		ZeroABL(abl, destStartByteOffset + byteSize, destEndSize * mBytesPerFrame);
+	}
+	
+	Byte **buffers = mBuffers;
+	int offset0 = FrameOffset(startRead);
+	int offset1 = FrameOffset(endRead);
+	int nbytes;
+	
+	if (offset0 < offset1) {
+		nbytes = offset1 - offset0;
+		FetchABL(abl, destStartByteOffset, buffers, offset0, nbytes);
+	} else {
+		nbytes = mCapacityBytes - offset0;
+		FetchABL(abl, destStartByteOffset, buffers, offset0, nbytes);
+		FetchABL(abl, destStartByteOffset + nbytes, buffers, 0, offset1);
+		nbytes += offset1;
+	}
+
+	int nchannels = abl->mNumberBuffers;
+	AudioBuffer *dest = abl->mBuffers;
+	while (--nchannels >= 0)
+	{
+		dest->mDataByteSize = nbytes;
+		dest++;
+	}
+
+	return noErr;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h
new file mode 100644
index 0000000..9569e9a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h
@@ -0,0 +1,126 @@
+/*
+     File: CARingBuffer.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+
+#ifndef CARingBuffer_Header
+#define CARingBuffer_Header
+
+enum {
+	kCARingBufferError_OK = 0,
+	kCARingBufferError_TooMuch = 3, // fetch start time is earlier than buffer start time and fetch end time is later than buffer end time
+	kCARingBufferError_CPUOverload = 4 // the reader is unable to get enough CPU cycles to capture a consistent snapshot of the time bounds
+};
+
+typedef SInt32 CARingBufferError;
+
+const UInt32 kGeneralRingTimeBoundsQueueSize = 32;
+const UInt32 kGeneralRingTimeBoundsQueueMask = kGeneralRingTimeBoundsQueueSize - 1;
+
+class CARingBuffer {
+public:
+	typedef SInt64 SampleTime;
+
+	CARingBuffer();
+	~CARingBuffer();
+	
+	void					Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames);
+								// capacityFrames will be rounded up to a power of 2
+	void					Deallocate();
+	
+	CARingBufferError	Store(const AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber);
+							// Copy nFrames of data into the ring buffer at the specified sample time.
+							// The sample time should normally increase sequentially, though gaps
+							// are filled with zeroes. A sufficiently large gap effectively empties
+							// the buffer before storing the new data. 
+							
+							// If frameNumber is less than the previous frame number, the behavior is undefined.
+							
+							// Return false for failure (buffer not large enough).
+				
+	CARingBufferError	Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber);
+								// will alter mNumDataBytes of the buffers
+	
+	CARingBufferError	GetTimeBounds(SampleTime &startTime, SampleTime &endTime);
+	
+protected:
+
+	int						FrameOffset(SampleTime frameNumber) { return (frameNumber & mCapacityFramesMask) * mBytesPerFrame; }
+
+	CARingBufferError		ClipTimeBounds(SampleTime& startRead, SampleTime& endRead);
+	
+	// these should only be called from Store.
+	SampleTime				StartTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mStartTime; }
+	SampleTime				EndTime()   const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mEndTime; }
+	void					SetTimeBounds(SampleTime startTime, SampleTime endTime);
+	
+protected:
+	Byte **					mBuffers;				// allocated in one chunk of memory
+	int						mNumberChannels;
+	UInt32					mBytesPerFrame;			// within one deinterleaved channel
+	UInt32					mCapacityFrames;		// per channel, must be a power of 2
+	UInt32					mCapacityFramesMask;
+	UInt32					mCapacityBytes;			// per channel
+	
+	// range of valid sample time in the buffer
+	typedef struct {
+		volatile SampleTime		mStartTime;
+		volatile SampleTime		mEndTime;
+		volatile UInt32			mUpdateCounter;
+	} TimeBounds;
+	
+	CARingBuffer::TimeBounds mTimeBoundsQueue[kGeneralRingTimeBoundsQueueSize];
+	UInt32 mTimeBoundsQueuePtr;
+};
+
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp
new file mode 100644
index 0000000..69bdffc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp
@@ -0,0 +1,737 @@
+/*
+     File: CASettingsStorage.cpp
+ Abstract: CASettingsStorage.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CASettingsStorage.h"
+
+//	PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CACFArray.h"
+#include "CACFData.h"
+#include "CACFDictionary.h"
+#include "CACFDistributedNotification.h"
+#include "CACFNumber.h"
+
+//	Stamdard Library Includes
+#include <string.h>
+#include <sys/fcntl.h>
+
+//==================================================================================================
+//	CASettingsStorage
+//==================================================================================================
+
+CASettingsStorage::CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode, CFPropertyListFormat inSettingsCacheFormat, bool inIsSingleProcessOnly, bool inIsReadOnly)
+:
+	mSettingsFilePath(NULL),
+	mSettingsFileAccessMode(inSettingsFileAccessMode),
+	mSettingsCache(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)),
+	mSettingsCacheFormat(inSettingsCacheFormat),
+	mSettingsCacheTime(),
+	mSettingsCacheForceRefresh(true),
+	mIsSingleProcessOnly(inIsSingleProcessOnly),
+	mIsReadOnly(inIsReadOnly)
+{
+	size_t theLength = strlen(inSettingsFilePath);
+	mSettingsFilePath = new char[theLength + 2];
+	strlcpy(mSettingsFilePath, inSettingsFilePath, theLength + 2);
+	
+	mSettingsCacheTime.tv_sec = 0;
+	mSettingsCacheTime.tv_nsec = 0;
+	
+	mSettingsCacheForceRefresh = true;
+}
+
+CASettingsStorage::~CASettingsStorage()
+{
+	delete[] mSettingsFilePath;
+	
+	if(mSettingsCache != NULL)
+	{
+		CFRelease(mSettingsCache);
+	}
+}
+
+UInt32	CASettingsStorage::GetNumberKeys() const
+{
+	//	make sure our cache is up to date
+	const_cast<CASettingsStorage*>(this)->RefreshSettings();
+
+	return ToUInt32(CFDictionaryGetCount(mSettingsCache));
+}
+
+void	CASettingsStorage::GetKeys(UInt32 inNumberKeys, UInt32& outNumberKeys, CFStringRef* outKeys) const
+{
+	//	make sure our cache is up to date
+	const_cast<CASettingsStorage*>(this)->RefreshSettings();
+
+	CFDictionaryGetKeysAndValues(mSettingsCache, reinterpret_cast<const void**>(outKeys), NULL);
+	outNumberKeys = inNumberKeys;
+}
+
+void	CASettingsStorage::CopyBoolValue(CFStringRef inKey, bool& outValue, bool inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = inDefaultValue;
+	
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, NULL);
+	
+	//	for this type, NULL is an invalid value
+	if(theValue != NULL)
+	{
+		//	bools can be made from either CFBooleans or CFNumbers
+		if(CFGetTypeID(theValue) == CFBooleanGetTypeID())
+		{
+			//	get the return value from the CF object
+			outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+		}
+		else if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	get the numeric value
+			SInt32 theNumericValue = 0;
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+			
+			//	non-zero indicates true
+			outValue = theNumericValue != 0;
+		}
+		
+		//	release the value since we aren't returning it
+		CFRelease(theValue);
+	}
+}
+
+void	CASettingsStorage::CopySInt32Value(CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = inDefaultValue;
+	
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, NULL);
+	
+	//	for this type, NULL is an invalid value
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	get the return value from the CF object
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+		}
+		
+		//	release the value since we aren't returning it
+		CFRelease(theValue);
+	}
+}
+
+void	CASettingsStorage::CopyUInt32Value(CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = inDefaultValue;
+	
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, NULL);
+	
+	//	for this type, NULL is an invalid value
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	get the return value from the CF object
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+		}
+		
+		//	release the value since we aren't returning it
+		CFRelease(theValue);
+	}
+}
+
+void	CASettingsStorage::CopySInt64Value(CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = inDefaultValue;
+	
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, NULL);
+	
+	//	for this type, NULL is an invalid value
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	get the return value from the CF object
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+		}
+		
+		//	release the value since we aren't returning it
+		CFRelease(theValue);
+	}
+}
+
+void	CASettingsStorage::CopyUInt64Value(CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = inDefaultValue;
+	
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, NULL);
+	
+	//	for this type, NULL is an invalid value
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	get the return value from the CF object
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+		}
+		
+		//	release the value since we aren't returning it
+		CFRelease(theValue);
+	}
+}
+
+void	CASettingsStorage::CopyFloat32Value(CFStringRef inKey, Float32& outValue, Float32 inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = inDefaultValue;
+	
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, NULL);
+	
+	//	for this type, NULL is an invalid value
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	get the return value from the CF object
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
+		}
+		
+		//	release the value since we aren't returning it
+		CFRelease(theValue);
+	}
+}
+
+void	CASettingsStorage::CopyFloat64Value(CFStringRef inKey, Float64& outValue, Float64 inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = inDefaultValue;
+	
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, NULL);
+	
+	//	for this type, NULL is an invalid value
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	get the return value from the CF object
+			CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
+		}
+		
+		//	release the value since we aren't returning it
+		CFRelease(theValue);
+	}
+}
+
+void	CASettingsStorage::CopyNumberValue(CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = NULL;
+
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, inDefaultValue);
+	
+	//	for this type, NULL is a valid value, but requires less work
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+		{
+			//	set the return value to the CF object we are returning
+			outValue = static_cast<CFNumberRef>(theValue);
+		}
+		else
+		{
+			//	release the value since we aren't returning it
+			CFRelease(theValue);
+			
+			//	set the return value to the default value
+			outValue = inDefaultValue;
+			
+			//	and retain it
+			CFRetain(outValue);
+		}
+	}
+}
+	
+void	CASettingsStorage::CopyStringValue(CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = NULL;
+
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, inDefaultValue);
+	
+	//	for this type, NULL is a valid value, but requires less work
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFStringGetTypeID())
+		{
+			//	set the return value to the CF object we are returning
+			outValue = static_cast<CFStringRef>(theValue);
+		}
+		else
+		{
+			//	release the value since we aren't returning it
+			CFRelease(theValue);
+			
+			//	set the return value to the default value
+			outValue = inDefaultValue;
+			
+			//	and retain it
+			CFRetain(outValue);
+		}
+	}
+}
+	
+void	CASettingsStorage::CopyArrayValue(CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = NULL;
+
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, inDefaultValue);
+	
+	//	for this type, NULL is a valid value, but requires less work
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFArrayGetTypeID())
+		{
+			//	set the return value to the CF object we are returning
+			outValue = static_cast<CFArrayRef>(theValue);
+		}
+		else
+		{
+			//	release the value since we aren't returning it
+			CFRelease(theValue);
+			
+			//	set the return value to the default value
+			outValue = inDefaultValue;
+			
+			//	and retain it
+			CFRetain(outValue);
+		}
+	}
+}
+	
+void	CASettingsStorage::CopyDictionaryValue(CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = NULL;
+
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, inDefaultValue);
+	
+	//	for this type, NULL is a valid value, but requires less work
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFDictionaryGetTypeID())
+		{
+			//	set the return value to the CF object we are returning
+			outValue = static_cast<CFDictionaryRef>(theValue);
+		}
+		else
+		{
+			//	release the value since we aren't returning it
+			CFRelease(theValue);
+			
+			//	set the return value to the default value
+			outValue = inDefaultValue;
+			
+			//	and retain it
+			CFRetain(outValue);
+		}
+	}
+}
+	
+void	CASettingsStorage::CopyDataValue(CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue) const
+{
+	//	initialize the return value
+	outValue = NULL;
+
+	//	get the raw value
+	CFTypeRef theValue = NULL;
+	CopyCFTypeValue(inKey, theValue, inDefaultValue);
+	
+	//	for this type, NULL is a valid value, but requires less work
+	if(theValue != NULL)
+	{
+		//	make sure we are dealing with the right kind of CF object
+		if(CFGetTypeID(theValue) == CFDataGetTypeID())
+		{
+			//	set the return value to the CF object we are returning
+			outValue = static_cast<CFDataRef>(theValue);
+		}
+		else
+		{
+			//	release the value since we aren't returning it
+			CFRelease(theValue);
+			
+			//	set the return value to the default value
+			outValue = inDefaultValue;
+			
+			//	and retain it
+			CFRetain(outValue);
+		}
+	}
+}
+
+void	CASettingsStorage::CopyCFTypeValue(CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue) const
+{
+	//	make sure our cache is up to date
+	const_cast<CASettingsStorage*>(this)->RefreshSettings();
+
+	//	check to see if we have a value for the given key
+	if(!CFDictionaryGetValueIfPresent(mSettingsCache, inKey, &outValue))
+	{
+		//	the key wasn't in the cache, so return the default value
+		outValue = inDefaultValue;
+	}
+		
+	//	make sure we retain the return value
+	if(outValue != NULL)
+	{
+		CFRetain(outValue);
+	}
+}
+
+void	CASettingsStorage::SetSInt32Value(CFStringRef inKey, SInt32 inValue)
+{
+	CACFNumber theValue(inValue);
+	SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void	CASettingsStorage::SetUInt32Value(CFStringRef inKey, UInt32 inValue)
+{
+	CACFNumber theValue(inValue);
+	SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void	CASettingsStorage::SetSInt64Value(CFStringRef inKey, SInt64 inValue)
+{
+	CACFNumber theValue(inValue);
+	SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void	CASettingsStorage::SetUInt64Value(CFStringRef inKey, UInt64 inValue)
+{
+	CACFNumber theValue(inValue);
+	SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void	CASettingsStorage::SetFloat32Value(CFStringRef inKey, Float32 inValue)
+{
+	CACFNumber theValue(inValue);
+	SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void	CASettingsStorage::SetFloat64Value(CFStringRef inKey, Float64 inValue)
+{
+	CACFNumber theValue(inValue);
+	SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void	CASettingsStorage::SetNumberValue(CFStringRef inKey, CFNumberRef inValue)
+{
+	SetCFTypeValue(inKey, inValue);
+}
+
+void	CASettingsStorage::SetStringValue(CFStringRef inKey, CFStringRef inValue)
+{
+	SetCFTypeValue(inKey, inValue);
+}
+
+void	CASettingsStorage::SetArrayValue(CFStringRef inKey, CFArrayRef inValue)
+{
+	SetCFTypeValue(inKey, inValue);
+}
+
+void	CASettingsStorage::SetDictionaryValue(CFStringRef inKey, CFDictionaryRef inValue)
+{
+	SetCFTypeValue(inKey, inValue);
+}
+
+void	CASettingsStorage::SetDataValue(CFStringRef inKey, CFDataRef inValue)
+{
+	SetCFTypeValue(inKey, inValue);
+}
+
+void	CASettingsStorage::SetCFTypeValue(CFStringRef inKey, CFTypeRef inValue)
+{
+	//	make sure our cache is up to date
+	RefreshSettings();
+	
+	//	add the new key/value to the dictionary
+	CFDictionarySetValue(mSettingsCache, inKey, inValue);
+	
+	//	write the settings to the file
+	SaveSettings();
+}
+
+void	CASettingsStorage::RemoveValue(CFStringRef inKey)
+{
+	//	make sure our cache is up to date
+	RefreshSettings();
+	
+	//	remove the given key
+	CFDictionaryRemoveValue(mSettingsCache, inKey);
+	
+	//	write the settings to the file
+	SaveSettings();
+}
+
+void	CASettingsStorage::RemoveAllValues()
+{
+	//	make sure our cache is up to date
+	RefreshSettings();
+	
+	//	remove the given key
+	CFDictionaryRemoveAllValues(mSettingsCache);
+	
+	//	write the settings to the file
+	SaveSettings();
+}
+
+void	CASettingsStorage::SendNotification(CFStringRef inName, CFDictionaryRef inData, bool inPostToAllSessions) const
+{
+	CACFDistributedNotification::PostNotification(inName, inData, inPostToAllSessions);
+}
+
+void	CASettingsStorage::ForceRefresh()
+{
+	mSettingsCacheForceRefresh = true;
+}
+
+inline bool	operator<(const struct timespec& inX, const struct timespec& inY)
+{
+	return ((inX.tv_sec < inY.tv_sec) || ((inX.tv_sec == inY.tv_sec) && (inX.tv_nsec < inY.tv_nsec)));
+}
+
+void	CASettingsStorage::RefreshSettings()
+{
+	//	if this storage is only supporting a single process, there is no need to hit the disk unless
+	//	required to by it being the first time or if the refresh is specifically forced for some reason
+	if(!mIsSingleProcessOnly || (mSettingsCache == NULL) || ((mSettingsCacheTime.tv_sec == 0) && (mSettingsCacheTime.tv_nsec == 0)) || mSettingsCacheForceRefresh)
+	{
+		//	first, we need to stat the file to check the mod date, this has the side effect of also
+		//	telling us if the file exisits
+		struct stat theFileInfo;
+		int theStatError = stat(mSettingsFilePath, &theFileInfo);
+		
+		//	we use this boolean to make error recovery easier since we need a case for when there's no file anyway
+		bool theSettingsWereCached = false;
+		bool theSettingsNeedSaving = true;
+		
+		if(theStatError == 0)
+		{
+			//	stat says there is something there, only have to do work if we either don't have a cache or the cache is out of date
+			if((mSettingsCache == NULL) || (mSettingsCacheTime < theFileInfo.st_mtimespec) || mSettingsCacheForceRefresh)
+			{
+				//	open the file
+				FILE* theFile = fopen(mSettingsFilePath, "r");
+				if(theFile != NULL)
+				{
+					//	lock the file (this call blocks until the lock is taken)
+					int theError = flock(fileno(theFile), LOCK_EX);
+					if(theError == 0)
+					{
+						//	get the length of the file
+						fseek(theFile, 0, SEEK_END);
+						size_t theFileLength = static_cast<size_t>(ftell(theFile));
+						fseek(theFile, 0, SEEK_SET);
+						
+						if(theFileLength > 0)
+						{
+							//	allocate a block of memory to hold the data in the file
+							CAAutoFree<Byte> theRawFileData(theFileLength);
+							
+							//	read all the data in
+							fread(static_cast<Byte*>(theRawFileData), theFileLength, 1, theFile);
+							
+							//	release the lock
+							flock(fileno(theFile), LOCK_UN);
+							
+							//	put it into a CFData object
+							CACFData theRawFileDataCFData(static_cast<Byte*>(theRawFileData), static_cast<UInt32>(theFileLength));
+							
+							//	get rid of the existing cache
+							if(mSettingsCache != NULL)
+							{
+								CFRelease(mSettingsCache);
+								mSettingsCache = NULL;
+							}
+							
+							//	parse the data as a property list
+							mSettingsCache = (CFMutableDictionaryRef)CFPropertyListCreateWithData(NULL, theRawFileDataCFData.GetCFData(), kCFPropertyListMutableContainersAndLeaves, NULL, NULL);
+							
+							//	check to be sure we parsed a plist out of the file
+							if(mSettingsCache != NULL)
+							{
+								//	save the date of the cache
+								mSettingsCacheTime = theFileInfo.st_mtimespec;
+								
+								//	mark that we're done
+								theSettingsWereCached = true;
+								theSettingsNeedSaving = false;
+							}
+						}
+					}
+					
+					//	close the file
+					fclose(theFile);
+					mSettingsCacheForceRefresh = false;
+				}
+			}
+			else
+			{
+				//	nothing to do since the file was older than the cached data
+				theSettingsNeedSaving = false;
+				theSettingsWereCached = true;
+			}
+		}
+		
+		//	if there was a failure, we need to clean up 
+		if((theStatError != 0) || theSettingsNeedSaving || !theSettingsWereCached)
+		{
+			//	we get here if either there isn't a file or something wacky happenned while parsing it
+			//	so, make sure we have a valid cache dictionary
+			if(mSettingsCache == NULL)
+			{
+				mSettingsCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+			}
+			
+			mSettingsCacheTime.tv_sec = 0;
+			mSettingsCacheTime.tv_nsec = 0;
+			
+			if((theStatError != 0) || theSettingsNeedSaving)
+			{
+				SaveSettings();
+			}
+		}
+	}
+}
+
+void	CASettingsStorage::SaveSettings()
+{
+	if(!mIsReadOnly && (mSettingsCache != NULL))
+	{
+		//	make a CFData that contains the new settings
+		CACFData theNewRawPrefsCFData(CFPropertyListCreateData(NULL, mSettingsCache, mSettingsCacheFormat, 0, NULL), true);
+		
+		//	open the file for writing
+		FILE* theFile = fopen(mSettingsFilePath, "w+");
+		if(theFile != NULL)
+		{
+			//	lock the file (this call blocks until the lock is taken)
+			int theError = flock(fileno(theFile), LOCK_EX);
+			if(theError == 0)
+			{
+				//	set the file access mode if necessary
+				if(mSettingsFileAccessMode != 0)
+				{
+					fchmod(fileno(theFile), mSettingsFileAccessMode);
+				}
+				
+				//	write the data
+				fwrite(theNewRawPrefsCFData.GetDataPtr(), theNewRawPrefsCFData.GetSize(), 1, theFile);
+				
+				//	flush the file to be sure it is all on disk
+				fflush(theFile);
+				
+				//	release the lock
+				flock(fileno(theFile), LOCK_UN);
+			
+				//	close the file
+				fclose(theFile);
+				
+				//	stat the file to get the mod date
+				struct stat theFileInfo;
+				stat(mSettingsFilePath, &theFileInfo);
+				
+				//	save the mod date
+				mSettingsCacheTime = theFileInfo.st_mtimespec;
+			}
+			else
+			{
+				//	close the file
+				fclose(theFile);
+			}
+		}
+	}
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h
new file mode 100644
index 0000000..d15f87d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h
@@ -0,0 +1,128 @@
+/*
+     File: CASettingsStorage.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CASettingsStorage_h__)
+#define __CASettingsStorage_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+//	Stamdard Library Includes
+#include <stdio.h>
+#include <sys/stat.h>
+
+//==================================================================================================
+//	CASettingsStorage
+//==================================================================================================
+
+class CASettingsStorage
+{
+
+//	Construction/Destruction
+public:
+							CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode = 0, CFPropertyListFormat inSettingsCacheFormat = kCFPropertyListXMLFormat_v1_0, bool inIsSingleProcessOnly = false, bool inIsReadOnly = false);
+							~CASettingsStorage();
+
+//	Operations
+public:
+	UInt32					GetNumberKeys() const;
+	void					GetKeys(UInt32 inNumberKeys, UInt32& outNumberKeys, CFStringRef* outKeys) const;
+
+	void					CopyBoolValue(const CFStringRef inKey, bool& outValue, bool inDefaultValue = false) const;
+	void					CopySInt32Value(const CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue = 0) const;
+	void					CopyUInt32Value(const CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue = 0) const;
+	void					CopySInt64Value(const CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue = 0) const;
+	void					CopyUInt64Value(const CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue = 0) const;
+	void					CopyFloat32Value(const CFStringRef inKey, Float32& outValue, Float32 inDefaultValue = 0) const;
+	void					CopyFloat64Value(const CFStringRef inKey, Float64& outValue, Float64 inDefaultValue = 0) const;
+	void					CopyNumberValue(const CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue = NULL) const;	
+	void					CopyStringValue(const CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue = NULL) const;	
+	void					CopyArrayValue(const CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue = NULL) const;	
+	void					CopyDictionaryValue(const CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue = NULL) const;	
+	void					CopyDataValue(const CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue = NULL) const;
+	void					CopyCFTypeValue(const CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue = NULL) const;
+	
+	void					SetSInt32Value(const CFStringRef inKey, SInt32 inValue);
+	void					SetUInt32Value(const CFStringRef inKey, UInt32 inValue);
+	void					SetSInt64Value(const CFStringRef inKey, SInt64 inValue);
+	void					SetUInt64Value(const CFStringRef inKey, UInt64 inValue);
+	void					SetFloat32Value(const CFStringRef inKey, Float32 inValue);
+	void					SetFloat64Value(const CFStringRef inKey, Float64 inValue);
+	void					SetNumberValue(const CFStringRef inKey, const CFNumberRef inValue);
+	void					SetStringValue(const CFStringRef inKey, const CFStringRef inValue);
+	void					SetArrayValue(const CFStringRef inKey, const CFArrayRef inValue);
+	void					SetDictionaryValue(const CFStringRef inKey, const CFDictionaryRef inValue);
+	void					SetDataValue(const CFStringRef inKey, const CFDataRef inValue);
+	void					SetCFTypeValue(const CFStringRef inKey, const CFTypeRef inValue);
+	
+	void					RemoveValue(const CFStringRef inKey);
+	void					RemoveAllValues();
+	
+	void					SendNotification(const CFStringRef inName, CFDictionaryRef inData = NULL, bool inPostToAllSessions = true) const;
+	void					ForceRefresh();
+
+//	Implementation
+private:
+	void					RefreshSettings();
+	void					SaveSettings();
+
+	char*					mSettingsFilePath;
+	mode_t					mSettingsFileAccessMode;
+	CFMutableDictionaryRef	mSettingsCache;
+	CFPropertyListFormat	mSettingsCacheFormat;
+	struct timespec			mSettingsCacheTime;
+	bool					mSettingsCacheForceRefresh;
+	bool					mIsSingleProcessOnly;
+	bool					mIsReadOnly;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp
new file mode 100644
index 0000000..0e39ac7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp
@@ -0,0 +1,118 @@
+/*
+     File: CASharedLibrary.cpp
+ Abstract: CASharedLibrary.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CASharedLibrary.h"
+
+//#define	CASharedLibrary_Use_DYLD	1
+#if	CASharedLibrary_Use_DYLD
+	#include <mach-o/dyld.h>
+#else
+	#include <dlfcn.h>
+	#include <stddef.h>
+#endif
+
+//=============================================================================
+//	CASharedLibrary
+//=============================================================================
+
+void*	CASharedLibrary::LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath)
+{
+	void* theRoutine = 0;
+
+#if	CASharedLibrary_Use_DYLD
+	const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+	if(theImage != 0)
+	{
+		NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+		if(theSymbol != 0)
+		{
+			theRoutine = NSAddressOfSymbol(theSymbol);
+		}
+	}
+#else
+	void* theImage = dlopen(inLibraryPath, RTLD_LAZY);
+	if(theImage != NULL)
+	{
+		//	we assume that all routine names passed here have a leading underscore which gets shaved
+		//	off when passed to dlsym
+		theRoutine = dlsym(theImage, &(inRoutineName[1]));
+	}
+	
+#endif
+
+	return theRoutine;
+}
+
+void*	CASharedLibrary::GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath)
+{
+	void* theRoutine = 0;
+		
+#if	CASharedLibrary_Use_DYLD
+	const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED);
+	if(theImage != 0)
+	{
+		NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+		if(theSymbol != 0)
+		{
+			theRoutine = NSAddressOfSymbol(theSymbol);
+		}
+	}
+#else
+	void* theImage = dlopen(inLibraryPath, RTLD_LAZY | RTLD_NOLOAD);
+	if(theImage != NULL)
+	{
+		//	we assume that all routine names passed here have a leading underscore which gets shaved
+		//	off when passed to dlsym
+		theRoutine = dlsym(theImage, &(inRoutineName[1]));
+	}
+#endif
+
+	return theRoutine;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h
new file mode 100644
index 0000000..d02e70e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h
@@ -0,0 +1,64 @@
+/*
+     File: CASharedLibrary.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CASharedLibrary_h__)
+#define __CASharedLibrary_h__
+
+//=============================================================================
+//	CASharedLibrary
+//=============================================================================
+
+class CASharedLibrary
+{
+
+//	Symbol Operations
+public:
+	static void*	LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath);
+	static void*	GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath);
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp
new file mode 100644
index 0000000..ffb2da8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp
@@ -0,0 +1,376 @@
+/*
+     File: CASpectralProcessor.cpp
+ Abstract: CASpectralProcessor.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+ 
+//#include "AudioFormulas.h"
+#include "CASpectralProcessor.h"
+#include "CABitOperations.h"
+
+
+#include <Accelerate/Accelerate.h>
+
+
+#define OFFSETOF(class, field)((size_t)&((class*)0)->field)
+
+CASpectralProcessor::CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames)
+	: mFFTSize(inFFTSize), mHopSize(inHopSize), mNumChannels(inNumChannels), mMaxFrames(inMaxFrames),
+	mLog2FFTSize(Log2Ceil(mFFTSize)), 
+	mFFTMask(mFFTSize - 1),
+	mFFTByteSize(mFFTSize * sizeof(Float32)),
+	mIOBufSize(NextPowerOfTwo(mFFTSize + mMaxFrames)),
+	mIOMask(mIOBufSize - 1),
+	mInputSize(0),
+	mInputPos(0), mOutputPos(-mFFTSize & mIOMask), 
+	mInFFTPos(0), mOutFFTPos(0),
+	mSpectralFunction(0), mUserData(0)
+{
+	mWindow.alloc(mFFTSize, false);
+	SineWindow(); // set default window.
+	
+	mChannels.alloc(mNumChannels);
+	mSpectralBufferList.allocBytes(OFFSETOF(SpectralBufferList, mDSPSplitComplex[mNumChannels]), true);
+	mSpectralBufferList->mNumberSpectra = mNumChannels;
+	for (UInt32 i = 0; i < mNumChannels; ++i) 
+	{
+		mChannels[i].mInputBuf.alloc(mIOBufSize, true);
+		mChannels[i].mOutputBuf.alloc(mIOBufSize, true);
+		mChannels[i].mFFTBuf.alloc(mFFTSize, true);
+		mChannels[i].mSplitFFTBuf.alloc(mFFTSize, true);
+		mSpectralBufferList->mDSPSplitComplex[i].realp = mChannels[i].mSplitFFTBuf();
+		mSpectralBufferList->mDSPSplitComplex[i].imagp = mChannels[i].mSplitFFTBuf() + (mFFTSize >> 1);
+	}
+
+	mFFTSetup = vDSP_create_fftsetup (mLog2FFTSize, FFT_RADIX2);
+	
+}
+
+CASpectralProcessor::~CASpectralProcessor()
+{
+	mWindow.free();
+	mChannels.free();
+	mSpectralBufferList.free();
+	vDSP_destroy_fftsetup(mFFTSetup);
+}
+
+void CASpectralProcessor::Reset()
+{
+	mInputPos = 0;
+	mOutputPos = -mFFTSize & mIOMask;
+	mInFFTPos = 0;
+	mOutFFTPos = 0;
+	
+	for (UInt32 i = 0; i < mNumChannels; ++i) 
+	{
+		memset(mChannels[i].mInputBuf(), 0, mIOBufSize * sizeof(Float32));
+		memset(mChannels[i].mOutputBuf(), 0, mIOBufSize * sizeof(Float32));
+		memset(mChannels[i].mFFTBuf(), 0, mFFTSize * sizeof(Float32));
+	}
+}
+
+const double two_pi = 2. * M_PI;
+
+void CASpectralProcessor::HanningWindow()
+{ 
+	// this is also vector optimized
+
+	double w = two_pi / (double)(mFFTSize - 1);
+	for (UInt32 i = 0; i < mFFTSize; ++i)
+	{
+		mWindow[i] = (0.5 - 0.5 * cos(w * (double)i));	
+	}
+}
+
+void CASpectralProcessor::SineWindow()
+{
+	double w = M_PI / (double)(mFFTSize - 1);
+	for (UInt32 i = 0; i < mFFTSize; ++i)
+	{
+		mWindow[i] = sin(w * (double)i);
+	}
+}
+
+void CASpectralProcessor::Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput)
+{
+	// copy from buffer list to input buffer
+	CopyInput(inNumFrames, inInput);
+	
+	// if enough input to process, then process.
+	while (mInputSize >= mFFTSize) 
+	{
+		CopyInputToFFT(); // copy from input buffer to fft buffer
+		DoWindowing();
+		DoFwdFFT();
+		ProcessSpectrum(mFFTSize, mSpectralBufferList());
+		DoInvFFT();
+		DoWindowing();
+		OverlapAddOutput();
+	}
+
+	// copy from output buffer to buffer list
+	CopyOutput(inNumFrames, outOutput);
+}
+
+void CASpectralProcessor::DoWindowing()
+{
+	Float32 *win = mWindow();
+	if (!win) return;
+	for (UInt32 i=0; i<mNumChannels; ++i) {
+		Float32 *x = mChannels[i].mFFTBuf();
+		vDSP_vmul(x, 1, win, 1, x, 1, mFFTSize);
+	}
+	//printf("DoWindowing %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+
+
+void CASpectralProcessor::CopyInput(UInt32 inNumFrames, AudioBufferList* inInput)
+{
+	UInt32 numBytes = inNumFrames * sizeof(Float32);
+	UInt32 firstPart = mIOBufSize - mInputPos;
+	
+
+	if (firstPart < inNumFrames) {
+		UInt32 firstPartBytes = firstPart * sizeof(Float32);
+		UInt32 secondPartBytes = numBytes - firstPartBytes;
+		for (UInt32 i=0; i<mNumChannels; ++i) {		
+			memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, firstPartBytes);
+			memcpy(mChannels[i].mInputBuf, (UInt8*)inInput->mBuffers[i].mData + firstPartBytes, secondPartBytes);
+		}
+	} else {
+		UInt32 numBytes = inNumFrames * sizeof(Float32);
+		for (UInt32 i=0; i<mNumChannels; ++i) {		
+			memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, numBytes);
+		}
+	}
+	//printf("CopyInput %g %g\n", mChannels[0].mInputBuf[mInputPos], mChannels[0].mInputBuf[(mInputPos + 200) & mIOMask]);
+	//printf("CopyInput mInputPos %u   mIOBufSize %u\n", (unsigned)mInputPos, (unsigned)mIOBufSize);
+	mInputSize += inNumFrames;
+	mInputPos = (mInputPos + inNumFrames) & mIOMask;
+}
+
+void CASpectralProcessor::CopyOutput(UInt32 inNumFrames, AudioBufferList* outOutput)
+{
+	//printf("->CopyOutput %g %g\n", mChannels[0].mOutputBuf[mOutputPos], mChannels[0].mOutputBuf[(mOutputPos + 200) & mIOMask]);
+	//printf("CopyOutput mOutputPos %u\n", (unsigned)mOutputPos);
+	UInt32 numBytes = inNumFrames * sizeof(Float32);
+	UInt32 firstPart = mIOBufSize - mOutputPos;
+	if (firstPart < inNumFrames) {
+		UInt32 firstPartBytes = firstPart * sizeof(Float32);
+		UInt32 secondPartBytes = numBytes - firstPartBytes;
+		for (UInt32 i=0; i<mNumChannels; ++i) {
+			memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, firstPartBytes);
+			memcpy((UInt8*)outOutput->mBuffers[i].mData + firstPartBytes, mChannels[i].mOutputBuf, secondPartBytes);
+			memset(mChannels[i].mOutputBuf + mOutputPos, 0, firstPartBytes);
+			memset(mChannels[i].mOutputBuf, 0, secondPartBytes);
+		}
+	} else {
+		for (UInt32 i=0; i<mNumChannels; ++i) {
+			memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, numBytes);
+			memset(mChannels[i].mOutputBuf + mOutputPos, 0, numBytes);
+		}
+	}
+	//printf("<-CopyOutput %g %g\n", ((Float32*)outOutput->mBuffers[0].mData)[0], ((Float32*)outOutput->mBuffers[0].mData)[200]);
+	mOutputPos = (mOutputPos + inNumFrames) & mIOMask;
+}
+
+void CASpectralProcessor::PrintSpectralBufferList()
+{
+	UInt32 half = mFFTSize >> 1;
+	for (UInt32 i=0; i<mNumChannels; ++i) {
+		DSPSplitComplex	&freqData = mSpectralBufferList->mDSPSplitComplex[i];
+	
+		for (UInt32 j=0; j<half; j++){
+			printf(" bin[%d]: %lf + %lfi\n", (int) j, freqData.realp[j], freqData.imagp[j]);
+		}
+	}
+}
+
+
+void CASpectralProcessor::CopyInputToFFT()
+{
+	//printf("CopyInputToFFT mInFFTPos %u\n", (unsigned)mInFFTPos);
+	UInt32 firstPart = mIOBufSize - mInFFTPos;
+	UInt32 firstPartBytes = firstPart * sizeof(Float32);
+	if (firstPartBytes < mFFTByteSize) {
+		UInt32 secondPartBytes = mFFTByteSize - firstPartBytes;
+		for (UInt32 i=0; i<mNumChannels; ++i) {
+			memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, firstPartBytes);
+			memcpy((UInt8*)mChannels[i].mFFTBuf() + firstPartBytes, mChannels[i].mInputBuf(), secondPartBytes);
+		}
+	} else {
+		for (UInt32 i=0; i<mNumChannels; ++i) {
+			memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, mFFTByteSize);
+		}
+	}
+	mInputSize -= mHopSize;
+	mInFFTPos = (mInFFTPos + mHopSize) & mIOMask;
+	//printf("CopyInputToFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::OverlapAddOutput()
+{
+	//printf("OverlapAddOutput mOutFFTPos %u\n", (unsigned)mOutFFTPos);
+	UInt32 firstPart = mIOBufSize - mOutFFTPos;
+	if (firstPart < mFFTSize) {
+		UInt32 secondPart = mFFTSize - firstPart;
+		for (UInt32 i=0; i<mNumChannels; ++i) {
+			float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos;
+			vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, firstPart);
+			float* out2 = mChannels[i].mOutputBuf();
+			vDSP_vadd(out2, 1, mChannels[i].mFFTBuf() + firstPart, 1, out2, 1, secondPart);
+		}
+	} else {
+		for (UInt32 i=0; i<mNumChannels; ++i) {
+			float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos;
+			vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, mFFTSize);
+		}
+	}
+	//printf("OverlapAddOutput %g %g\n", mChannels[0].mOutputBuf[mOutFFTPos], mChannels[0].mOutputBuf[(mOutFFTPos + 200) & mIOMask]);
+	mOutFFTPos = (mOutFFTPos + mHopSize) & mIOMask;
+}
+
+
+void CASpectralProcessor::DoFwdFFT()
+{
+	//printf("->DoFwdFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+	UInt32 half = mFFTSize >> 1;
+	for (UInt32 i=0; i<mNumChannels; ++i) 
+	{
+		vDSP_ctoz((DSPComplex*)mChannels[i].mFFTBuf(), 2, &mSpectralBufferList->mDSPSplitComplex[i], 1, half);
+		vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_FORWARD);
+	}
+	//printf("<-DoFwdFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::DoInvFFT()
+{
+	//printf("->DoInvFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+	UInt32 half = mFFTSize >> 1;
+	for (UInt32 i=0; i<mNumChannels; ++i) 
+	{
+		vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_INVERSE);
+		vDSP_ztoc(&mSpectralBufferList->mDSPSplitComplex[i], 1, (DSPComplex*)mChannels[i].mFFTBuf(), 2, half);		
+		float scale = 0.5 / mFFTSize;
+		vDSP_vsmul(mChannels[i].mFFTBuf(), 1, &scale, mChannels[i].mFFTBuf(), 1, mFFTSize );
+	}
+	//printf("<-DoInvFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::SetSpectralFunction(SpectralFunction inFunction, void* inUserData)
+{
+	mSpectralFunction = inFunction; 
+	mUserData = inUserData;
+}
+
+void CASpectralProcessor::ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra)
+{
+	if (mSpectralFunction)
+		(mSpectralFunction)(inSpectra, mUserData);
+}
+
+#pragma mark ___Utility___
+
+void CASpectralProcessor::GetMagnitude(AudioBufferList* list, Float32* min, Float32* max) 
+{	
+	UInt32 half = mFFTSize >> 1;	
+	for (UInt32 i=0; i<mNumChannels; ++i) {
+		DSPSplitComplex	&freqData = mSpectralBufferList->mDSPSplitComplex[i];		
+		
+		Float32* b = (Float32*) list->mBuffers[i].mData;
+		
+		vDSP_zvabs(&freqData,1,b,1,half); 		
+   
+		vDSP_maxmgv(b, 1, &max[i], half); 
+ 		vDSP_minmgv(b, 1, &min[i], half); 
+		
+   } 
+}
+
+
+void CASpectralProcessor::GetFrequencies(Float32* freqs, Float32 sampleRate)
+{
+	UInt32 half = mFFTSize >> 1;	
+
+	for (UInt32 i=0; i< half; i++){
+		freqs[i] = ((Float32)(i))*sampleRate/((Float32)mFFTSize);	
+	}
+}
+
+
+bool CASpectralProcessor::ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput)
+{
+	// copy from buffer list to input buffer
+	CopyInput(inNumFrames, inInput);
+		
+	bool processed = false;
+	// if enough input to process, then process.
+	while (mInputSize >= mFFTSize) 
+	{
+		CopyInputToFFT(); // copy from input buffer to fft buffer
+		DoWindowing();
+		DoFwdFFT();
+		ProcessSpectrum(mFFTSize, mSpectralBufferList()); // here you would copy the fft results out to a buffer indicated in mUserData, say for sonogram drawing
+		processed = true;
+	}
+	
+	return processed;
+}
+
+bool CASpectralProcessor::ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput)
+{		
+	
+	ProcessSpectrum(mFFTSize, mSpectralBufferList());
+	DoInvFFT();
+	DoWindowing();
+	OverlapAddOutput();		
+	
+	// copy from output buffer to buffer list
+	CopyOutput(inNumFrames, outOutput);
+	
+	return true;
+}
+
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h
new file mode 100644
index 0000000..d7c285b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h
@@ -0,0 +1,146 @@
+/*
+     File: CASpectralProcessor.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef _SpectralProcesor_H_
+#define _SpectralProcesor_H_
+ 
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+#else
+#include <CoreAudioTypes.h>
+#include <CoreFoundation.h>
+#endif
+
+#include <Accelerate/Accelerate.h>
+
+#include "CAAutoDisposer.h"
+
+struct SpectralBufferList
+{
+	UInt32 mNumberSpectra;
+	DSPSplitComplex mDSPSplitComplex[1];
+};
+
+class CASpectralProcessor 
+{
+public:
+	CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames);
+	virtual ~CASpectralProcessor();
+	
+	void Reset();
+	
+	void Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput);
+	
+	typedef void (*SpectralFunction)(SpectralBufferList* inSpectra, void* inUserData);
+	
+	void SetSpectralFunction(SpectralFunction inFunction, void* inUserData);
+	
+	UInt32 FFTSize() const { return mFFTSize; }
+	UInt32 MaxFrames() const { return mMaxFrames; }
+	UInt32 NumChannels() const { return mNumChannels; }
+	UInt32 HopSize() const { return mHopSize; }
+	Float32* Window() const { return mWindow; }
+	
+	
+	void HanningWindow(); // set up a hanning window
+	void SineWindow();
+	
+	void GetFrequencies(Float32* freqs, Float32 sampleRate);				// only for processed forward
+	void GetMagnitude(AudioBufferList* inCopy, Float32* min, Float32* max); // only for processed forward
+	
+	virtual bool ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput);
+	bool ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput);
+
+
+	void PrintSpectralBufferList();
+	
+protected:
+	void CopyInput(UInt32 inNumFrames, AudioBufferList* inInput);
+	void CopyInputToFFT();
+	void DoWindowing();
+	void DoFwdFFT();
+	void DoInvFFT();
+	void OverlapAddOutput();
+	void CopyOutput(UInt32 inNumFrames, AudioBufferList* inOutput);
+	void ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra);
+	
+	UInt32 mFFTSize;
+	UInt32 mHopSize;
+	UInt32 mNumChannels;
+	UInt32 mMaxFrames;
+
+	UInt32 mLog2FFTSize;
+	UInt32 mFFTMask; 
+	UInt32 mFFTByteSize;
+	UInt32 mIOBufSize;
+	UInt32 mIOMask;
+	UInt32 mInputSize;
+	UInt32 mInputPos;
+	UInt32 mOutputPos;
+	UInt32 mInFFTPos;
+	UInt32 mOutFFTPos;
+	FFTSetup mFFTSetup;
+
+	CAAutoFree<Float32> mWindow;
+	struct SpectralChannel 
+	{
+		CAAutoFree<Float32> mInputBuf;		// log2ceil(FFT size + max frames)
+		CAAutoFree<Float32> mOutputBuf;		// log2ceil(FFT size + max frames)
+		CAAutoFree<Float32> mFFTBuf;		// FFT size
+		CAAutoFree<Float32> mSplitFFTBuf;	// FFT size
+	};
+	CAAutoArrayDelete<SpectralChannel> mChannels;
+
+	CAAutoFree<SpectralBufferList> mSpectralBufferList;
+	
+	SpectralFunction mSpectralFunction;
+	void *mUserData;
+	
+};
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp
new file mode 100644
index 0000000..d56947a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp
@@ -0,0 +1,879 @@
+/*
+     File: CAStreamBasicDescription.cpp
+ Abstract: CAStreamBasicDescription.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAStreamBasicDescription.h"
+#include "CAMath.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CFByteOrder.h>
+#else
+	#include <CFByteOrder.h>
+#endif
+
+#pragma mark	This file needs to compile on earlier versions of the OS, so please keep that in mind when editing it
+
+char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize)
+{
+	if (bufsize > 0) {
+		char *p = writeLocation, *pend = writeLocation + bufsize;
+		union { UInt32 i; unsigned char str[4]; } u;
+		unsigned char *q = u.str;
+		u.i = CFSwapInt32HostToBig(t);
+
+		bool hasNonPrint = false;
+		for (int i = 0; i < 4; ++i) {
+			if (!(isprint(*q) && *q != '\\')) {
+				hasNonPrint = true;
+				break;
+			}
+            q++;
+		}
+        q = u.str;
+		
+		if (hasNonPrint)
+			p += snprintf (p, pend - p, "0x");
+		else if (p < pend)
+			*p++ = '\'';
+			
+		for (int i = 0; i < 4 && p < pend; ++i) {
+			if (hasNonPrint) {
+				p += snprintf(p, pend - p, "%02X", *q++);
+			} else {
+				*p++ = *q++;
+			}
+		}
+		if (!hasNonPrint && p < pend)
+			*p++ = '\'';
+		if (p >= pend) p -= 1;
+		*p = '\0';
+	}
+	return writeLocation;
+}
+
+
+const AudioStreamBasicDescription	CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+CAStreamBasicDescription::CAStreamBasicDescription() 
+{ 
+	memset (this, 0, sizeof(AudioStreamBasicDescription)); 
+}
+	
+CAStreamBasicDescription::CAStreamBasicDescription(const AudioStreamBasicDescription &desc)
+{
+	SetFrom(desc);
+}
+
+
+CAStreamBasicDescription::CAStreamBasicDescription(double inSampleRate,		UInt32 inFormatID,
+									UInt32 inBytesPerPacket,	UInt32 inFramesPerPacket,
+									UInt32 inBytesPerFrame,		UInt32 inChannelsPerFrame,
+									UInt32 inBitsPerChannel,	UInt32 inFormatFlags)
+{
+	mSampleRate = inSampleRate;
+	mFormatID = inFormatID;
+	mBytesPerPacket = inBytesPerPacket;
+	mFramesPerPacket = inFramesPerPacket;
+	mBytesPerFrame = inBytesPerFrame;
+	mChannelsPerFrame = inChannelsPerFrame;
+	mBitsPerChannel = inBitsPerChannel;
+	mFormatFlags = inFormatFlags;
+	mReserved = 0;
+}
+
+char *CAStreamBasicDescription::AsString(char *buf, size_t _bufsize, bool brief /*=false*/) const
+{
+	int bufsize = (int)_bufsize;	// must be signed to protect against overflow
+	char *theBuffer = buf;
+	int nc;
+	char formatID[24];
+	CAStringForOSType(mFormatID, formatID, sizeof(formatID));
+	if (brief) {
+		CommonPCMFormat com;
+		bool interleaved;
+		if (IdentifyCommonPCMFormat(com, &interleaved) && com != kPCMFormatOther) {
+			const char *desc;
+			switch (com) {
+			case kPCMFormatInt16:
+				desc = "Int16";
+				break;
+			case kPCMFormatFixed824:
+				desc = "Int8.24";
+				break;
+			case kPCMFormatFloat32:
+				desc = "Float32";
+				break;
+			case kPCMFormatFloat64:
+				desc = "Float64";
+				break;
+			default:
+				desc = NULL;
+				break;
+			}
+			if (desc) {
+				const char *inter ="";
+				if (mChannelsPerFrame > 1)
+					inter = !interleaved ? ", non-inter" : ", inter";
+				snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s%s", (int)mChannelsPerFrame, mSampleRate, desc, inter);
+				return theBuffer;
+			}
+		}
+		if (mChannelsPerFrame == 0 && mSampleRate == 0.0 && mFormatID == 0) {
+			snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz", (int)mChannelsPerFrame, mSampleRate);
+			return theBuffer;
+		}
+	}
+	
+	nc = snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s (0x%08X) ", (int)NumberChannels(), mSampleRate, formatID, (int)mFormatFlags);
+	buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+	if (mFormatID == kAudioFormatLinearPCM) {
+		bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat);
+		int wordSize = static_cast<int>(SampleWordSize());
+		const char *endian = (wordSize > 1) ? 
+			((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : "";
+		const char *sign = isInt ? 
+			((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : "";
+		const char *floatInt = isInt ? "integer" : "float";
+		char packed[32];
+		if (wordSize > 0 && PackednessIsSignificant()) {
+			if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
+				snprintf(packed, sizeof(packed), "packed in %d bytes", wordSize);
+			else
+				snprintf(packed, sizeof(packed), "unpacked in %d bytes", wordSize);
+		} else
+			packed[0] = '\0';
+		const char *align = (wordSize > 0 && AlignmentIsSignificant()) ?
+			((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
+		const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
+		const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
+		char bitdepth[20];
+
+		int fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+		if (fracbits > 0)
+			snprintf(bitdepth, sizeof(bitdepth), "%d.%d", (int)mBitsPerChannel - fracbits, fracbits);
+		else
+			snprintf(bitdepth, sizeof(bitdepth), "%d", (int)mBitsPerChannel);
+		
+		/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%s-bit%s%s %s%s%s%s%s",
+			bitdepth, endian, sign, floatInt, 
+			commaSpace, packed, align, deinter);
+		// buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+	} else if (mFormatID == kAudioFormatAppleLossless) {
+		int sourceBits = 0;
+		switch (mFormatFlags)
+		{
+			case 1:	//	kAppleLosslessFormatFlag_16BitSourceData
+				sourceBits = 16;
+				break;
+    		case 2:	//	kAppleLosslessFormatFlag_20BitSourceData
+    			sourceBits = 20;
+    			break;
+    		case 3:	//	kAppleLosslessFormatFlag_24BitSourceData
+    			sourceBits = 24;
+    			break;
+    		case 4:	//	kAppleLosslessFormatFlag_32BitSourceData
+    			sourceBits = 32;
+    			break;
+		}
+		if (sourceBits)
+			nc = snprintf(buf, static_cast<size_t>(bufsize), "from %d-bit source, ", sourceBits);
+		else
+			nc = snprintf(buf, static_cast<size_t>(bufsize), "from UNKNOWN source bit depth, ");
+		buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+		/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d frames/packet", (int)mFramesPerPacket);
+		//	buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+	}
+	else
+		/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d bits/channel, %d bytes/packet, %d frames/packet, %d bytes/frame", 
+			(int)mBitsPerChannel, (int)mBytesPerPacket, (int)mFramesPerPacket, (int)mBytesPerFrame);
+exit:
+	return theBuffer;
+}
+
+void	CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
+{
+	//  the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
+	if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
+	{
+		//  the canonical linear PCM format
+		ioDescription.mFormatFlags = kAudioFormatFlagsCanonical;
+		ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+		ioDescription.mFramesPerPacket = 1;
+		ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+		ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
+	}
+}
+
+void	CAStreamBasicDescription::NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription)
+{
+	//  the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
+	if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
+	{
+		//  the canonical linear PCM format
+		ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
+		if(inNativeEndian)
+		{
+#if TARGET_RT_BIG_ENDIAN
+			ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
+#endif
+		}
+		else
+		{
+#if TARGET_RT_LITTLE_ENDIAN
+			ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
+#endif
+		}
+		ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+		ioDescription.mFramesPerPacket = 1;
+		ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+		ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
+	}
+}
+
+void	CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription)
+{
+	ioDescription.mSampleRate = 0;
+	ioDescription.mFormatID = 0;
+	ioDescription.mBytesPerPacket = 0;
+	ioDescription.mFramesPerPacket = 0;
+	ioDescription.mBytesPerFrame = 0;
+	ioDescription.mChannelsPerFrame = 0;
+	ioDescription.mBitsPerChannel = 0;
+	ioDescription.mFormatFlags = 0;
+}
+
+void	CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription)
+{
+	if(fiszero(ioDescription.mSampleRate))
+	{
+		ioDescription.mSampleRate = inTemplateDescription.mSampleRate;
+	}
+	if(ioDescription.mFormatID == 0)
+	{
+		ioDescription.mFormatID = inTemplateDescription.mFormatID;
+	}
+	if(ioDescription.mFormatFlags == 0)
+	{
+		ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags;
+	}
+	if(ioDescription.mBytesPerPacket == 0)
+	{
+		ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket;
+	}
+	if(ioDescription.mFramesPerPacket == 0)
+	{
+		ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket;
+	}
+	if(ioDescription.mBytesPerFrame == 0)
+	{
+		ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame;
+	}
+	if(ioDescription.mChannelsPerFrame == 0)
+	{
+		ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame;
+	}
+	if(ioDescription.mBitsPerChannel == 0)
+	{
+		ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel;
+	}
+}
+
+void	CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate)
+{
+	if(inIncludeSampleRate)
+	{
+		int theCharactersWritten = snprintf(outName, inMaxNameLength, "%.0f ", inDescription.mSampleRate);
+		outName += theCharactersWritten;
+		inMaxNameLength -= static_cast<UInt32>(theCharactersWritten);
+	}
+	
+	switch(inDescription.mFormatID)
+	{
+		case kAudioFormatLinearPCM:
+			{
+				const char* theEndianString = NULL;
+				if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
+				{
+					#if	TARGET_RT_LITTLE_ENDIAN
+						theEndianString = "Big Endian";
+					#endif
+				}
+				else
+				{
+					#if	TARGET_RT_BIG_ENDIAN
+						theEndianString = "Little Endian";
+					#endif
+				}
+				
+				const char* theKindString = NULL;
+				if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
+				{
+					theKindString = (inAbbreviate ? "Float" : "Floating Point");
+				}
+				else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
+				{
+					theKindString = (inAbbreviate ? "SInt" : "Signed Integer");
+				}
+				else
+				{
+					theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
+				}
+				
+				const char* thePackingString = NULL;
+				if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
+				{
+					if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
+					{
+						thePackingString = "High";
+					}
+					else
+					{
+						thePackingString = "Low";
+					}
+				}
+				
+				const char* theMixabilityString = NULL;
+				if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
+				{
+					theMixabilityString = "Mixable";
+				}
+				else
+				{
+					theMixabilityString = "Unmixable";
+				}
+				
+				if(inAbbreviate)
+				{
+					if(theEndianString != NULL)
+					{
+						if(thePackingString != NULL)
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+						}
+						else
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel);
+						}
+					}
+					else
+					{
+						if(thePackingString != NULL)
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8));
+						}
+						else
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel);
+						}
+					}
+				}
+				else
+				{
+					if(theEndianString != NULL)
+					{
+						if(thePackingString != NULL)
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+						}
+						else
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString);
+						}
+					}
+					else
+					{
+						if(thePackingString != NULL)
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+						}
+						else
+						{
+							snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString);
+						}
+					}
+				}
+			}
+			break;
+		
+		case kAudioFormatAC3:
+			strlcpy(outName, "AC-3", sizeof(outName));
+			break;
+		
+		case kAudioFormat60958AC3:
+			strlcpy(outName, "AC-3 for SPDIF", sizeof(outName));
+			break;
+		
+		default:
+			CACopy4CCToCString(outName, inDescription.mFormatID);
+			break;
+	};
+}
+
+#if CoreAudio_Debug
+#include "CALogMacros.h"
+
+void	CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc)
+{
+	PrintFloat		("  Sample Rate:        ", inDesc.mSampleRate);
+	Print4CharCode	("  Format ID:          ", inDesc.mFormatID);
+	PrintHex		("  Format Flags:       ", inDesc.mFormatFlags);
+	PrintInt		("  Bytes per Packet:   ", inDesc.mBytesPerPacket);
+	PrintInt		("  Frames per Packet:  ", inDesc.mFramesPerPacket);
+	PrintInt		("  Bytes per Frame:    ", inDesc.mBytesPerFrame);
+	PrintInt		("  Channels per Frame: ", inDesc.mChannelsPerFrame);
+	PrintInt		("  Bits per Channel:   ", inDesc.mBitsPerChannel);
+}
+#endif
+
+bool	operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+	bool theAnswer = false;
+	bool isDone = false;
+	
+	//	note that if either side is 0, that field is skipped
+	
+	//	format ID is the first order sort
+	if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
+	{
+		if(x.mFormatID != y.mFormatID)
+		{
+			//	formats are sorted numerically except that linear
+			//	PCM is always first
+			if(x.mFormatID == kAudioFormatLinearPCM)
+			{
+				theAnswer = true;
+			}
+			else if(y.mFormatID == kAudioFormatLinearPCM)
+			{
+				theAnswer = false;
+			}
+			else
+			{
+				theAnswer = x.mFormatID < y.mFormatID;
+			}
+			isDone = true;
+		}
+	}
+	
+	
+	//  mixable is always better than non-mixable for linear PCM and should be the second order sort item
+	if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+	{
+		if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
+		{
+			theAnswer = true;
+			isDone = true;
+		}
+		else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
+		{
+			theAnswer = false;
+			isDone = true;
+		}
+	}
+	
+	//	floating point vs integer for linear PCM only
+	if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+	{
+		if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
+		{
+			//	floating point is better than integer
+			theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
+			isDone = true;
+		}
+	}
+	
+	//	bit depth
+	if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
+	{
+		if(x.mBitsPerChannel != y.mBitsPerChannel)
+		{
+			//	deeper bit depths are higher quality
+			theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
+			isDone = true;
+		}
+	}
+	
+	//	sample rate
+	if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
+	{
+		if(fnotequal(x.mSampleRate, y.mSampleRate))
+		{
+			//	higher sample rates are higher quality
+			theAnswer = x.mSampleRate < y.mSampleRate;
+			isDone = true;
+		}
+	}
+	
+	//	number of channels
+	if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
+	{
+		if(x.mChannelsPerFrame != y.mChannelsPerFrame)
+		{
+			//	more channels is higher quality
+			theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
+			//isDone = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
+void CAStreamBasicDescription::ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly )
+{
+    // match wildcards
+	if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0)
+    {
+		// Obliterate all flags.
+        xFlags = yFlags = 0;
+        return;
+    }
+    
+    if (x.mFormatID == kAudioFormatLinearPCM) {
+        // knock off the all clear flag
+        xFlags = xFlags & ~kAudioFormatFlagsAreAllClear;
+        yFlags = yFlags & ~kAudioFormatFlagsAreAllClear;
+        
+        // if both kAudioFormatFlagIsPacked bits are set, then we don't care about the kAudioFormatFlagIsAlignedHigh bit.
+        if (xFlags & yFlags & kAudioFormatFlagIsPacked) {
+            xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+            yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+        }
+        
+        // if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit.
+        if (xFlags & yFlags & kAudioFormatFlagIsFloat) {
+            xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
+            yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
+        }
+        
+        //	if the bit depth is 8 bits or less and the format is packed, we don't care about endianness
+        if((x.mBitsPerChannel <= 8) && ((xFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
+        {
+            xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
+        }
+        if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
+        {
+            yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
+        }
+        
+        //	if the number of channels is 1, we don't care about non-interleavedness
+        if (x.mChannelsPerFrame == 1 && y.mChannelsPerFrame == 1) {
+            xFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
+            yFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
+        }
+        
+        if (converterOnly) {
+            CAStreamBasicDescription cas_x = CAStreamBasicDescription(x);
+            CAStreamBasicDescription cas_y = CAStreamBasicDescription(y);
+            if (!cas_x.PackednessIsSignificant() && !cas_y.PackednessIsSignificant()) {
+                xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
+                yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
+            }
+            if (!cas_x.AlignmentIsSignificant() && !cas_y.AlignmentIsSignificant()) {
+                xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+                yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+            }
+            // We don't care about whether the streams are mixable in this case
+            xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
+            yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
+        }
+    }
+}
+
+static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+	UInt32 xFlags = x.mFormatFlags;
+	UInt32 yFlags = y.mFormatFlags;
+	
+    CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, false);
+	return xFlags == yFlags;
+}
+
+bool	operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+	//	the semantics for equality are:
+	//		1) Values must match exactly -- except for PCM format flags, see above.
+	//		2) wildcard's are ignored in the comparison
+	
+#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name))
+	
+	return 
+    //	check all but the format flags
+    CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
+    //	check the format flags
+    && MatchFormatFlags(x, y);  
+}
+
+bool    CAStreamBasicDescription::FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
+{
+    return 
+    //	check the sample rate
+    (fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate))
+    
+    //	check the format ids
+    && MATCH(mFormatID)
+        
+    //	check the bytes per packet
+    && MATCH(mBytesPerPacket) 
+    
+    //	check the frames per packet
+    && MATCH(mFramesPerPacket) 
+    
+    //	check the bytes per frame
+    && MATCH(mBytesPerFrame) 
+    
+    //	check the channels per frame
+    && MATCH(mChannelsPerFrame) 
+    
+    //	check the channels per frame
+    && MATCH(mBitsPerChannel) ;
+}
+
+bool	CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const
+{
+	if (interpretingWildcards)
+		return *this == other;
+	return memcmp(this, &other, offsetof(AudioStreamBasicDescription, mReserved)) == 0;
+}
+
+bool    CAStreamBasicDescription::IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
+{
+    UInt32 xFlags = x.mFormatFlags, yFlags = y.mFormatFlags;    
+    CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, true);
+    
+    return
+    // check all but the format flags
+    CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
+    // check the format flags with converter focus
+    && (xFlags == yFlags);
+    
+}
+
+bool SanityCheck(const AudioStreamBasicDescription& x)
+{
+	// This function returns false if there are sufficiently insane values in any field.
+	// It is very conservative so even some very unlikely values will pass.
+	// This is just meant to catch the case where the data from a file is corrupted.
+	
+	return 
+		(x.mSampleRate >= 0.)	
+		&& (x.mSampleRate < 3e6)	// SACD sample rate is 2.8224 MHz
+		&& (x.mBytesPerPacket < 1000000)
+		&& (x.mFramesPerPacket < 1000000)
+		&& (x.mBytesPerFrame < 1000000)
+		&& (x.mChannelsPerFrame <= 1024)
+		&& (x.mBitsPerChannel <= 1024)
+		&& (x.mFormatID != 0)
+		&& !(x.mFormatID == kAudioFormatLinearPCM && (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
+}
+
+bool CAStreamBasicDescription::FromText(const char *inTextDesc, AudioStreamBasicDescription &fmt)
+{
+	const char *p = inTextDesc;
+	
+	memset(&fmt, 0, sizeof(fmt));
+
+	bool isPCM = true;	// until proven otherwise
+	UInt32 pcmFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
+
+	if (p[0] == '-')	// previously we required a leading dash on PCM formats
+		++p;
+
+	if (p[0] == 'B' && p[1] == 'E') {
+		pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
+		p += 2;
+	} else if (p[0] == 'L' && p[1] == 'E') {
+		p += 2;
+	} else {
+		// default is native-endian
+#if TARGET_RT_BIG_ENDIAN
+		pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
+#endif
+	}
+	if (p[0] == 'F') {
+		pcmFlags = (pcmFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger)) | kAudioFormatFlagIsFloat;
+		++p;
+	} else {
+		if (p[0] == 'U') {
+			pcmFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
+			++p;
+		}
+		if (p[0] == 'I')
+			++p;
+		else {
+			// it's not PCM; presumably some other format (NOT VALIDATED; use AudioFormat for that)
+			isPCM = false;
+			p = inTextDesc;	// go back to the beginning
+			char buf[4] = { ' ',' ',' ',' ' };
+			for (int i = 0; i < 4; ++i) {
+				if (*p != '\\') {
+					if ((buf[i] = *p++) == '\0') {
+						// special-case for 'aac'
+						if (i != 3) return false;
+						--p;	// keep pointing at the terminating null
+						buf[i] = ' ';
+						break;
+					}
+				} else {
+					// "\xNN" is a hex byte
+					if (*++p != 'x') return false;
+					int x;
+					if (sscanf(++p, "%02X", &x) != 1) return false;
+					buf[i] = static_cast<char>(x);
+					p += 2;
+				}
+			}
+			
+			if (strchr("-@/#", buf[3])) {
+				// further special-casing for 'aac'
+				buf[3] = ' ';
+				--p;
+			}
+			
+			memcpy(&fmt.mFormatID, buf, 4);
+			fmt.mFormatID = CFSwapInt32BigToHost(fmt.mFormatID);
+		}
+	}
+	
+	if (isPCM) {
+		fmt.mFormatID = kAudioFormatLinearPCM;
+		fmt.mFormatFlags = pcmFlags;
+		fmt.mFramesPerPacket = 1;
+		fmt.mChannelsPerFrame = 1;
+		UInt32 bitdepth = 0, fracbits = 0;
+		while (isdigit(*p))
+			bitdepth = 10 * bitdepth + static_cast<UInt32>(*p++ - '0');
+		if (*p == '.') {
+			++p;
+			if (!isdigit(*p)) {
+				fprintf(stderr, "Expected fractional bits following '.'\n");
+				goto Bail;
+			}
+			while (isdigit(*p))
+				fracbits = 10 * fracbits + static_cast<UInt32>(*p++ - '0');
+			bitdepth += fracbits;
+			fmt.mFormatFlags |= (fracbits << kLinearPCMFormatFlagsSampleFractionShift);
+		}
+		fmt.mBitsPerChannel = bitdepth;
+		fmt.mBytesPerPacket = fmt.mBytesPerFrame = (bitdepth + 7) / 8;
+		if (bitdepth & 7) {
+			// assume unpacked. (packed odd bit depths are describable but not supported in AudioConverter.)
+			fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
+			// alignment matters; default to high-aligned. use ':L_' for low.
+			fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
+		}
+	}
+	if (*p == '@') {
+		++p;
+		while (isdigit(*p))
+			fmt.mSampleRate = 10 * fmt.mSampleRate + (*p++ - '0');
+	}
+	if (*p == '/') {
+		UInt32 flags = 0;
+		while (true) {
+			char c = *++p;
+			if (c >= '0' && c <= '9')
+				flags = (flags << 4) | static_cast<UInt32>(c - '0');
+			else if (c >= 'A' && c <= 'F')
+				flags = (flags << 4) | static_cast<UInt32>(c - 'A' + 10);
+			else if (c >= 'a' && c <= 'f')
+				flags = (flags << 4) | static_cast<UInt32>(c - 'a' + 10);
+			else break;
+		}
+		fmt.mFormatFlags = flags;
+	}
+	if (*p == '#') {
+		++p;
+		while (isdigit(*p))
+			fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + static_cast<UInt32>(*p++ - '0');
+	}
+	if (*p == ':') {
+		++p;
+		fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
+		if (*p == 'L')
+			fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsAlignedHigh);
+		else if (*p == 'H')
+			fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
+		else
+			goto Bail;
+		++p;
+		UInt32 bytesPerFrame = 0;
+		while (isdigit(*p))
+			bytesPerFrame = 10 * bytesPerFrame + static_cast<UInt32>(*p++ - '0');
+		fmt.mBytesPerFrame = fmt.mBytesPerPacket = bytesPerFrame;
+	}
+	if (*p == ',') {
+		++p;
+		int ch = 0;
+		while (isdigit(*p))
+			ch = 10 * ch + (*p++ - '0');
+		fmt.mChannelsPerFrame = static_cast<UInt32>(ch);
+		if (*p == 'D') {
+			++p;
+			if (fmt.mFormatID != kAudioFormatLinearPCM) {
+				fprintf(stderr, "non-interleaved flag invalid for non-PCM formats\n");
+				goto Bail;
+			}
+			fmt.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+		} else {
+			if (*p == 'I') ++p;	// default
+			if (fmt.mFormatID == kAudioFormatLinearPCM)
+				fmt.mBytesPerPacket = fmt.mBytesPerFrame *= static_cast<UInt32>(ch);
+		}
+	}
+	if (*p != '\0') {
+		fprintf(stderr, "extra characters at end of format string: %s\n", p);
+		goto Bail;
+	}
+	return true;
+
+Bail:
+	fprintf(stderr, "Invalid format string: %s\n", inTextDesc);
+	fprintf(stderr, "Syntax of format strings is: \n");
+	return false;
+}
+
+const char *CAStreamBasicDescription::sTextParsingUsageString = 
+	"format[@sample_rate_hz][/format_flags][#frames_per_packet][:LHbytesPerFrame][,channelsDI].\n"
+	"Format for PCM is [-][BE|LE]{F|I|UI}{bitdepth}; else a 4-char format code (e.g. aac, alac).\n";
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h
new file mode 100644
index 0000000..8b81dba
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h
@@ -0,0 +1,424 @@
+/*
+     File: CAStreamBasicDescription.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAStreamBasicDescription_h__
+#define __CAStreamBasicDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include "CoreAudioTypes.h"
+	#include "CoreFoundation.h"
+#endif
+
+#include "CADebugMacros.h"
+#include <string.h>	// for memset, memcpy
+#include <stdio.h>	// for FILE *
+
+#pragma mark	This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
+
+extern char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize);
+
+// define Leopard specific symbols for backward compatibility if applicable
+#if COREAUDIOTYPES_VERSION < 1050
+typedef Float32 AudioSampleType;
+enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked };
+#endif
+#if COREAUDIOTYPES_VERSION < 1051
+typedef Float32 AudioUnitSampleType;
+enum {
+	kLinearPCMFormatFlagsSampleFractionShift    = 7,
+	kLinearPCMFormatFlagsSampleFractionMask     = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),
+};
+#endif
+
+//	define the IsMixable format flag for all versions of the system
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+	enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
+#else
+	enum { kIsNonMixableFlag = (1L << 6) };
+#endif
+
+//=============================================================================
+//	CAStreamBasicDescription
+//
+//	This is a wrapper class for the AudioStreamBasicDescription struct.
+//	It adds a number of convenience routines, but otherwise adds nothing
+//	to the footprint of the original struct.
+//=============================================================================
+class CAStreamBasicDescription : 
+	public AudioStreamBasicDescription
+{
+
+//	Constants
+public:
+	static const AudioStreamBasicDescription	sEmpty;
+	
+	enum CommonPCMFormat {
+		kPCMFormatOther		= 0,
+		kPCMFormatFloat32	= 1,
+		kPCMFormatInt16		= 2,
+		kPCMFormatFixed824	= 3,
+		kPCMFormatFloat64	= 4
+	};
+	
+//	Construction/Destruction
+public:
+	CAStreamBasicDescription();
+	
+	CAStreamBasicDescription(const AudioStreamBasicDescription &desc);
+	
+	CAStreamBasicDescription(		double inSampleRate,		UInt32 inFormatID,
+									UInt32 inBytesPerPacket,	UInt32 inFramesPerPacket,
+									UInt32 inBytesPerFrame,		UInt32 inChannelsPerFrame,
+									UInt32 inBitsPerChannel,	UInt32 inFormatFlags);
+
+	CAStreamBasicDescription(	double inSampleRate, UInt32 inNumChannels, CommonPCMFormat pcmf, bool inIsInterleaved) {
+		unsigned wordsize;
+
+		mSampleRate = inSampleRate;
+		mFormatID = kAudioFormatLinearPCM;
+		mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
+		mFramesPerPacket = 1;
+		mChannelsPerFrame = inNumChannels;
+		mBytesPerFrame = mBytesPerPacket = 0;
+		mReserved = 0;
+
+		switch (pcmf) {
+		default:
+			return;
+		case kPCMFormatFloat32:
+			wordsize = 4;
+			mFormatFlags |= kAudioFormatFlagIsFloat;
+			break;
+		case kPCMFormatFloat64:
+			wordsize = 8;
+			mFormatFlags |= kAudioFormatFlagIsFloat;
+			break;
+		case kPCMFormatInt16:
+			wordsize = 2;
+			mFormatFlags |= kAudioFormatFlagIsSignedInteger;
+			break;
+		case kPCMFormatFixed824:
+			wordsize = 4;
+			mFormatFlags |= kAudioFormatFlagIsSignedInteger | (24 << kLinearPCMFormatFlagsSampleFractionShift);
+			break;
+		}
+		mBitsPerChannel = wordsize * 8;
+		if (inIsInterleaved)
+			mBytesPerFrame = mBytesPerPacket = wordsize * inNumChannels;
+		else {
+			mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+			mBytesPerFrame = mBytesPerPacket = wordsize;
+		}
+	}
+
+//	Assignment
+	CAStreamBasicDescription&	operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; }
+
+	void	SetFrom(const AudioStreamBasicDescription &desc)
+	{
+		memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
+	}
+	
+	bool		FromText(const char *inTextDesc) { return FromText(inTextDesc, *this); }
+	static bool	FromText(const char *inTextDesc, AudioStreamBasicDescription &outDesc);
+					// return true if parsing was successful
+	
+	static const char *sTextParsingUsageString;
+	
+	// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+	//
+	// interrogation
+	
+	bool	IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
+	
+	bool	PackednessIsSignificant() const
+	{
+		Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
+		return (SampleWordSize() << 3) != mBitsPerChannel;
+	}
+	
+	bool	AlignmentIsSignificant() const
+	{
+		return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
+	}
+	
+	bool	IsInterleaved() const
+	{
+		return !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
+	}
+	
+	bool	IsSignedInteger() const
+	{
+		return IsPCM() && (mFormatFlags & kAudioFormatFlagIsSignedInteger);
+	}
+	
+	bool	IsFloat() const
+	{
+		return IsPCM() && (mFormatFlags & kAudioFormatFlagIsFloat);
+	}
+	
+	bool	IsNativeEndian() const
+	{
+		return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian;
+	}
+	
+	// for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
+	UInt32	NumberInterleavedChannels() const	{ return IsInterleaved() ? mChannelsPerFrame : 1; }	
+	UInt32	NumberChannelStreams() const		{ return IsInterleaved() ? 1 : mChannelsPerFrame; }
+	UInt32	NumberChannels() const				{ return mChannelsPerFrame; }
+	UInt32	SampleWordSize() const				{ 
+			return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() :  0;
+	}
+
+	UInt32	FramesToBytes(UInt32 nframes) const	{ return nframes * mBytesPerFrame; }
+	UInt32	BytesToFrames(UInt32 nbytes) const	{
+		Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
+		return nbytes / mBytesPerFrame;
+	}
+	
+	bool	SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
+	{
+		return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
+	}
+	
+	bool	IdentifyCommonPCMFormat(CommonPCMFormat &outFormat, bool *outIsInterleaved=NULL) const
+	{	// return true if it's a valid PCM format.
+	
+		outFormat = kPCMFormatOther;
+		// trap out patently invalid formats.
+		if (mFormatID != kAudioFormatLinearPCM || mFramesPerPacket != 1 || mBytesPerFrame != mBytesPerPacket || mBitsPerChannel/8 > mBytesPerFrame || mChannelsPerFrame == 0)
+			return false;
+		bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
+		if (outIsInterleaved != NULL) *outIsInterleaved = interleaved;
+		unsigned wordsize = mBytesPerFrame;
+		if (interleaved) {
+			if (wordsize % mChannelsPerFrame != 0) return false;
+			wordsize /= mChannelsPerFrame;
+		}
+		
+		if ((mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian
+		&& wordsize * 8 == mBitsPerChannel) {
+			// packed and native endian, good
+			if (mFormatFlags & kLinearPCMFormatFlagIsFloat) {
+				// float: reject nonsense bits
+				if (mFormatFlags & (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagsSampleFractionMask))
+					return false;
+				if (wordsize == 4)
+					outFormat = kPCMFormatFloat32;
+				if (wordsize == 8)
+					outFormat = kPCMFormatFloat64;
+			} else if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) {
+				// signed int
+				unsigned fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+				if (wordsize == 4 && fracbits == 24)
+					outFormat = kPCMFormatFixed824;
+				else if (wordsize == 2 && fracbits == 0)
+					outFormat = kPCMFormatInt16;
+			}
+		}
+		return true;
+	}
+
+	bool IsCommonFloat32(bool *outIsInterleaved=NULL) const {
+		CommonPCMFormat fmt;
+		return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat32;
+	}
+	bool IsCommonFloat64(bool *outIsInterleaved=NULL) const {
+		CommonPCMFormat fmt;
+		return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat64;
+	}
+	bool IsCommonFixed824(bool *outIsInterleaved=NULL) const {
+		CommonPCMFormat fmt;
+		return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFixed824;
+	}
+	bool IsCommonInt16(bool *outIsInterleaved=NULL) const {
+		CommonPCMFormat fmt;
+		return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatInt16;
+	}
+	
+	// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+	//
+	//	manipulation
+	
+	void	SetCanonical(UInt32 nChannels, bool interleaved)
+				// note: leaves sample rate untouched
+	{
+		mFormatID = kAudioFormatLinearPCM;
+		UInt32 sampleSize = SizeOf32(AudioSampleType);
+		mFormatFlags = kAudioFormatFlagsCanonical;
+		mBitsPerChannel = 8 * sampleSize;
+		mChannelsPerFrame = nChannels;
+		mFramesPerPacket = 1;
+		if (interleaved)
+			mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
+		else {
+			mBytesPerPacket = mBytesPerFrame = sampleSize;
+			mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+		}
+	}
+	
+	bool	IsCanonical() const
+	{
+		if (mFormatID != kAudioFormatLinearPCM) return false;
+		UInt32 reqFormatFlags;
+		UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagsSampleFractionMask);
+		bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
+		unsigned sampleSize = SizeOf32(AudioSampleType);
+		reqFormatFlags = kAudioFormatFlagsCanonical;
+		UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize;
+
+		return ((mFormatFlags & flagsMask) == reqFormatFlags
+			&& mBitsPerChannel == 8 * sampleSize
+			&& mFramesPerPacket == 1
+			&& mBytesPerFrame == reqFrameSize
+			&& mBytesPerPacket == reqFrameSize);
+	}
+	
+	void	SetAUCanonical(UInt32 nChannels, bool interleaved)
+	{
+		mFormatID = kAudioFormatLinearPCM;
+#if CA_PREFER_FIXED_POINT
+		mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
+#else
+		mFormatFlags = kAudioFormatFlagsCanonical;
+#endif
+		mChannelsPerFrame = nChannels;
+		mFramesPerPacket = 1;
+		mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType);
+		if (interleaved)
+			mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType);
+		else {
+			mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType);
+			mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+		}
+	}
+	
+	void	ChangeNumberChannels(UInt32 nChannels, bool interleaved)
+				// alter an existing format
+	{
+		Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
+		UInt32 wordSize = SampleWordSize();	// get this before changing ANYTHING
+		if (wordSize == 0)
+			wordSize = (mBitsPerChannel + 7) / 8;
+		mChannelsPerFrame = nChannels;
+		mFramesPerPacket = 1;
+		if (interleaved) {
+			mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
+			mFormatFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonInterleaved);
+		} else {
+			mBytesPerPacket = mBytesPerFrame = wordSize;
+			mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+		}
+	}
+	
+	// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+	//
+	//	other
+	
+	bool            IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards=true) const;
+	static bool     FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
+    static bool     IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
+    
+	void	Print() const {
+		Print (stdout);
+	}
+
+	void	Print(FILE* file) const {
+		PrintFormat (file, "", "AudioStreamBasicDescription:");	
+	}
+
+	void	PrintFormat(FILE *f, const char *indent, const char *name) const {
+		char buf[256];
+		fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf)));
+	}
+	
+	void	PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline
+		char buf[256];
+		fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf)));
+	}
+
+	char *	AsString(char *buf, size_t bufsize, bool brief=false) const;
+
+	static void Print (const AudioStreamBasicDescription &inDesc) 
+	{ 
+		CAStreamBasicDescription desc(inDesc);
+		desc.Print ();
+	}
+	
+	OSStatus			Save(CFPropertyListRef *outData) const;
+		
+	OSStatus			Restore(CFPropertyListRef &inData);
+
+//	Operations
+	static bool			IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
+	static void			NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
+	static void			NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription);
+	static void			ResetFormat(AudioStreamBasicDescription& ioDescription);
+	static void			FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
+	static void			GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate = false);
+    static void         ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly);
+
+#if CoreAudio_Debug
+	static void			PrintToLog(const AudioStreamBasicDescription& inDesc);
+#endif
+};
+
+bool		operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+bool		operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool	operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
+inline bool	operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
+inline bool	operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
+inline bool	operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
+#endif
+
+bool SanityCheck(const AudioStreamBasicDescription& x);
+
+
+#endif // __CAStreamBasicDescription_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp
new file mode 100644
index 0000000..9b72054
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp
@@ -0,0 +1,183 @@
+/*
+     File: CAStreamRangedDescription.cpp
+ Abstract: CAStreamRangedDescription.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//	Self Include
+#include "CAStreamRangedDescription.h"
+#include "CAMath.h"
+
+//==================================================================================================
+//	CAStreamRangedDescription
+//==================================================================================================
+
+const AudioStreamRangedDescription	CAStreamRangedDescription::sEmpty = { { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.0, 0.0 } };
+
+#if CoreAudio_Debug
+#include "CALogMacros.h"
+
+void	CAStreamRangedDescription::PrintToLog(const AudioStreamRangedDescription& inDesc)
+{
+	PrintFloat		("  Sample Rate:        ", inDesc.mFormat.mSampleRate);
+	PrintFloat		("  Max Sample Rate:    ", inDesc.mSampleRateRange.mMaximum);
+	PrintFloat		("  Min Sample Rate:    ", inDesc.mSampleRateRange.mMinimum);
+	Print4CharCode	("  Format ID:          ", inDesc.mFormat.mFormatID);
+	PrintHex		("  Format Flags:       ", inDesc.mFormat.mFormatFlags);
+	PrintInt		("  Bytes per Packet:   ", inDesc.mFormat.mBytesPerPacket);
+	PrintInt		("  Frames per Packet:  ", inDesc.mFormat.mFramesPerPacket);
+	PrintInt		("  Bytes per Frame:    ", inDesc.mFormat.mBytesPerFrame);
+	PrintInt		("  Channels per Frame: ", inDesc.mFormat.mChannelsPerFrame);
+	PrintInt		("  Bits per Channel:   ", inDesc.mFormat.mBitsPerChannel);
+}
+#endif
+
+bool	CAStreamRangedDescription::Sorter(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)
+{
+	bool theAnswer = false;
+	bool isDone = false;
+	
+	//	note that if either side is 0, that field is skipped
+	
+	//	format ID is the first order sort
+	if((!isDone) && ((x.mFormat.mFormatID != 0) && (y.mFormat.mFormatID != 0)))
+	{
+		if(x.mFormat.mFormatID != y.mFormat.mFormatID)
+		{
+			//	formats are sorted numerically except that linear
+			//	PCM is always first
+			if(x.mFormat.mFormatID == kAudioFormatLinearPCM)
+			{
+				theAnswer = true;
+			}
+			else if(y.mFormat.mFormatID == kAudioFormatLinearPCM)
+			{
+				theAnswer = false;
+			}
+			else
+			{
+				theAnswer = x.mFormat.mFormatID < y.mFormat.mFormatID;
+			}
+			isDone = true;
+		}
+	}
+	
+	
+	//  mixable is always better than non-mixable for linear PCM and should be the second order sort item
+	if((!isDone) && ((x.mFormat.mFormatID == kAudioFormatLinearPCM) && (y.mFormat.mFormatID == kAudioFormatLinearPCM)))
+	{
+		if(((x.mFormat.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormat.mFormatFlags & kIsNonMixableFlag) != 0))
+		{
+			theAnswer = true;
+			isDone = true;
+		}
+		else if(((x.mFormat.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormat.mFormatFlags & kIsNonMixableFlag) == 0))
+		{
+			theAnswer = false;
+			isDone = true;
+		}
+	}
+	
+	//	floating point vs integer for linear PCM only
+	if((!isDone) && ((x.mFormat.mFormatID == kAudioFormatLinearPCM) && (y.mFormat.mFormatID == kAudioFormatLinearPCM)))
+	{
+		if((x.mFormat.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormat.mFormatFlags & kAudioFormatFlagIsFloat))
+		{
+			//	floating point is better than integer
+			theAnswer = y.mFormat.mFormatFlags & kAudioFormatFlagIsFloat;
+			isDone = true;
+		}
+	}
+	
+	//	bit depth
+	if((!isDone) && ((x.mFormat.mBitsPerChannel != 0) && (y.mFormat.mBitsPerChannel != 0)))
+	{
+		if(x.mFormat.mBitsPerChannel != y.mFormat.mBitsPerChannel)
+		{
+			//	deeper bit depths are higher quality
+			theAnswer = x.mFormat.mBitsPerChannel > y.mFormat.mBitsPerChannel;
+			isDone = true;
+		}
+	}
+	
+	//	sample rate range
+	if((!isDone) && fnonzero(x.mSampleRateRange.mMinimum) && fnonzero(x.mSampleRateRange.mMaximum) && fnonzero(y.mSampleRateRange.mMinimum) && fnonzero(y.mSampleRateRange.mMaximum))
+	{
+		if(x.mSampleRateRange != y.mSampleRateRange)
+		{
+			//	higher sample rates are higher quality
+			theAnswer = x.mSampleRateRange > y.mSampleRateRange;
+			isDone = true;
+		}
+	}
+	
+	//	sample rate
+	if((!isDone) && fnonzero(x.mFormat.mSampleRate) && fnonzero(y.mFormat.mSampleRate))
+	{
+		if(fnotequal(x.mFormat.mSampleRate, y.mFormat.mSampleRate))
+		{
+			//	higher sample rates are higher quality
+			theAnswer = x.mFormat.mSampleRate > y.mFormat.mSampleRate;
+			isDone = true;
+		}
+	}
+	
+	//	number of channels
+	if((!isDone) && ((x.mFormat.mChannelsPerFrame != 0) && (y.mFormat.mChannelsPerFrame != 0)))
+	{
+		if(x.mFormat.mChannelsPerFrame != y.mFormat.mChannelsPerFrame)
+		{
+			//	more channels is higher quality
+			theAnswer = x.mFormat.mChannelsPerFrame < y.mFormat.mChannelsPerFrame;
+			//	commented out to prevent this from being flagged as a dead store by the static analyzer
+			//isDone = true;
+		}
+	}
+	
+	return theAnswer;
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h
new file mode 100644
index 0000000..7f8284d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h
@@ -0,0 +1,140 @@
+/*
+     File: CAStreamRangedDescription.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAStreamRangedDescription_h__)
+#define __CAStreamRangedDescription_h__
+
+//==================================================================================================
+//	Includes
+//==================================================================================================
+
+//  Super Class Includes
+#include <CoreAudio/AudioHardware.h>
+
+//  PublicUtility Includes
+#include "CAAudioValueRange.h"
+#include "CAStreamBasicDescription.h"
+
+//==================================================================================================
+//	CAStreamRangedDescription
+//==================================================================================================
+
+class CAStreamRangedDescription
+:
+	public AudioStreamRangedDescription
+{
+
+//	Constants
+public:
+	static const AudioStreamRangedDescription	sEmpty;
+
+//	Construction/Destruction
+public:
+								CAStreamRangedDescription()																							{ memset(this, 0, sizeof(AudioStreamRangedDescription)); }
+								CAStreamRangedDescription(const CAStreamRangedDescription& inFormat)												{ mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; }
+								CAStreamRangedDescription(const AudioStreamRangedDescription& inFormat)												{ mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; }
+								CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat)												{ mFormat = inFormat; mSampleRateRange.mMinimum = inFormat.mSampleRate; mSampleRateRange.mMaximum = inFormat.mSampleRate; }
+								CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat, const AudioValueRange& inSampleRateRange)	{ mFormat = inFormat; mSampleRateRange = inSampleRateRange; }
+	CAStreamRangedDescription&  operator=(const CAStreamRangedDescription& inFormat)																{ mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; }
+	CAStreamRangedDescription&  operator=(const AudioStreamRangedDescription& inFormat)																{ mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; }
+
+	static bool					IsMixable(const AudioStreamRangedDescription& inDescription) { return (inDescription.mFormat.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormat.mFormatFlags & kIsNonMixableFlag) == 0); }
+#if CoreAudio_Debug
+	static void					PrintToLog(const AudioStreamRangedDescription& inDesc);
+#endif
+	static bool					Sorter(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y);
+
+};
+
+inline bool operator<(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)													{	return	(x.mFormat.mFormatID == y.mFormat.mFormatID) ? 
+																																								(x.mFormat < y.mFormat) && (x.mSampleRateRange < y.mSampleRateRange) :
+																																								(x.mFormat.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormat.mFormatID < y.mFormat.mFormatID); }
+inline bool operator==(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)												{ return (x.mFormat == y.mFormat) && (x.mSampleRateRange == y.mSampleRateRange); }
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool	operator!=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)												{ return !(x == y); }
+inline bool	operator<=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)												{ return (x < y) || (x == y); }
+inline bool	operator>=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)												{ return !(x < y); }
+inline bool	operator>(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)													{ return !((x < y) || (x == y)); }
+#endif
+
+inline bool operator<(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y)													{	return	(x.mFormatID == y.mFormat.mFormatID) ? 
+																																								(x < y.mFormat) && (x.mSampleRate < y.mSampleRateRange.mMinimum) :
+																																								(x.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormatID < y.mFormat.mFormatID); }
+inline bool operator<(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y)													{	return	(x.mFormat.mFormatID == y.mFormatID) ? 
+																																								(x.mFormat < y) && (x.mSampleRateRange.mMinimum < y.mSampleRate) :
+																																								(x.mFormat.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormat.mFormatID < y.mFormatID); }
+inline bool operator==(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y)													{ return (x == y.mFormat) && CAAudioValueRange::ContainsValue(y.mSampleRateRange, x.mSampleRate); }
+inline bool operator==(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y)													{ return (x.mFormat == y) && CAAudioValueRange::ContainsValue(x.mSampleRateRange, y.mSampleRate); }
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool	operator!=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y)													{ return !(x == y); }
+inline bool	operator!=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y)													{ return !(x == y); }
+inline bool	operator<=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y)													{ return (x < y) || (x == y); }
+inline bool	operator<=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y)													{ return (x < y) || (x == y); }
+inline bool	operator>=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y)													{ return !(x < y); }
+inline bool	operator>=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y)													{ return !(x < y); }
+inline bool	operator>(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y)													{ return !((x < y) || (x == y)); }
+inline bool	operator>(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y)													{ return !((x < y) || (x == y)); }
+#endif
+
+//	STL Functors
+struct	CAStreamRangedDescription_EqualToASBD
+:
+	public std::unary_function<AudioStreamRangedDescription, bool>
+{
+			CAStreamRangedDescription_EqualToASBD(const AudioStreamBasicDescription& inFormat)	: mFormat(inFormat) {}
+	bool	operator()(const AudioStreamRangedDescription& x) const								{ return mFormat == x; }
+	
+	AudioStreamBasicDescription	mFormat;
+};
+
+struct	CAStreamRangedDescription_ReverseSort
+:
+	public std::binary_function<AudioStreamRangedDescription, AudioStreamRangedDescription, bool>
+{
+	bool	operator()(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) const	{ return CAStreamRangedDescription::Sorter(x, y); }
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h b/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h
new file mode 100644
index 0000000..d0b7391
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h
@@ -0,0 +1,233 @@
+/*
+     File: CAThreadSafeList.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAThreadSafeList_h__
+#define __CAThreadSafeList_h__
+
+#include "CAAtomicStack.h"
+
+//  linked list of T's
+//	T must define operator ==
+template <class T>
+class TThreadSafeList {
+private:
+	enum EEventType { kAdd, kRemove, kClear };
+	class Node {
+	public:
+		Node *		mNext;
+		EEventType	mEventType;
+		T			mObject;
+		
+		Node *&	next() { return mNext; }
+	};
+
+public:
+	class iterator {
+	public:
+		iterator() { }
+		iterator(Node *n) : mNode(n) { }
+		
+		bool operator == (const iterator &other) const { return this->mNode == other.mNode; }
+		bool operator != (const iterator &other) const { return this->mNode != other.mNode; }
+		
+		T & operator * () const { return mNode->mObject; }
+		
+		iterator & operator ++ () { mNode = mNode->next(); return *this; }	// preincrement
+		iterator operator ++ (int) { iterator tmp = *this; mNode = mNode->next(); return tmp; } // postincrement
+		
+	private:
+		Node *		mNode;
+	};
+	
+	TThreadSafeList() { }
+	~TThreadSafeList()
+	{
+		mActiveList.free_all();
+		mPendingList.free_all();
+		mFreeList.free_all();
+	}
+	
+	// These may be called on any thread
+	
+	void	deferred_add(const T &obj)	// can be called on any thread
+	{
+		Node *node = AllocNode();
+		node->mEventType = kAdd;
+		node->mObject = obj;
+		mPendingList.push_atomic(node);
+		//mPendingList.dump("pending after add");
+	}
+	
+	void	deferred_remove(const T &obj)	// can be called on any thread
+	{
+		Node *node = AllocNode();
+		node->mEventType = kRemove;
+		node->mObject = obj;
+		mPendingList.push_atomic(node);
+		//mPendingList.dump("pending after remove");
+	}
+	
+	void	deferred_clear()					// can be called on any thread
+	{
+		Node *node = AllocNode();
+		node->mEventType = kClear;
+		mPendingList.push_atomic(node);
+	}
+	
+	// These must be called from only one thread
+	
+	void	update()		// must only be called from one thread
+	{
+		NodeStack reversed;
+		Node *event, *node, *next;
+		bool workDone = false;
+		
+		// reverse the events so they are in order
+		event = mPendingList.pop_all();
+		while (event != NULL) {
+			next = event->mNext;
+			reversed.push_NA(event);
+			event = next;
+			workDone = true;
+		}
+		if (workDone) {
+			//reversed.dump("pending popped");
+			//mActiveList.dump("active before update");
+			
+			// now process them
+			while ((event = reversed.pop_NA()) != NULL) {
+				switch (event->mEventType) {
+				case kAdd:
+					{
+						Node **pnode;
+						bool needToInsert = true;
+						for (pnode = mActiveList.phead(); *pnode != NULL; pnode = &node->mNext) {
+							node = *pnode;
+							if (node->mObject == event->mObject) {
+								//printf("already active!!!\n");
+								FreeNode(event);
+								needToInsert = false;
+								break;
+							}
+						}
+						if (needToInsert) {
+							// link the new event in at the end of the active list
+							*pnode = event;
+							event->mNext = NULL;
+						}
+					}
+					break;
+				case kRemove:
+					// find matching node in the active list, remove it
+					for (Node **pnode = mActiveList.phead(); *pnode != NULL; ) {
+						node = *pnode;
+						if (node->mObject == event->mObject) {
+							*pnode = node->mNext;	// remove from linked list
+							FreeNode(node);
+							break;
+						}
+						pnode = &node->mNext;
+					}
+					// dispose the request node
+					FreeNode(event);
+					break;
+				case kClear:
+					for (node = mActiveList.head(); node != NULL; ) {
+						next = node->mNext;
+						FreeNode(node);
+						node = next;
+					}
+					FreeNode(event);
+					break;
+				default:
+					//printf("invalid node type %d!\n", event->mEventType);
+					break;
+				}
+			}
+			//mActiveList.dump("active after update");
+		}
+	}
+	
+	iterator begin() const {
+		//mActiveList.dump("active at begin");
+		return iterator(mActiveList.head());
+	}
+	iterator end() const { return iterator(NULL); }
+
+	
+private:
+	Node *	AllocNode()
+	{
+		Node *node = mFreeList.pop_atomic();
+		if (node == NULL)
+			node = (Node *)CA_malloc(sizeof(Node));
+		return node;
+	}
+	
+	void	FreeNode(Node *node)
+	{
+		mFreeList.push_atomic(node);
+	}
+
+private:
+	class NodeStack : public TAtomicStack<Node> {
+	public:
+		void free_all() {
+			Node *node;
+			while ((node = this->pop_NA()) != NULL)
+				free(node);
+		}
+		
+		Node **	phead() { return &this->mHead; }
+		Node *	head() const { return this->mHead; }
+	};
+
+	NodeStack	mActiveList;	// what's actually in the container - only accessed on one thread
+	NodeStack	mPendingList;	// add or remove requests - threadsafe
+	NodeStack	mFreeList;		// free nodes for reuse - threadsafe
+};
+
+#endif // __CAThreadSafeList_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CATink.h b/libs/appleutility/CoreAudio/PublicUtility/CATink.h
new file mode 100644
index 0000000..f082935
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CATink.h
@@ -0,0 +1,146 @@
+/*
+     File: CATink.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CATink_h__)
+#define __CATink_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//	System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreServices/CoreServices.h>
+#else
+	#include <CoreServices.h>
+#endif
+
+
+//=============================================================================
+//	CATink
+//
+//	A Tink is a small jump island that can make one function appear as if it
+//	has many addresses. Note that Tinks are not supported for 64 bit environments
+//	as the APIs that made tinks useful have been replaced by APIs that do away
+//	with all the reasons for using a tink.
+//=============================================================================
+
+template <class F>
+class CATink
+{
+
+public:
+	CATink(F proc) { Set(proc); }
+	
+	~CATink() { Set((F)0xDEADDEAD); }		// jump to an obviously bad (odd) address if accessed after destruction
+
+#if TARGET_CPU_PPC
+	void Set(F proc)
+	{
+		/*
+			lis		r11,0x1234
+		00000000: 3D601234  lis        r11,4660
+			ori		r11,r11,0x5678
+		00000004: 616B5678  ori        r11,r11,$5678
+			mtctr	r11
+		00000008: 7D6903A6  mtctr      r11
+			bctr
+		0000000C: 4E800420  bctr
+		*/
+		UInt32 p = UInt32(proc);
+		mCode[0] = 0x3D600000 | (p >> 16);
+		mCode[1] = 0x616B0000 | (p & 0xFFFF);
+		mCode[2] = 0x7D6903A6;
+		mCode[3] = 0x4E800420;
+		MakeDataExecutable(mCode, sizeof(mCode));
+	}
+	
+	operator F () { return F(mCode); }
+
+private:
+	UInt32		mCode[4];
+#elif TARGET_CPU_X86
+	void Set(F proc)
+	{
+		/*
+			<tink>:   push   $0x12345678
+			<tink+5>: ret    
+			<tink>:   0x34567868
+			<tink+4>: 0x00e8c312
+		*/
+		UInt32 p = UInt32(proc);
+		mCode[0] = ((p & 0xFFFFFF) << 8) | 0x00000068;
+		mCode[1] = 0xCCCCC300 | (p >> 24);
+		MakeDataExecutable(mCode, sizeof(mCode));
+	}
+
+	operator F () { return F(&mCode[0]); }
+
+private:
+	UInt32		mCode[2];
+#else
+	#warning: CPU not directly supported by CATink
+	
+	// For other CPU's, just wrap the function pointer for now.
+	// this bypasses what we're trying to accomplish with the Tink
+	// (multiple unique "instances" of a function), but it will at
+	// least compile and run.
+
+	void Set(F proc) { mProcPtr = proc; }
+	
+	operator F () { return mProcPtr; }
+private:
+	F			mProcPtr;
+#endif
+
+//	Tinks cannot be allocated in STL Containers, so we make a few key methods private
+private:
+	CATink(){}
+	CATink(const CATink&){}
+	CATink& operator=(const CATink&){ return *this;}
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h b/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h
new file mode 100644
index 0000000..f85f393
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h
@@ -0,0 +1,212 @@
+/*
+     File: CATokenMap.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CATokenMap_h__)
+#define __CATokenMap_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+//  System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+
+//  PublicUtility Includes
+#include "CAMutex.h"
+
+//  Standard Library Includes
+#include <map>
+#include <iterator>
+
+//=============================================================================
+//	CATokenMap
+//=============================================================================
+
+template <class T>
+class	CATokenMap
+{
+
+//	Types
+private:
+	typedef std::map<UInt32, T*>	TokenMap;
+
+//	Construction/Destruction
+public:
+			CATokenMap() : mTokenMap(), mNextToken(256), mTokenMapMutex("CATokenMap Mutex") {}
+			~CATokenMap() {}
+
+//	Operations
+public:
+	bool	Lock()
+	{
+		return mTokenMapMutex.Lock();
+	}
+	
+	void	Unlock()
+	{
+		mTokenMapMutex.Unlock();
+	}
+
+	UInt32	GetToken(T* inObject) const
+	{
+		CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+		UInt32 theAnswer = 0;
+		typename TokenMap::const_iterator i = mTokenMap.begin();
+		while((theAnswer == 0) && (i != mTokenMap.end()))
+		{
+			if(i->second == inObject)
+			{
+				theAnswer = i->first;
+			}
+			std::advance(i, 1);
+		}
+		return theAnswer;
+	}
+	
+	T*		GetObject(UInt32 inToken) const
+	{
+		CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+		typename TokenMap::const_iterator i = mTokenMap.find(inToken);
+		return i != mTokenMap.end() ? i->second : NULL;
+	}
+
+	T*		GetObject(const void* inToken) const
+	{
+		#if __LP64__
+			return GetObject((UInt32)((UInt64)inToken));
+		#else
+			return GetObject((UInt32)inToken);
+		#endif
+	}
+	
+	UInt32	GetNumberObjects() const
+	{
+		CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+		return static_cast<UInt32>(mTokenMap.size());
+	}
+	
+	T*		GetObjectByIndex(UInt32 inIndex) const
+	{
+		T* theAnswer = NULL;
+		CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+		if(inIndex < mTokenMap.size())
+		{
+			typename TokenMap::const_iterator i = mTokenMap.begin();
+			std::advance(i, inIndex);
+			theAnswer = (i != mTokenMap.end()) ? i->second : NULL;
+		}
+		return theAnswer;
+	}
+	
+	void	AddMapping(UInt32 inToken, T* inObject)
+	{
+		CAMutex::Locker theLocker(mTokenMapMutex);
+		typename TokenMap::iterator i = mTokenMap.find(inToken);
+		if(i != mTokenMap.end())
+		{
+			i->second = inObject;
+		}
+		else
+		{
+			mTokenMap.insert(typename TokenMap::value_type(inToken, inObject));
+		}
+	}
+	
+	void	RemoveMapping(UInt32 inToken, T* /*inObject*/)
+	{
+		CAMutex::Locker theLocker(mTokenMapMutex);
+		typename TokenMap::iterator i = mTokenMap.find(inToken);
+		if(i != mTokenMap.end())
+		{
+			mTokenMap.erase(i);
+		}
+	}
+	
+	UInt32	GetNextToken()
+	{
+		return mNextToken++;
+	}
+	
+	UInt32	MapObject(T* inObject)
+	{
+		CAMutex::Locker theLocker(mTokenMapMutex);
+		UInt32 theToken = GetNextToken();
+		mTokenMap.insert(typename TokenMap::value_type(theToken, inObject));
+		return theToken;
+	}
+	
+	void	UnmapObject(T* inObject)
+	{
+		CAMutex::Locker theLocker(mTokenMapMutex);
+		bool isDone = false;
+		typename TokenMap::iterator i = mTokenMap.begin();
+		while(!isDone && (i != mTokenMap.end()))
+		{
+			if(i->second == inObject)
+			{
+				mTokenMap.erase(i);
+				isDone = true;
+			}
+			else
+			{
+				std::advance(i, 1);
+			}
+		}
+	}
+
+//	Implementation
+private:	
+	TokenMap	mTokenMap;
+	UInt32		mNextToken;
+	CAMutex		mTokenMapMutex;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp
new file mode 100644
index 0000000..83bfb8c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp
@@ -0,0 +1,195 @@
+/*
+     File: CAVectorUnit.cpp
+ Abstract: CAVectorUnit.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAVectorUnit.h"
+
+#if !TARGET_OS_WIN32
+	#include <sys/sysctl.h>
+#elif HAS_IPP
+	#include "ippdefs.h"
+	#include "ippcore.h"
+#endif
+
+int gCAVectorUnitType = kVecUninitialized;
+
+#if TARGET_OS_WIN32
+// Use cpuid to check if SSE2 is available.
+// Before calling this function make sure cpuid is available
+static SInt32 IsSSE2Available()
+{
+	int return_value;
+
+	{
+		int r_edx;
+		_asm
+		{
+			mov eax, 0x01
+			cpuid
+			mov r_edx, edx
+		}
+		return_value = (r_edx >> 26) & 0x1;
+	}
+	return return_value;
+}
+
+// Use cpuid to check if SSE3 is available.
+// Before calling this function make sure cpuid is available
+static SInt32 IsSSE3Available()
+{
+	SInt32 return_value;
+
+	{
+		SInt32 r_ecx;
+		_asm
+		{
+			mov eax, 0x01
+			cpuid
+			mov r_ecx, ecx
+		}
+		return_value = r_ecx & 0x1;
+	}
+	return return_value;
+}
+
+// Return true if the cpuid instruction is available.
+// The cpuid instruction is available if bit 21 in the EFLAGS register can be changed
+// This function may not work on Intel CPUs prior to Pentium (didn't test)
+static bool IsCpuidAvailable()
+{
+	SInt32 return_value = 0x0;
+	_asm{
+		pushfd    ;			//push original EFLAGS 
+		pop eax   ;			//get original EFLAGS 
+		mov ecx, eax   ;	//save original EFLAGS 
+		xor eax, 200000h  ; //flip ID bit in EFLAGS 
+		push eax   ;		//save new EFLAGS value on stack 
+		popfd    ;			//replace current EFLAGS value 
+		pushfd    ;			//get new EFLAGS 
+		pop eax   ;			//store new EFLAGS in EAX 
+		xor eax, ecx   ;	 
+		je end_cpuid_identify  ; //can't toggle ID bit
+		mov return_value, 0x1;	
+end_cpuid_identify:
+		nop;
+		}
+		return return_value;
+}
+
+#endif
+
+SInt32	CAVectorUnit_Examine()
+{
+	int result = kVecNone;
+	
+#if TARGET_OS_WIN32
+#if HAS_IPP	
+	// Initialize the static IPP library! This needs to be done before
+	// any IPP function calls, otherwise we may have a performance penalty
+	int status = ippStaticInit();
+	if ( status == ippStsNonIntelCpu )
+	{
+		IppCpuType cpuType = ippGetCpuType();
+		if ( cpuType >= ippCpuSSE || cpuType <= ippCpuSSE42 )
+			ippStaticInitCpu( cpuType );
+	}
+#endif
+	{
+		// On Windows we use cpuid to detect the vector unit because it works on Intel and AMD.
+		// The IPP library does not detect SSE on AMD processors.
+		if (IsCpuidAvailable())
+		{
+			if(IsSSE3Available())
+			{
+				result = kVecSSE3;
+			}
+			else if(IsSSE2Available())
+			{
+				result = kVecSSE2;
+			}
+		}
+	}
+#elif TARGET_OS_MAC
+#if DEBUG
+	if (getenv("CA_NoVector")) {
+		fprintf(stderr, "CA_NoVector set; Vector unit optimized routines will be bypassed\n");
+		return result;
+	} 
+	else
+#endif
+	{
+	#if (TARGET_CPU_PPC || TARGET_CPU_PPC64)
+		int sels[2] = { CTL_HW, HW_VECTORUNIT };
+		int vType = 0; //0 == scalar only
+		size_t length = sizeof(vType);
+		int error = sysctl(sels, 2, &vType, &length, NULL, 0);
+		if (!error && vType > 0)
+			result = kVecAltivec;
+	#elif (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+		static const struct { const char* kName; const int kVectype; } kStringVectypes[] = {
+			{ "hw.optional.avx1_0", kVecAVX1 }, { "hw.optional.sse3", kVecSSE3 }, { "hw.optional.sse2", kVecSSE2 }
+		};
+		static const size_t kNumStringVectypes = sizeof(kStringVectypes)/sizeof(kStringVectypes[0]);
+		int i = 0, answer = 0;
+		while(i != kNumStringVectypes)
+		{
+			size_t length = sizeof(answer);
+			int error = sysctlbyname(kStringVectypes[i].kName, &answer, &length, NULL, 0);
+			if (!error && answer)
+			{
+				result = kStringVectypes[i].kVectype;
+				break;
+			}
+			++i;
+		};
+	#elif CA_ARM_NEON
+		result = kVecNeon;
+	#endif
+	}
+#endif
+	gCAVectorUnitType = result;
+	return result;
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h
new file mode 100644
index 0000000..cf3a16c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h
@@ -0,0 +1,101 @@
+/*
+     File: CAVectorUnit.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAVectorUnit_h__
+#define __CAVectorUnit_h__
+
+#include <TargetConditionals.h>
+#include "CAVectorUnitTypes.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CFBase.h>
+#else
+	#include "CFBase.h"
+#endif
+
+// Unify checks for vector units.
+// Allow setting an environment variable "CA_NoVector" to turn off vectorized code at runtime (very useful for performance testing).
+
+extern int gCAVectorUnitType;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern SInt32 CAVectorUnit_Examine();	// expensive. use GetType() for lazy initialization and caching.
+
+static inline SInt32 CAVectorUnit_GetType()
+{
+	int x = gCAVectorUnitType;
+	return (x != kVecUninitialized) ? x : CAVectorUnit_Examine();
+}
+
+static inline Boolean CAVectorUnit_HasVectorUnit()
+{
+	return CAVectorUnit_GetType() > kVecNone;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+class CAVectorUnit {
+public:
+	static SInt32		GetVectorUnitType() { return CAVectorUnit_GetType(); }
+	static bool			HasVectorUnit() { return GetVectorUnitType() > kVecNone; }
+	static bool			HasAltivec() { return GetVectorUnitType() == kVecAltivec; }
+	static bool			HasSSE2() { return GetVectorUnitType() >= kVecSSE2; }
+	static bool			HasSSE3() { return GetVectorUnitType() >= kVecSSE3; }
+	static bool			HasAVX1() { return GetVectorUnitType() >= kVecAVX1; }
+	static bool			HasNeon() { return GetVectorUnitType() == kVecNeon; }
+};
+#endif
+
+#endif // __CAVectorUnit_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h
new file mode 100644
index 0000000..85ff837
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h
@@ -0,0 +1,60 @@
+/*
+     File: CAVectorUnitTypes.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAVectorUnitTypes_h__
+#define __CAVectorUnitTypes_h__
+
+enum {
+	kVecUninitialized = -1,
+	kVecNone = 0,
+	kVecAltivec = 1,
+	kVecSSE2 = 100,
+	kVecSSE3 = 101,
+	kVecAVX1 = 110,
+	kVecNeon = 200
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp
new file mode 100644
index 0000000..bb6e70c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp
@@ -0,0 +1,482 @@
+/*
+     File: CAVolumeCurve.cpp
+ Abstract: CAVolumeCurve.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#include "CAVolumeCurve.h"
+#include "CADebugMacros.h"
+#include <math.h>
+
+//=============================================================================
+//	CAVolumeCurve
+//=============================================================================
+
+CAVolumeCurve::CAVolumeCurve()
+:
+	mTag(0),
+	mCurveMap(),
+	mIsApplyingTransferFunction(true),
+	mTransferFunction(kPow2Over1Curve),
+	mRawToScalarExponentNumerator(2.0f),
+	mRawToScalarExponentDenominator(1.0f)
+{
+}
+
+CAVolumeCurve::~CAVolumeCurve()
+{
+}
+
+SInt32	CAVolumeCurve::GetMinimumRaw() const
+{
+	SInt32 theAnswer = 0;
+	
+	if(!mCurveMap.empty())
+	{
+		CurveMap::const_iterator theIterator = mCurveMap.begin();
+		theAnswer = theIterator->first.mMinimum;
+	}
+	
+	return theAnswer;
+}
+
+SInt32	CAVolumeCurve::GetMaximumRaw() const
+{
+	SInt32 theAnswer = 0;
+	
+	if(!mCurveMap.empty())
+	{
+		CurveMap::const_iterator theIterator = mCurveMap.begin();
+		std::advance(theIterator, static_cast<int>(mCurveMap.size() - 1));
+		theAnswer = theIterator->first.mMaximum;
+	}
+	
+	return theAnswer;
+}
+
+Float32	CAVolumeCurve::GetMinimumDB() const
+{
+	Float32 theAnswer = 0;
+	
+	if(!mCurveMap.empty())
+	{
+		CurveMap::const_iterator theIterator = mCurveMap.begin();
+		theAnswer = theIterator->second.mMinimum;
+	}
+	
+	return theAnswer;
+}
+
+Float32	CAVolumeCurve::GetMaximumDB() const
+{
+	Float32 theAnswer = 0;
+	
+	if(!mCurveMap.empty())
+	{
+		CurveMap::const_iterator theIterator = mCurveMap.begin();
+		std::advance(theIterator, static_cast<int>(mCurveMap.size() - 1));
+		theAnswer = theIterator->second.mMaximum;
+	}
+	
+	return theAnswer;
+}
+
+void	CAVolumeCurve::SetTransferFunction(UInt32 inTransferFunction)
+{
+	mTransferFunction = inTransferFunction;
+	
+	//	figure out the co-efficients
+	switch(inTransferFunction)
+	{
+		case kLinearCurve:
+			mIsApplyingTransferFunction = false;
+			mRawToScalarExponentNumerator = 1.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+			
+		case kPow1Over3Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 1.0f;
+			mRawToScalarExponentDenominator = 3.0f;
+			break;
+			
+		case kPow1Over2Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 1.0f;
+			mRawToScalarExponentDenominator = 2.0f;
+			break;
+			
+		case kPow3Over4Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 3.0f;
+			mRawToScalarExponentDenominator = 4.0f;
+			break;
+			
+		case kPow3Over2Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 3.0f;
+			mRawToScalarExponentDenominator = 2.0f;
+			break;
+			
+		case kPow2Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 2.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+			
+		case kPow3Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 3.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow4Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 4.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow5Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 5.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow6Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 6.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow7Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 7.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow8Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 8.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow9Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 9.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow10Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 10.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow11Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 11.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		case kPow12Over1Curve:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 12.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+		
+		default:
+			mIsApplyingTransferFunction = true;
+			mRawToScalarExponentNumerator = 2.0f;
+			mRawToScalarExponentDenominator = 1.0f;
+			break;
+	};
+}
+
+void	CAVolumeCurve::AddRange(SInt32 inMinRaw, SInt32 inMaxRaw, Float32 inMinDB, Float32 inMaxDB)
+{
+	CARawPoint theRaw(inMinRaw, inMaxRaw);
+	CADBPoint theDB(inMinDB, inMaxDB);
+	
+	bool isOverlapped = false;
+	bool isDone = false;
+	CurveMap::iterator theIterator = mCurveMap.begin();
+	while((theIterator != mCurveMap.end()) && !isOverlapped && !isDone)
+	{
+		isOverlapped = CARawPoint::Overlap(theRaw, theIterator->first);
+		isDone = theRaw >= theIterator->first;
+		
+		if(!isOverlapped && !isDone)
+		{
+			std::advance(theIterator, 1);
+		}
+	}
+	
+	if(!isOverlapped)
+	{
+		mCurveMap.insert(CurveMap::value_type(theRaw, theDB));
+	}
+	else
+	{
+		DebugMessage("CAVolumeCurve::AddRange: new point overlaps");
+	}
+}
+
+void	CAVolumeCurve::ResetRange()
+{
+	mCurveMap.clear();
+}
+
+bool	CAVolumeCurve::CheckForContinuity() const
+{
+	bool theAnswer = true;
+	
+	CurveMap::const_iterator theIterator = mCurveMap.begin();
+	if(theIterator != mCurveMap.end())
+	{
+		SInt32 theRaw = theIterator->first.mMinimum;
+		Float32 theDB = theIterator->second.mMinimum;
+		do
+		{
+			SInt32 theRawMin = theIterator->first.mMinimum;
+			SInt32 theRawMax = theIterator->first.mMaximum;
+			SInt32 theRawRange = theRawMax - theRawMin;
+			
+			Float32 theDBMin = theIterator->second.mMinimum;
+			Float32 theDBMax = theIterator->second.mMaximum;
+			Float32 theDBRange = theDBMax - theDBMin;
+
+			theAnswer = theRaw == theRawMin;
+			theAnswer = theAnswer && (theDB == theDBMin);
+			
+			theRaw += theRawRange;
+			theDB += theDBRange;
+			
+			std::advance(theIterator, 1);
+		}
+		while((theIterator != mCurveMap.end()) && theAnswer);
+	}
+	
+	return theAnswer;
+}
+
+SInt32	CAVolumeCurve::ConvertDBToRaw(Float32 inDB) const
+{
+	//	clamp the value to the dB range
+	Float32 theOverallDBMin = GetMinimumDB();
+	Float32 theOverallDBMax = GetMaximumDB();
+	
+	if(inDB < theOverallDBMin) inDB = theOverallDBMin;
+	if(inDB > theOverallDBMax) inDB = theOverallDBMax;
+	
+	//	get the first entry in the curve map;
+	CurveMap::const_iterator theIterator = mCurveMap.begin();
+	
+	//	initialize the answer to the minimum raw of the first item in the curve map
+	SInt32 theAnswer = theIterator->first.mMinimum;
+	
+	//	iterate through the curve map until we run out of dB
+	bool isDone = false;
+	while(!isDone && (theIterator != mCurveMap.end()))
+	{
+		SInt32 theRawMin = theIterator->first.mMinimum;
+		SInt32 theRawMax = theIterator->first.mMaximum;
+		SInt32 theRawRange = theRawMax - theRawMin;
+		
+		Float32 theDBMin = theIterator->second.mMinimum;
+		Float32 theDBMax = theIterator->second.mMaximum;
+		Float32 theDBRange = theDBMax - theDBMin;
+		
+		Float32 theDBPerRaw = theDBRange / static_cast<Float32>(theRawRange);
+		
+		//	figure out how many steps we are into this entry in the curve map
+		if(inDB > theDBMax)
+		{
+			//	we're past the end of this one, so add in the whole range for this entry
+			theAnswer += theRawRange;
+		}
+		else
+		{
+			//	it's somewhere within the current entry
+			//	figure out how many steps it is
+			Float32 theNumberRawSteps = inDB - theDBMin;
+			theNumberRawSteps /= theDBPerRaw;
+			
+			//	only move in whole steps
+			theNumberRawSteps = roundf(theNumberRawSteps);
+			
+			//	add this many steps to the answer
+			theAnswer += static_cast<SInt32>(theNumberRawSteps);
+			
+			//	mark that we are done
+			isDone = true;
+		}
+		
+		//	go to the next entry in the curve map
+		std::advance(theIterator, 1);
+	}
+	
+	return theAnswer;
+}
+
+Float32	CAVolumeCurve::ConvertRawToDB(SInt32 inRaw) const
+{
+	Float32 theAnswer = 0;
+	
+	//	clamp the raw value
+	SInt32 theOverallRawMin = GetMinimumRaw();
+	SInt32 theOverallRawMax = GetMaximumRaw();
+	
+	if(inRaw < theOverallRawMin) inRaw = theOverallRawMin;
+	if(inRaw > theOverallRawMax) inRaw = theOverallRawMax;
+	
+	//	figure out how many raw steps need to be taken from the first one
+	SInt32 theNumberRawSteps = inRaw - theOverallRawMin;
+
+	//	get the first item in the curve map
+	CurveMap::const_iterator theIterator = mCurveMap.begin();
+	
+	//	initialize the answer to the minimum dB of the first item in the curve map
+	theAnswer = theIterator->second.mMinimum;
+	
+	//	iterate through the curve map until we run out of steps
+	while((theNumberRawSteps > 0) && (theIterator != mCurveMap.end()))
+	{
+		//	compute some values
+		SInt32 theRawMin = theIterator->first.mMinimum;
+		SInt32 theRawMax = theIterator->first.mMaximum;
+		SInt32 theRawRange = theRawMax - theRawMin;
+		
+		Float32 theDBMin = theIterator->second.mMinimum;
+		Float32 theDBMax = theIterator->second.mMaximum;
+		Float32 theDBRange = theDBMax - theDBMin;
+		
+		Float32 theDBPerRaw = theDBRange / static_cast<Float32>(theRawRange);
+		
+		//	there might be more steps than the current map entry accounts for
+		SInt32 theRawStepsToAdd = std::min(theRawRange, theNumberRawSteps);
+		
+		//	add this many steps worth of db to the answer;
+		theAnswer += theRawStepsToAdd * theDBPerRaw;
+		
+		//	figure out how many steps are left
+		theNumberRawSteps -= theRawStepsToAdd;
+		
+		//	go to the next map entry
+		std::advance(theIterator, 1);
+	}
+	
+	return theAnswer;
+}
+
+Float32	CAVolumeCurve::ConvertRawToScalar(SInt32 inRaw) const
+{
+	//	get some important values
+	Float32	theDBMin = GetMinimumDB();
+	Float32	theDBMax = GetMaximumDB();
+	Float32	theDBRange = theDBMax - theDBMin;
+	SInt32	theRawMin = GetMinimumRaw();
+	SInt32	theRawMax = GetMaximumRaw();
+	SInt32	theRawRange = theRawMax - theRawMin;
+	
+	//	range the raw value
+	if(inRaw < theRawMin) inRaw = theRawMin;
+	if(inRaw > theRawMax) inRaw = theRawMax;
+
+	//	calculate the distance in the range inRaw is
+	Float32 theAnswer = static_cast<Float32>(inRaw - theRawMin) / static_cast<Float32>(theRawRange);
+
+	//	only apply a curve to the scalar values if the dB range is greater than 30
+	if(mIsApplyingTransferFunction && (theDBRange > 30.0f))
+	{
+		theAnswer = powf(theAnswer, mRawToScalarExponentNumerator / mRawToScalarExponentDenominator);
+	}
+
+	return theAnswer;
+}
+
+Float32	CAVolumeCurve::ConvertDBToScalar(Float32 inDB) const
+{
+	SInt32 theRawValue = ConvertDBToRaw(inDB);
+	Float32 theAnswer = ConvertRawToScalar(theRawValue);
+	return theAnswer;
+}
+
+SInt32	CAVolumeCurve::ConvertScalarToRaw(Float32 inScalar) const
+{
+	//	range the scalar value
+	inScalar = std::min(1.0f, std::max(0.0f, inScalar));
+	
+	//	get some important values
+	Float32	theDBMin = GetMinimumDB();
+	Float32	theDBMax = GetMaximumDB();
+	Float32	theDBRange = theDBMax - theDBMin;
+	SInt32	theRawMin = GetMinimumRaw();
+	SInt32	theRawMax = GetMaximumRaw();
+	SInt32	theRawRange = theRawMax - theRawMin;
+	
+	//	have to undo the curve if the dB range is greater than 30
+	if(mIsApplyingTransferFunction && (theDBRange > 30.0f))
+	{
+		inScalar = powf(inScalar, mRawToScalarExponentDenominator / mRawToScalarExponentNumerator);
+	}
+	
+	//	now we can figure out how many raw steps this is
+	Float32 theNumberRawSteps = inScalar * static_cast<Float32>(theRawRange);
+	theNumberRawSteps = roundf(theNumberRawSteps);
+	
+	//	the answer is the minimum raw value plus the number of raw steps
+	SInt32 theAnswer = theRawMin + static_cast<SInt32>(theNumberRawSteps);
+	
+	return theAnswer;
+}
+
+Float32	CAVolumeCurve::ConvertScalarToDB(Float32 inScalar) const
+{
+	SInt32 theRawValue = ConvertScalarToRaw(inScalar);
+	Float32 theAnswer = ConvertRawToDB(theRawValue);
+	return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h
new file mode 100644
index 0000000..4f95446
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h
@@ -0,0 +1,178 @@
+/*
+     File: CAVolumeCurve.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#if !defined(__CAVolumeCurve_h__)
+#define __CAVolumeCurve_h__
+
+//=============================================================================
+//	Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreAudio/CoreAudioTypes.h>
+#else
+	#include <CoreAudioTypes.h>
+#endif
+#include <map>
+
+//=============================================================================
+//	Types
+//=============================================================================
+
+struct CARawPoint
+{
+	SInt32	mMinimum;
+	SInt32	mMaximum;
+	
+	CARawPoint() : mMinimum(0), mMaximum(0) {}
+	CARawPoint(const CARawPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {}
+	CARawPoint(SInt32 inMinimum, SInt32 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {}
+	CARawPoint&	operator=(const CARawPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; }
+	
+	static bool	Overlap(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum > y.mMinimum); }
+};
+
+inline bool	operator<(const CARawPoint& x, const CARawPoint& y) { return x.mMinimum < y.mMinimum; }
+inline bool	operator==(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool	operator!=(const CARawPoint& x, const CARawPoint& y) { return !(x == y); }
+inline bool	operator<=(const CARawPoint& x, const CARawPoint& y) { return (x < y) || (x == y); }
+inline bool	operator>=(const CARawPoint& x, const CARawPoint& y) { return !(x < y); }
+inline bool	operator>(const CARawPoint& x, const CARawPoint& y) { return !((x < y) || (x == y)); }
+
+struct CADBPoint
+{
+	Float32	mMinimum;
+	Float32	mMaximum;
+	
+	CADBPoint() : mMinimum(0), mMaximum(0) {}
+	CADBPoint(const CADBPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {}
+	CADBPoint(Float32 inMinimum, Float32 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {}
+	CADBPoint&	operator=(const CADBPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; }
+	
+	static bool	Overlap(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum >= y.mMinimum); }
+};
+
+inline bool	operator<(const CADBPoint& x, const CADBPoint& y) { return x.mMinimum < y.mMinimum; }
+inline bool	operator==(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool	operator!=(const CADBPoint& x, const CADBPoint& y) { return !(x == y); }
+inline bool	operator<=(const CADBPoint& x, const CADBPoint& y) { return (x < y) || (x == y); }
+inline bool	operator>=(const CADBPoint& x, const CADBPoint& y) { return !(x < y); }
+inline bool	operator>(const CADBPoint& x, const CADBPoint& y) { return !((x < y) || (x == y)); }
+
+//=============================================================================
+//	CAVolumeCurve
+//=============================================================================
+
+class CAVolumeCurve
+{
+
+//	Constants
+public:
+	enum
+	{
+					kLinearCurve		= 0,
+					kPow1Over3Curve		= 1,
+					kPow1Over2Curve		= 2,
+					kPow3Over4Curve		= 3,
+					kPow3Over2Curve		= 4,
+					kPow2Over1Curve		= 5,
+					kPow3Over1Curve		= 6,
+					kPow4Over1Curve		= 7,
+					kPow5Over1Curve		= 8,
+					kPow6Over1Curve		= 9,
+					kPow7Over1Curve		= 10,
+					kPow8Over1Curve		= 11,
+					kPow9Over1Curve		= 12,
+					kPow10Over1Curve	= 13,
+					kPow11Over1Curve	= 14,
+					kPow12Over1Curve	= 15
+	};
+
+//	Construction/Destruction
+public:
+					CAVolumeCurve();
+	virtual			~CAVolumeCurve();
+
+//	Attributes
+public:
+	UInt32			GetTag() const			{ return mTag; }
+	void			SetTag(UInt32 inTag)	{ mTag = inTag; }
+	SInt32			GetMinimumRaw() const;
+	SInt32			GetMaximumRaw() const;
+	Float32			GetMinimumDB() const;
+	Float32			GetMaximumDB() const;
+	
+	void			SetIsApplyingTransferFunction(bool inIsApplyingTransferFunction)  { mIsApplyingTransferFunction = inIsApplyingTransferFunction; }
+	UInt32			GetTransferFunction() const { return mTransferFunction; }
+	void			SetTransferFunction(UInt32 inTransferFunction);
+
+//	Operations
+public:
+	void			AddRange(SInt32 mMinRaw, SInt32 mMaxRaw, Float32 inMinDB, Float32 inMaxDB);
+	void			ResetRange();
+	bool			CheckForContinuity() const;
+	
+	SInt32			ConvertDBToRaw(Float32 inDB) const;
+	Float32			ConvertRawToDB(SInt32 inRaw) const;
+	Float32			ConvertRawToScalar(SInt32 inRaw) const;
+	Float32			ConvertDBToScalar(Float32 inDB) const;
+	SInt32			ConvertScalarToRaw(Float32 inScalar) const;
+	Float32			ConvertScalarToDB(Float32 inScalar) const;
+
+//	Implementation
+private:
+	typedef	std::map<CARawPoint, CADBPoint>	CurveMap;
+	
+	UInt32			mTag;
+	CurveMap		mCurveMap;
+	bool			mIsApplyingTransferFunction;
+	UInt32			mTransferFunction;
+	Float32			mRawToScalarExponentNumerator;
+	Float32			mRawToScalarExponentDenominator;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp
new file mode 100644
index 0000000..c2dbac5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp
@@ -0,0 +1,49 @@
+/*
+     File: CAXException.cpp
+ Abstract: CAXException.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "CAXException.h"
+
+CAXException::WarningHandler CAXException::sWarningHandler = NULL;
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAXException.h b/libs/appleutility/CoreAudio/PublicUtility/CAXException.h
new file mode 100644
index 0000000..90dabe9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAXException.h
@@ -0,0 +1,361 @@
+/*
+     File: CAXException.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __CAXException_h__
+#define __CAXException_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <CoreFoundation/CoreFoundation.h>
+#else
+	#include <ConditionalMacros.h>
+	#include <CoreFoundation.h>
+#endif
+#include "CADebugMacros.h"
+#include <ctype.h>
+//#include <stdio.h>
+#include <string.h>
+
+
+class CAX4CCString {
+public:
+	CAX4CCString(OSStatus error) {
+		// see if it appears to be a 4-char-code
+		UInt32 beErr = CFSwapInt32HostToBig(error);
+		char *str = mStr;
+		memcpy(str + 1, &beErr, 4);
+		if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
+			str[0] = str[5] = '\'';
+			str[6] = '\0';
+		} else if (error > -200000 && error < 200000)
+			// no, format it as an integer
+			snprintf(str, sizeof(mStr), "%d", (int)error);
+		else
+			snprintf(str, sizeof(mStr), "0x%x", (int)error);
+	}
+	const char *get() const { return mStr; }
+	operator const char *() const { return mStr; }
+private:
+	char mStr[16];
+};
+
+class CAX4CCStringNoQuote {
+public:
+	CAX4CCStringNoQuote(OSStatus error) {
+		// see if it appears to be a 4-char-code
+		UInt32 beErr = CFSwapInt32HostToBig(error);
+		char *str = mStr;
+		memcpy(str, &beErr, 4);
+		if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) {
+			str[4] = '\0';
+		} else if (error > -200000 && error < 200000)
+			// no, format it as an integer
+			snprintf(str, sizeof(mStr), "%d", (int)error);
+		else
+			snprintf(str, sizeof(mStr), "0x%x", (int)error);
+	}
+	const char *get() const { return mStr; }
+	operator const char *() const { return mStr; }
+private:
+	char mStr[16];
+};
+
+
+// An extended exception class that includes the name of the failed operation
+class CAXException {
+public:
+	CAXException(const char *operation, OSStatus err) :
+		mError(err)
+		{
+			if (operation == NULL)
+				mOperation[0] = '\0';
+			else if (strlen(operation) >= sizeof(mOperation)) {
+				memcpy(mOperation, operation, sizeof(mOperation) - 1);
+				mOperation[sizeof(mOperation) - 1] = '\0';
+			} else
+
+			strlcpy(mOperation, operation, sizeof(mOperation));
+		}
+	
+	char *FormatError(char *str, size_t strsize) const
+	{
+		return FormatError(str, strsize, mError);
+	}
+	
+	char				mOperation[256];
+	const OSStatus		mError;
+	
+	// -------------------------------------------------
+	
+	typedef void (*WarningHandler)(const char *msg, OSStatus err);
+	
+	static char *FormatError(char *str, size_t strsize, OSStatus error)
+	{
+		strlcpy(str, CAX4CCString(error), strsize);
+		return str;
+	}
+	
+	static void Warning(const char *s, OSStatus error)
+	{
+		if (sWarningHandler)
+			(*sWarningHandler)(s, error);
+	}
+	
+	static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
+private:
+	static WarningHandler	sWarningHandler;
+};
+
+#if	DEBUG || CoreAudio_Debug
+	#define XThrowIfError(error, operation)										\
+		do {																	\
+			OSStatus __err = error;												\
+			if (__err) {														\
+				DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
+				__THROW_STOP;															\
+				throw CAXException(operation, __err);							\
+			}																	\
+		} while (0)
+
+	#define XThrowIf(condition, error, operation)								\
+		do {																	\
+			if (condition) {													\
+				OSStatus __err = error;											\
+				DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
+				__THROW_STOP;															\
+				throw CAXException(operation, __err);							\
+			}																	\
+		} while (0)
+
+	#define XRequireNoError(error, label)										\
+		do {																	\
+			OSStatus __err = error;												\
+			if (__err) {														\
+				DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
+				STOP;															\
+				goto label;														\
+			}																	\
+		} while (0)
+	
+	#define XAssert(assertion)													\
+		do {																	\
+			if (!(assertion)) {													\
+				DebugMessageN3("%s:%d: error: failed assertion: %s", __FILE__, __LINE__, #assertion);		\
+				__ASSERT_STOP;															\
+			}																	\
+		} while (0)
+	
+	#define XAssertNoError(error)												\
+		do {																	\
+			OSStatus __err = error;												\
+			if (__err) {														\
+				DebugMessageN4("%s:%d: error %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
+				STOP;															\
+			}																	\
+		} while (0)
+
+	#define ca_require_noerr(errorCode, exceptionLabel)							\
+		do																		\
+		{																		\
+			int evalOnceErrorCode = (errorCode);								\
+			if ( __builtin_expect(0 != evalOnceErrorCode, 0) )					\
+			{																	\
+				DebugMessageN5("ca_require_noerr: [%s, %d] (goto %s;) %s:%d",	\
+					#errorCode,	evalOnceErrorCode,		 						\
+					#exceptionLabel,											\
+					__FILE__,													\
+					__LINE__);													\
+				goto exceptionLabel;											\
+			}																	\
+		} while ( 0 )
+
+	#define ca_verify_noerr(errorCode)											\
+		do																		\
+		{																		\
+			int evalOnceErrorCode = (errorCode);								\
+			if ( __builtin_expect(0 != evalOnceErrorCode, 0) )					\
+			{																	\
+				DebugMessageN4("ca_verify_noerr: [%s, %d] %s:%d",				\
+					#errorCode,	evalOnceErrorCode,								\
+					__FILE__,													\
+					__LINE__);													\
+			}																	\
+		} while ( 0 )
+
+	#define ca_debug_string(message)											\
+		do																		\
+		{																		\
+			DebugMessageN3("ca_debug_string: %s %s:%d",							\
+				message,														\
+				__FILE__,														\
+				__LINE__);														\
+		} while ( 0 )
+
+
+	#define ca_verify(assertion)												\
+		do																		\
+		{																		\
+			if ( __builtin_expect(!(assertion), 0) )							\
+			{																	\
+				DebugMessageN3("ca_verify: %s %s:%d",							\
+					#assertion,													\
+					__FILE__,													\
+					__LINE__);													\
+			}																	\
+		} while ( 0 )
+
+	#define ca_require(assertion, exceptionLabel)								\
+		do																		\
+		{																		\
+			if ( __builtin_expect(!(assertion), 0) )							\
+			{																	\
+				DebugMessageN4("ca_require: %s %s %s:%d",						\
+					#assertion,													\
+					#exceptionLabel,											\
+					__FILE__,													\
+					__LINE__);													\
+				goto exceptionLabel;											\
+			}																	\
+		} while ( 0 )
+
+   #define ca_check(assertion)													\
+      do																		\
+      {																			\
+          if ( __builtin_expect(!(assertion), 0) )								\
+          {																		\
+              DebugMessageN3("ca_check: %s %s:%d",							\
+                  #assertion,													\
+                  __FILE__,														\
+                  __LINE__);													\
+          }																		\
+      } while ( 0 )
+		
+#else
+	#define XThrowIfError(error, operation)										\
+		do {																	\
+			OSStatus __err = error;												\
+			if (__err) {														\
+				throw CAXException(operation, __err);							\
+			}																	\
+		} while (0)
+
+	#define XThrowIf(condition, error, operation)								\
+		do {																	\
+			if (condition) {													\
+				OSStatus __err = error;											\
+				throw CAXException(operation, __err);							\
+			}																	\
+		} while (0)
+
+	#define XRequireNoError(error, label)										\
+		do {																	\
+			OSStatus __err = error;												\
+			if (__err) {														\
+				goto label;														\
+			}																	\
+		} while (0)
+
+	#define XAssert(assertion)													\
+		do {																	\
+			if (!(assertion)) {													\
+			}																	\
+		} while (0)
+
+	#define XAssertNoError(error)												\
+		do {																	\
+			/*OSStatus __err =*/ error;											\
+		} while (0)
+
+	#define ca_require_noerr(errorCode, exceptionLabel)							\
+		do																		\
+		{																		\
+			if ( __builtin_expect(0 != (errorCode), 0) )						\
+			{																	\
+				goto exceptionLabel;											\
+			}																	\
+		} while ( 0 )
+
+	#define ca_verify_noerr(errorCode)											\
+		do																		\
+		{																		\
+			if ( 0 != (errorCode) )												\
+			{																	\
+			}																	\
+		} while ( 0 )
+
+	#define ca_debug_string(message)
+
+	#define ca_verify(assertion)												\
+		do																		\
+		{																		\
+			if ( !(assertion) )													\
+			{																	\
+			}																	\
+		} while ( 0 )
+
+	#define ca_require(assertion, exceptionLabel)								\
+		do																		\
+		{																		\
+			if ( __builtin_expect(!(assertion), 0) )							\
+			{																	\
+				goto exceptionLabel;											\
+			}																	\
+		} while ( 0 )
+
+   #define ca_check(assertion)													\
+		do																		\
+		{																		\
+			if ( !(assertion) )													\
+			{																	\
+			}																	\
+		} while ( 0 )
+
+
+#endif
+
+#define XThrow(error, operation) XThrowIf(true, error, operation)
+#define XThrowIfErr(error) XThrowIfError(error, #error)
+
+#endif // __CAXException_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp
new file mode 100644
index 0000000..98d868e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp
@@ -0,0 +1,149 @@
+/*
+     File: MatrixMixerVolumes.cpp
+ Abstract: MatrixMixerVolumes.h
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#include "MatrixMixerVolumes.h"
+#include "CAXException.h"
+
+OSStatus	NumberChannels (AudioUnit 		 	au,
+							AudioUnitScope		inScope,
+							AudioUnitElement	inEl,
+							UInt32				&outChans);
+
+
+OSStatus PrintBuses (FILE* file, const char* str, AudioUnit au, AudioUnitScope inScope)
+{
+	OSStatus result;
+	UInt32 busCount;
+	UInt32 theSize = sizeof(busCount);
+
+	ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_ElementCount,	
+							inScope, 0, &busCount, &theSize), home);
+		
+	fprintf (file, "\t%s Elements:\n\t\t", str);
+	for (UInt32 i = 0; i < busCount; ++i) {
+		Float32 val;
+		ca_require_noerr (result = AudioUnitGetParameter (au, kMatrixMixerParam_Enable, inScope, i, &val), home);
+		UInt32 numChans;
+		ca_require_noerr (result = NumberChannels (au, inScope, i, numChans), home);
+		char frameCharStart = (val != 0 ? '[' : '{');
+		char frameCharEnd = (val != 0 ? ']' : '}');
+		fprintf (file, "%d:%c%d, %c%c  ", (int)i, frameCharStart, (int)numChans, (val != 0 ? 'T' : 'F'), frameCharEnd);
+	}
+	fprintf (file, "\n");
+home:
+	return result;
+}
+
+void	PrintMatrixMixerVolumes (FILE* file, AudioUnit au)
+{
+	UInt32 dims[2];
+	UInt32 theSize =  sizeof(UInt32) * 2;
+	Float32 *theVols = NULL;
+	OSStatus result;
+	
+// this call will fail if the unit is NOT initialized as it would present an incomplete state	
+	ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixDimensions,	
+							kAudioUnitScope_Global, 0, dims, &theSize), home);
+
+	theSize = ((dims[0] + 1) * (dims[1] + 1)) * sizeof(Float32);
+	
+	theVols	= static_cast<Float32*> (malloc (theSize));
+	
+	ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixLevels,	
+							kAudioUnitScope_Global, 0, theVols, &theSize), home);
+
+home:
+	if (result) {
+		if (theVols)
+			free(theVols);
+		return;
+	}
+	
+	theSize /= sizeof(Float32);
+	
+	unsigned int inputs = dims[0];
+	unsigned int outputs = dims[1];
+
+	fprintf (file, "\tInput Channels = %d, Output Channels = %d\n", (int)dims[0], (int)dims[1]);
+	PrintBuses (file, "Input", au, kAudioUnitScope_Input);
+	PrintBuses (file, "Output", au, kAudioUnitScope_Output);
+	fprintf (file, "\tGlobal Volume: %.3f\n", theVols [theSize - 1]);
+	for (unsigned int i = 0; i < (inputs + 1); ++i) {
+		if (i < inputs) {
+			fprintf (file, "\t%.3f   ", theVols[(i + 1) * (outputs + 1) - 1]);
+			
+			for (unsigned int j = 0; j < outputs; ++j)
+				fprintf (file, "(%.3f) ", theVols[(i * (outputs  + 1)) + j]);
+		} else {
+			fprintf (file, "\t        ");
+			for (unsigned int j = 0; j < outputs; ++j)
+				fprintf (file, " %.3f  ", theVols[(i * (outputs + 1)) + j]);
+		}
+		fprintf (file, "\n");
+	}
+
+#if 0
+	for (unsigned int i = 0; i < theSize; ++i)
+		printf ("%f, ", theVols[i]);
+#endif
+	free(theVols);
+}
+
+// Utility routine that gets the number of channels from an audio unit
+OSStatus	NumberChannels (AudioUnit 		 	au,
+							AudioUnitScope		inScope,
+							AudioUnitElement	inEl,
+							UInt32				&outChans)
+{
+	AudioStreamBasicDescription desc;
+	UInt32 dataSize = sizeof (AudioStreamBasicDescription);
+	OSStatus result = AudioUnitGetProperty (au, kAudioUnitProperty_StreamFormat,
+								inScope, inEl, 
+								&desc, &dataSize);
+	if (!result)
+		outChans = desc.mChannelsPerFrame;
+	return result;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h
new file mode 100644
index 0000000..06854f0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h
@@ -0,0 +1,71 @@
+/*
+     File: MatrixMixerVolumes.h
+ Abstract: Part of CoreAudio Utility Classes
+  Version: 1.1
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+ 
+*/
+#ifndef __MatrixMixerVolumes_h__
+#define __MatrixMixerVolumes_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+	#include <AudioUnit/AudioUnit.h>
+#else
+	#include <AudioUnit.h>
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+// prints the matrix mixer volumes of a specific audio unit to the given file
+void	 PrintMatrixMixerVolumes (FILE* file, AudioUnit au);				
+
+// prints the mixer volumes for the specific scope of the audio unit
+// results will be printed to the speficied file "file" with identifiying string tag "str"		
+OSStatus PrintBuses (FILE* file, char* str, AudioUnit au, AudioUnitScope inScope);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/libs/appleutility/AUOutputBL.cpp b/libs/appleutility/CoreAudio105/AUOutputBL.cpp
similarity index 100%
rename from libs/appleutility/AUOutputBL.cpp
rename to libs/appleutility/CoreAudio105/AUOutputBL.cpp
diff --git a/libs/appleutility/AUOutputBL.h b/libs/appleutility/CoreAudio105/AUOutputBL.h
similarity index 100%
rename from libs/appleutility/AUOutputBL.h
rename to libs/appleutility/CoreAudio105/AUOutputBL.h
diff --git a/libs/appleutility/AUParamInfo.cpp b/libs/appleutility/CoreAudio105/AUParamInfo.cpp
similarity index 100%
rename from libs/appleutility/AUParamInfo.cpp
rename to libs/appleutility/CoreAudio105/AUParamInfo.cpp
diff --git a/libs/appleutility/AUParamInfo.h b/libs/appleutility/CoreAudio105/AUParamInfo.h
similarity index 100%
rename from libs/appleutility/AUParamInfo.h
rename to libs/appleutility/CoreAudio105/AUParamInfo.h
diff --git a/libs/appleutility/CAAUParameter.cpp b/libs/appleutility/CoreAudio105/CAAUParameter.cpp
similarity index 100%
rename from libs/appleutility/CAAUParameter.cpp
rename to libs/appleutility/CoreAudio105/CAAUParameter.cpp
diff --git a/libs/appleutility/CAAUParameter.h b/libs/appleutility/CoreAudio105/CAAUParameter.h
similarity index 100%
rename from libs/appleutility/CAAUParameter.h
rename to libs/appleutility/CoreAudio105/CAAUParameter.h
diff --git a/libs/appleutility/CAAudioChannelLayout.cpp b/libs/appleutility/CoreAudio105/CAAudioChannelLayout.cpp
similarity index 100%
rename from libs/appleutility/CAAudioChannelLayout.cpp
rename to libs/appleutility/CoreAudio105/CAAudioChannelLayout.cpp
diff --git a/libs/appleutility/CAAudioChannelLayout.h b/libs/appleutility/CoreAudio105/CAAudioChannelLayout.h
similarity index 100%
rename from libs/appleutility/CAAudioChannelLayout.h
rename to libs/appleutility/CoreAudio105/CAAudioChannelLayout.h
diff --git a/libs/appleutility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CoreAudio105/CAAudioChannelLayoutObject.cpp
similarity index 100%
rename from libs/appleutility/CAAudioChannelLayoutObject.cpp
rename to libs/appleutility/CoreAudio105/CAAudioChannelLayoutObject.cpp
diff --git a/libs/appleutility/CAAudioFile.cpp b/libs/appleutility/CoreAudio105/CAAudioFile.cpp
similarity index 100%
rename from libs/appleutility/CAAudioFile.cpp
rename to libs/appleutility/CoreAudio105/CAAudioFile.cpp
diff --git a/libs/appleutility/CAAudioFile.h b/libs/appleutility/CoreAudio105/CAAudioFile.h
similarity index 100%
rename from libs/appleutility/CAAudioFile.h
rename to libs/appleutility/CoreAudio105/CAAudioFile.h
diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CoreAudio105/CAAudioUnit.cpp
similarity index 100%
rename from libs/appleutility/CAAudioUnit.cpp
rename to libs/appleutility/CoreAudio105/CAAudioUnit.cpp
diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CoreAudio105/CAAudioUnit.h
similarity index 100%
rename from libs/appleutility/CAAudioUnit.h
rename to libs/appleutility/CoreAudio105/CAAudioUnit.h
diff --git a/libs/appleutility/CABufferList.cpp b/libs/appleutility/CoreAudio105/CABufferList.cpp
similarity index 100%
rename from libs/appleutility/CABufferList.cpp
rename to libs/appleutility/CoreAudio105/CABufferList.cpp
diff --git a/libs/appleutility/CABufferList.h b/libs/appleutility/CoreAudio105/CABufferList.h
similarity index 100%
rename from libs/appleutility/CABufferList.h
rename to libs/appleutility/CoreAudio105/CABufferList.h
diff --git a/libs/appleutility/CACFDictionary.cpp b/libs/appleutility/CoreAudio105/CACFDictionary.cpp
similarity index 100%
rename from libs/appleutility/CACFDictionary.cpp
rename to libs/appleutility/CoreAudio105/CACFDictionary.cpp
diff --git a/libs/appleutility/CACFDictionary.h b/libs/appleutility/CoreAudio105/CACFDictionary.h
similarity index 100%
rename from libs/appleutility/CACFDictionary.h
rename to libs/appleutility/CoreAudio105/CACFDictionary.h
diff --git a/libs/appleutility/CACFNumber.cpp b/libs/appleutility/CoreAudio105/CACFNumber.cpp
similarity index 100%
rename from libs/appleutility/CACFNumber.cpp
rename to libs/appleutility/CoreAudio105/CACFNumber.cpp
diff --git a/libs/appleutility/CACFNumber.h b/libs/appleutility/CoreAudio105/CACFNumber.h
similarity index 100%
rename from libs/appleutility/CACFNumber.h
rename to libs/appleutility/CoreAudio105/CACFNumber.h
diff --git a/libs/appleutility/CACFString.cpp b/libs/appleutility/CoreAudio105/CACFString.cpp
similarity index 100%
rename from libs/appleutility/CACFString.cpp
rename to libs/appleutility/CoreAudio105/CACFString.cpp
diff --git a/libs/appleutility/CACFString.h b/libs/appleutility/CoreAudio105/CACFString.h
similarity index 100%
rename from libs/appleutility/CACFString.h
rename to libs/appleutility/CoreAudio105/CACFString.h
diff --git a/libs/appleutility/CAComponent.cpp b/libs/appleutility/CoreAudio105/CAComponent.cpp
similarity index 100%
rename from libs/appleutility/CAComponent.cpp
rename to libs/appleutility/CoreAudio105/CAComponent.cpp
diff --git a/libs/appleutility/CAComponent.h b/libs/appleutility/CoreAudio105/CAComponent.h
similarity index 100%
rename from libs/appleutility/CAComponent.h
rename to libs/appleutility/CoreAudio105/CAComponent.h
diff --git a/libs/appleutility/CAComponentDescription.cpp b/libs/appleutility/CoreAudio105/CAComponentDescription.cpp
similarity index 100%
rename from libs/appleutility/CAComponentDescription.cpp
rename to libs/appleutility/CoreAudio105/CAComponentDescription.cpp
diff --git a/libs/appleutility/CAComponentDescription.h b/libs/appleutility/CoreAudio105/CAComponentDescription.h
similarity index 100%
rename from libs/appleutility/CAComponentDescription.h
rename to libs/appleutility/CoreAudio105/CAComponentDescription.h
diff --git a/libs/appleutility/CAConditionalMacros.h b/libs/appleutility/CoreAudio105/CAConditionalMacros.h
similarity index 100%
rename from libs/appleutility/CAConditionalMacros.h
rename to libs/appleutility/CoreAudio105/CAConditionalMacros.h
diff --git a/libs/appleutility/CADebugMacros.cpp b/libs/appleutility/CoreAudio105/CADebugMacros.cpp
similarity index 100%
rename from libs/appleutility/CADebugMacros.cpp
rename to libs/appleutility/CoreAudio105/CADebugMacros.cpp
diff --git a/libs/appleutility/CADebugMacros.h b/libs/appleutility/CoreAudio105/CADebugMacros.h
similarity index 100%
rename from libs/appleutility/CADebugMacros.h
rename to libs/appleutility/CoreAudio105/CADebugMacros.h
diff --git a/libs/appleutility/CAMath.h b/libs/appleutility/CoreAudio105/CAMath.h
similarity index 100%
rename from libs/appleutility/CAMath.h
rename to libs/appleutility/CoreAudio105/CAMath.h
diff --git a/libs/appleutility/CAReferenceCounted.h b/libs/appleutility/CoreAudio105/CAReferenceCounted.h
similarity index 100%
rename from libs/appleutility/CAReferenceCounted.h
rename to libs/appleutility/CoreAudio105/CAReferenceCounted.h
diff --git a/libs/appleutility/CAStreamBasicDescription.cpp b/libs/appleutility/CoreAudio105/CAStreamBasicDescription.cpp
similarity index 100%
rename from libs/appleutility/CAStreamBasicDescription.cpp
rename to libs/appleutility/CoreAudio105/CAStreamBasicDescription.cpp
diff --git a/libs/appleutility/CAStreamBasicDescription.h b/libs/appleutility/CoreAudio105/CAStreamBasicDescription.h
similarity index 100%
rename from libs/appleutility/CAStreamBasicDescription.h
rename to libs/appleutility/CoreAudio105/CAStreamBasicDescription.h
diff --git a/libs/appleutility/CAXException.cpp b/libs/appleutility/CoreAudio105/CAXException.cpp
similarity index 100%
rename from libs/appleutility/CAXException.cpp
rename to libs/appleutility/CoreAudio105/CAXException.cpp
diff --git a/libs/appleutility/CAXException.h b/libs/appleutility/CoreAudio105/CAXException.h
similarity index 100%
rename from libs/appleutility/CAXException.h
rename to libs/appleutility/CoreAudio105/CAXException.h
diff --git a/libs/appleutility/wscript b/libs/appleutility/wscript
index 2c54b28..63a1a1a 100644
--- a/libs/appleutility/wscript
+++ b/libs/appleutility/wscript
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 from waflib.extras import autowaf as autowaf
+from waflib import Options
 import os
 
 libappleutility_sources = [
@@ -7,7 +8,6 @@ libappleutility_sources = [
         'AUParamInfo.cpp',
         'CAAudioChannelLayout.cpp',
         'CAAudioChannelLayoutObject.cpp',
-        'CAAudioFile.cpp',
         'CAAudioUnit.cpp',
         'CAAUParameter.cpp',
         'CABufferList.cpp',
@@ -26,15 +26,28 @@ def options(opt):
 
 def configure(conf):
     autowaf.configure(conf)
+    if conf.env['build_target'] in ['panther', 'tiger', 'leopard'] or (Options.options.ppc and conf.env['build_target'] == 'snowleopard'):
+        conf.env.append_value ('CFLAGS', '-DCOREAUDIO105')
+        conf.env.append_value ('CXXFLAGS', '-DCOREAUDIO105')
+        conf.define ('COREAUDIO105', 1)
 
 def build(bld):
     obj                = bld(features = 'cxx cxxshlib')
     obj.uselib         = 'AUDIOUNITS OSX'
-    obj.source         = libappleutility_sources
+    obj.source         = '';
+    if bld.is_defined('COREAUDIO105'):
+        obj.export_includes = ['CoreAudio105']
+        obj.source += ' CoreAudio105/CAAudioFile.cpp';
+        for src in libappleutility_sources:
+            obj.source += ' CoreAudio105/' + src;
+    else:
+        obj.export_includes = ['CoreAudio/PublicUtility']
+        for src in libappleutility_sources:
+            obj.source += ' CoreAudio/PublicUtility/' + src;
+
     # apple did not write this library with full symbol export control
     # so we need to override any visibility default.
     autowaf.ensure_visible_symbols (obj, True)
-    obj.export_includes = ['.']
     obj.includes       = ['.']
     obj.name           = 'libappleutility'
     obj.target         = 'appleutility'
diff --git a/libs/ardour/MSVClibardour/ardour.vcproj b/libs/ardour/MSVClibardour/ardour.vcproj
index ac51b71..69bf963 100644
--- a/libs/ardour/MSVClibardour/ardour.vcproj
+++ b/libs/ardour/MSVClibardour/ardour.vcproj
@@ -460,6 +460,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\ebur128_analysis.cc"
+				>
+			</File>
+			<File
 				RelativePath="..\element_import_handler.cc"
 				>
 			</File>
@@ -1264,6 +1268,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\transpose.cc"
+				>
+			</File>
+			<File
 				RelativePath="..\unknown_processor.cc"
 				>
 			</File>
@@ -1538,6 +1546,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\ardour\ebur128_analysis.h"
+				>
+			</File>
+			<File
 				RelativePath="..\ardour\element_import_handler.h"
 				>
 			</File>
@@ -2234,6 +2246,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\ardour\transpose.h"
+				>
+			</File>
+			<File
 				RelativePath="..\ardour\trimmable.h"
 				>
 			</File>
diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc
index c62bb7f..924a77e 100644
--- a/libs/ardour/amp.cc
+++ b/libs/ardour/amp.cc
@@ -54,12 +54,7 @@ Amp::Amp (Session& s, std::string type)
 	_gain_control->set_flags (Controllable::GainLike);
 
 	add_control(_gain_control);
-}
-
-std::string
-Amp::display_name() const
-{
-	return _type == "trim" ? _("Trim") : _("Fader");
+	set_display_name (_type == "trim" ? _("Trim") : _("Fader"));
 }
 
 bool
@@ -373,7 +368,7 @@ Amp::inc_gain (gain_t factor, void *src)
 void
 Amp::set_gain (gain_t val, void *)
 {
-	_gain_control->set_value (val);
+	_gain_control->set_value (val, Controllable::NoGroup);
 }
 
 XMLNode&
@@ -401,9 +396,17 @@ Amp::set_state (const XMLNode& node, int version)
 }
 
 void
-Amp::GainControl::set_value (double val)
+Amp::GainControl::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+{
+	if (writable()) {
+		set_value_unchecked (val);
+	}
+}
+
+void
+Amp::GainControl::set_value_unchecked (double val)
 {
-	AutomationControl::set_value (std::max (std::min (val, (double)_desc.upper), (double)_desc.lower));
+	AutomationControl::set_value (std::max (std::min (val, (double)_desc.upper), (double)_desc.lower), Controllable::NoGroup);
 	_amp->session().set_dirty ();
 }
 
diff --git a/libs/ardour/analyser.cc b/libs/ardour/analyser.cc
index fa22bd7..58a8f30 100644
--- a/libs/ardour/analyser.cc
+++ b/libs/ardour/analyser.cc
@@ -31,6 +31,7 @@ using namespace ARDOUR;
 using namespace PBD;
 
 Analyser* Analyser::the_analyser = 0;
+Glib::Threads::Mutex Analyser::analysis_active_lock;
 Glib::Threads::Mutex Analyser::analysis_queue_lock;
 Glib::Threads::Cond  Analyser::SourcesToAnalyse;
 list<boost::weak_ptr<Source> > Analyser::analysis_queue;
@@ -96,6 +97,7 @@ Analyser::work ()
 		boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
 
 		if (afs && afs->length(afs->timeline_position())) {
+			Glib::Threads::Mutex::Lock lm (analysis_active_lock);
 			analyse_audio_file_source (afs);
 		}
 	}
@@ -119,3 +121,11 @@ Analyser::analyse_audio_file_source (boost::shared_ptr<AudioFileSource> src)
 		return;
 	}
 }
+
+void
+Analyser::flush ()
+{
+	Glib::Threads::Mutex::Lock lq (analysis_queue_lock);
+	Glib::Threads::Mutex::Lock la (analysis_active_lock);
+	analysis_queue.clear();
+}
diff --git a/libs/ardour/ardour/amp.h b/libs/ardour/ardour/amp.h
index 62f273e..c92edcc 100644
--- a/libs/ardour/ardour/amp.h
+++ b/libs/ardour/ardour/amp.h
@@ -38,7 +38,9 @@ class LIBARDOUR_API Amp : public Processor {
 public:
 	Amp(Session& s, std::string type = "amp");
 
-	std::string display_name() const;
+	std::string display_name () const { return _display_name; }
+	void set_display_name (const std::string& name) { _display_name = name; }
+
 	std::string type() const { return _type;}
 
 	bool visible () const;
@@ -90,7 +92,8 @@ public:
 			range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db;
 		}
 
-		void set_value (double val);
+		void set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
+		void set_value_unchecked (double);
 
 		double internal_to_interface (double) const;
 		double interface_to_internal (double) const;
@@ -120,6 +123,8 @@ private:
 	float  _current_gain;
 	framepos_t _current_automation_frame;
 
+	std::string _display_name;
+
 	boost::shared_ptr<GainControl> _gain_control;
 
 	/** Buffer that we should use for gain automation */
diff --git a/libs/ardour/ardour/analyser.h b/libs/ardour/ardour/analyser.h
index 8e757ef..fec6bd2 100644
--- a/libs/ardour/ardour/analyser.h
+++ b/libs/ardour/ardour/analyser.h
@@ -40,11 +40,13 @@ class LIBARDOUR_API Analyser {
 	static void init ();
 	static void queue_source_for_analysis (boost::shared_ptr<Source>, bool force);
 	static void work ();
+	static void flush ();
 
   private:
 	static Analyser* the_analyser;
-        static Glib::Threads::Mutex analysis_queue_lock;
-        static Glib::Threads::Cond  SourcesToAnalyse;
+	static Glib::Threads::Mutex analysis_active_lock;
+	static Glib::Threads::Mutex analysis_queue_lock;
+	static Glib::Threads::Cond  SourcesToAnalyse;
 	static std::list<boost::weak_ptr<Source> > analysis_queue;
 
 	static void analyse_audio_file_source (boost::shared_ptr<AudioFileSource>);
diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h
index 73310bd..379eae9 100644
--- a/libs/ardour/ardour/audio_backend.h
+++ b/libs/ardour/ardour/audio_backend.h
@@ -228,6 +228,22 @@ class LIBARDOUR_API AudioBackend : public PortEngine {
     virtual std::vector<DeviceStatus> enumerate_output_devices () const
     { return std::vector<DeviceStatus>(); }
 
+
+	/** An interface to set buffers/period for playback latency.
+	 * useful for ALSA or JACK/ALSA on Linux.
+	 *
+	 * @return true if the backend supports period-size configuration
+	 */
+	virtual bool can_set_period_size () const { return false; }
+
+	/** Returns a vector of supported period-sizes for the given driver */
+	virtual std::vector<uint32_t> available_period_sizes (const std::string& driver) const { return std::vector<uint32_t>(); }
+
+	/** Set the period size to be used.
+	 * must be called before starting the backend.
+	 */
+	virtual int set_peridod_size (uint32_t) { return -1; }
+
 	/**
 	 * @return true if backend supports requesting an update to the device list
 	 * and any cached properties associated with the devices.
@@ -334,6 +350,11 @@ class LIBARDOUR_API AudioBackend : public PortEngine {
      */
     virtual bool can_change_buffer_size_when_running () const = 0;
 
+		/** return true if the backend can measure and update
+		 * systemic latencies without restart.
+		 */
+		virtual bool can_change_systemic_latency_when_running () const { return false; }
+
     /* Set the hardware parameters.
      *
      * If called when the current state is stopped or paused,
@@ -426,6 +447,7 @@ class LIBARDOUR_API AudioBackend : public PortEngine {
     virtual uint32_t     systemic_output_latency () const = 0;
     virtual uint32_t     systemic_midi_input_latency (std::string const) const = 0;
     virtual uint32_t     systemic_midi_output_latency (std::string const) const = 0;
+    virtual uint32_t     period_size () const { return 0; }
 
     /** override this if this implementation returns true from
      * requires_driver_selection()
diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
index 41654a8..e9a5622 100644
--- a/libs/ardour/ardour/audio_unit.h
+++ b/libs/ardour/ardour/audio_unit.h
@@ -34,7 +34,7 @@
 
 #include <AudioUnit/AudioUnit.h>
 #include <AudioUnit/AudioUnitProperties.h>
-#include "appleutility/AUParamInfo.h"
+#include "AUParamInfo.h"
 
 #include <boost/shared_ptr.hpp>
 
@@ -232,6 +232,8 @@ class LIBARDOUR_API AUPluginInfo : public PluginInfo {
 
 	PluginPtr load (Session& session);
 
+	std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
+
 	bool needs_midi_input ();
 	bool is_effect () const;
 	bool is_effect_without_midi_input () const;
@@ -244,7 +246,6 @@ class LIBARDOUR_API AUPluginInfo : public PluginInfo {
 
 	static PluginInfoList* discover (bool scan_only);
 	static bool au_get_crashlog (std::string &msg);
-	static void get_names (CAComponentDescription&, std::string& name, std::string& maker);
 	static std::string stringify_descriptor (const CAComponentDescription&);
 
 	static int load_cached_info ();
diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h
index 345d424..59d5add 100644
--- a/libs/ardour/ardour/audiosource.h
+++ b/libs/ardour/ardour/audiosource.h
@@ -156,6 +156,7 @@ class LIBARDOUR_API AudioSource : virtual public Source,
 	 *  during the handling of the signal.
 	 */
         mutable Glib::Threads::Mutex _peaks_ready_lock;
+        Glib::Threads::Mutex _initialize_peaks_lock;
 
 	int        _peakfile_fd;
 	framecnt_t peak_leftover_cnt;
diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h
index 5d73e4a..0d06568 100644
--- a/libs/ardour/ardour/automation_control.h
+++ b/libs/ardour/ardour/automation_control.h
@@ -81,8 +81,23 @@ public:
 	void start_touch(double when);
 	void stop_touch(bool mark, double when);
 
-	void set_value (double);
+	/* inherited from PBD::Controllable.
+	 * Derived classes MUST call ::writable() to verify
+	 * that writing to the parameter is legal at that time.
+	 */
 	double get_value () const;
+	/* inherited from PBD::Controllable.
+	 * Derived classes MUST call ::writable() to verify
+	 * that writing to the parameter is legal at that time.
+	 */
+	void set_value (double value, PBD::Controllable::GroupControlDisposition group_override);
+	/* automation related value setting */
+	virtual bool writable () const;
+	/* Call to ::set_value() with no test for writable() because
+	 * this is only used by automation playback. We would like
+	 * to make it pure virtual 
+	 */
+	virtual void set_value_unchecked (double val) {}
 
 	double lower()   const { return _desc.lower; }
 	double upper()   const { return _desc.upper; }
@@ -95,13 +110,12 @@ public:
 	const ParameterDescriptor& desc() const { return _desc; }
 
 	const ARDOUR::Session& session() const { return _session; }
+	void commit_transaction (bool did_write);
 
 protected:
-
 	ARDOUR::Session& _session;
 
 	const ParameterDescriptor _desc;
-	XMLNode* _before; //used for undo of touch start/stop pairs.
 };
 
 
diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h
index bc47f2f..37a30ac 100644
--- a/libs/ardour/ardour/automation_list.h
+++ b/libs/ardour/ardour/automation_list.h
@@ -97,6 +97,9 @@ class LIBARDOUR_API AutomationList : public PBD::StatefulDestructible, public Ev
 
 	static PBD::Signal1<void,AutomationList*> AutomationListCreated;
 
+	void start_write_pass (double when);
+	void write_pass_finished (double when, double thinning_factor=0.0);
+
 	void start_touch (double when);
 	void stop_touch (bool mark, double when);
         bool touching() const { return g_atomic_int_get (const_cast<gint*>(&_touching)); }
@@ -110,6 +113,8 @@ class LIBARDOUR_API AutomationList : public PBD::StatefulDestructible, public Ev
 
 	bool operator!= (const AutomationList &) const;
 
+	XMLNode* before () { return _before; }
+	void clear_history ();
   private:
 	void create_curve_if_necessary ();
 	int deserialize_events (const XMLNode&);
@@ -121,6 +126,8 @@ class LIBARDOUR_API AutomationList : public PBD::StatefulDestructible, public Ev
 	gint         _touching;
 
 	bool operator== (const AutomationList&) const { /* not called */ abort(); return false; }
+	XMLNode* _before; //used for undo of touch start/stop pairs.
+
 };
 
 } // namespace
diff --git a/libs/ardour/ardour/butler.h b/libs/ardour/ardour/butler.h
index 7a74fef..44ce784 100644
--- a/libs/ardour/ardour/butler.h
+++ b/libs/ardour/ardour/butler.h
@@ -24,10 +24,6 @@
 
 #include <glibmm/threads.h>
 
-#ifdef PLATFORM_WINDOWS
-#include "pbd/glib_semaphore.h"
-#endif
-
 #include "pbd/crossthread.h"
 #include "pbd/ringbuffer.h"
 #include "pbd/pool.h"
diff --git a/libs/ardour/ardour/caimportable.h b/libs/ardour/ardour/caimportable.h
index 211329b..441008f 100644
--- a/libs/ardour/ardour/caimportable.h
+++ b/libs/ardour/ardour/caimportable.h
@@ -25,7 +25,11 @@
 #include "ardour/types.h"
 #include "ardour/importable_source.h"
 
-#include <appleutility/CAAudioFile.h>
+#ifdef COREAUDIO105
+#include "CAAudioFile.h"
+#else
+#include "CAExtAudioFile.h"
+#endif
 
 namespace ARDOUR {
 
@@ -43,7 +47,11 @@ class LIBARDOUR_API CAImportableSource : public ImportableSource {
 	bool clamped_at_unity () const { return false; }
 
    protected:
+#ifdef COREAUDIO105
 	mutable CAAudioFile af;
+#else
+	mutable CAExtAudioFile af;
+#endif
 };
 
 }
diff --git a/libs/ardour/ardour/control_protocol_manager.h b/libs/ardour/ardour/control_protocol_manager.h
index 0c14d2a..dbbb0c3 100644
--- a/libs/ardour/ardour/control_protocol_manager.h
+++ b/libs/ardour/ardour/control_protocol_manager.h
@@ -65,6 +65,7 @@ class LIBARDOUR_API ControlProtocolManager : public PBD::Stateful, public ARDOUR
 	void load_mandatory_protocols ();
 	void midi_connectivity_established ();
 	void drop_protocols ();
+	void register_request_buffer_factories ();
 
 	int activate (ControlProtocolInfo&);
         int deactivate (ControlProtocolInfo&);
diff --git a/libs/ardour/ardour/coreaudiosource.h b/libs/ardour/ardour/coreaudiosource.h
index d817587..bb00776 100644
--- a/libs/ardour/ardour/coreaudiosource.h
+++ b/libs/ardour/ardour/coreaudiosource.h
@@ -20,7 +20,11 @@
 #ifndef __coreaudio_source_h__
 #define __coreaudio_source_h__
 
-#include <appleutility/CAAudioFile.h>
+#ifdef COREAUDIO105
+#include "CAAudioFile.h"
+#else
+#include "CAExtAudioFile.h"
+#endif
 #include "ardour/audiofilesource.h"
 #include <string>
 
@@ -55,7 +59,11 @@ class LIBARDOUR_API CoreAudioSource : public AudioFileSource {
 	framecnt_t write_unlocked (Sample *, framecnt_t) { return 0; }
 
   private:
+#ifdef COREAUDIO105
 	mutable CAAudioFile af;
+#else
+	mutable CAExtAudioFile af;
+#endif
 	uint16_t n_channels;
 
 	void init_cafile ();
diff --git a/libs/ardour/ardour/debug.h b/libs/ardour/ardour/debug.h
index d7cb27f..6ebf21a 100644
--- a/libs/ardour/ardour/debug.h
+++ b/libs/ardour/ardour/debug.h
@@ -75,7 +75,8 @@ namespace PBD {
 		LIBARDOUR_API extern DebugBits BackendTiming;
 		LIBARDOUR_API extern DebugBits BackendThreads;
 		LIBARDOUR_API extern DebugBits BackendPorts;
-		LIBARDOUR_API extern DebugBits VSTCallbacks;;
+		LIBARDOUR_API extern DebugBits VSTCallbacks;
+		LIBARDOUR_API extern DebugBits FaderPort;
 
 	}
 }
diff --git a/libs/pbd/pbd/glib_semaphore.h b/libs/ardour/ardour/ebur128_analysis.h
similarity index 53%
rename from libs/pbd/pbd/glib_semaphore.h
rename to libs/ardour/ardour/ebur128_analysis.h
index 7f96120..325ed76 100644
--- a/libs/pbd/pbd/glib_semaphore.h
+++ b/libs/ardour/ardour/ebur128_analysis.h
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2010 Tim Mayberry
+    Copyright (C) 2015 Robin Gareus
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -17,41 +17,37 @@
 
 */
 
-#ifndef PBD_GLIB_SEMAPHORE_H
-#define PBD_GLIB_SEMAPHORE_H
+#ifndef __ardour_ebur128_analysis_h__
+#define __ardour_ebur128_analysis_h__
 
-#include <glibmm/threads.h>
+#include "ardour/audioanalyser.h"
+#include "ardour/readable.h"
 
-#include "pbd/libpbd_visibility.h"
-#include "atomic_counter.h"
+namespace ARDOUR {
 
-namespace PBD {
+class AudioSource;
+class Session;
 
-class LIBPBD_API GlibSemaphore
+class LIBARDOUR_API EBUr128Analysis : public AudioAnalyser
 {
-
-	// prevent copying and assignment
-	GlibSemaphore(const GlibSemaphore& sema);
-	GlibSemaphore& operator= (const GlibSemaphore& sema);
-
 public:
+	EBUr128Analysis (float sample_rate);
+	~EBUr128Analysis();
 
-	GlibSemaphore (gint initial_val = 1);
+	int run (Readable*);
 
-	void wait ();
+	float loudness () const { return _loudness; }
+	float loudness_range () const { return _loudness_range; }
 
-	bool try_wait ();
-
-	void post ();
+protected:
+	int use_features (Vamp::Plugin::FeatureSet&, std::ostream*);
 
 private:
-
-	atomic_counter           m_counter;
-	Glib::Threads::Cond      m_cond;
-	Glib::Threads::Mutex     m_mutex;
+	float _loudness;
+	float _loudness_range;
 
 };
 
-} // namespace PBD
+} /* namespace */
 
-#endif // PBD_SEMAPHORE_H
+#endif /* __ardour_audioanalyser_h__ */
diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h
index 2d4a0ad..239f9ad 100644
--- a/libs/ardour/ardour/graph.h
+++ b/libs/ardour/ardour/graph.h
@@ -101,12 +101,12 @@ private:
 	std::vector<GraphNode *> _trigger_queue;
 	pthread_mutex_t          _trigger_mutex;
 
-	PBD::ProcessSemaphore _execution_sem;
+	PBD::Semaphore _execution_sem;
 
 	/** Signalled to start a run of the graph for a process callback */
-	PBD::ProcessSemaphore _callback_start_sem;
-	PBD::ProcessSemaphore _callback_done_sem;
-	PBD::ProcessSemaphore _cleanup_sem;
+	PBD::Semaphore _callback_start_sem;
+	PBD::Semaphore _callback_done_sem;
+	PBD::Semaphore _cleanup_sem;
 
 	/** The number of processing threads that are asleep */
 	volatile gint _execution_tokens;
diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h
index f23517f..6fd214d 100644
--- a/libs/ardour/ardour/ladspa_plugin.h
+++ b/libs/ardour/ardour/ladspa_plugin.h
@@ -105,8 +105,6 @@ class LIBARDOUR_API LadspaPlugin : public ARDOUR::Plugin
 
 	bool has_editor() const { return false; }
 
-	int require_output_streams (uint32_t);
-
 	/* LADSPA extras */
 
 	LADSPA_Properties           properties() const                { return _descriptor->Properties; }
@@ -153,6 +151,7 @@ class LIBARDOUR_API LadspaPluginInfo : public PluginInfo {
 	~LadspaPluginInfo () { };
 
 	PluginPtr load (Session& session);
+	std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
 };
 
 typedef boost::shared_ptr<LadspaPluginInfo> LadspaPluginInfoPtr;
diff --git a/libs/ardour/ardour/legatize.h b/libs/ardour/ardour/legatize.h
index 78b384e..aba6568 100644
--- a/libs/ardour/ardour/legatize.h
+++ b/libs/ardour/ardour/legatize.h
@@ -45,7 +45,7 @@ public:
 	                    Evoral::Beats                        position,
 	                    std::vector<Notes>&                  seqs);
 
-	std::string name() const { return std::string ("legatize"); }
+	std::string name () const { return (_shrink_only ? std::string ("remove overlap") : std::string ("legatize")); }
 
 private:
 	bool _shrink_only;
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index 12e079f..a4cdfcd 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -97,6 +97,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
 	void cleanup ();
 
 	int set_block_size (pframes_t);
+	bool requires_fixed_sized_buffers () const;
 
 	int connect_and_run (BufferSet& bufs,
 	                     ChanMapping in, ChanMapping out,
@@ -120,6 +121,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
 	get_scale_points(uint32_t port_index) const;
 
 	void set_insert_id(PBD::ID id);
+	void set_state_dir (const std::string& d = "");
 
 	int      set_state (const XMLNode& node, int version);
 	bool     save_preset (std::string uri);
@@ -175,9 +177,11 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
 	framepos_t    _next_cycle_start;  ///< Expected start frame of next run cycle
 	double        _next_cycle_speed;  ///< Expected start frame of next run cycle
 	PBD::ID       _insert_id;
+	std::string   _plugin_state_dir;
 	uint32_t      _patch_port_in_index;
 	uint32_t      _patch_port_out_index;
 	URIMap&       _uri_map;
+	bool          _no_sample_accurate_ctrl;
 
 	friend const void* lv2plugin_get_port_value(const char* port_symbol,
 	                                            void*       user_data,
@@ -277,6 +281,9 @@ public:
 	static PluginInfoList* discover ();
 
 	PluginPtr load (Session& session);
+	std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
+	virtual bool in_category (const std::string &c) const;
+	virtual bool is_instrument() const;
 
 	char * _plugin_uri;
 };
diff --git a/libs/ardour/ardour/lxvst_plugin.h b/libs/ardour/ardour/lxvst_plugin.h
index cc6f507..5a35d98 100644
--- a/libs/ardour/ardour/lxvst_plugin.h
+++ b/libs/ardour/ardour/lxvst_plugin.h
@@ -47,6 +47,7 @@ class LIBARDOUR_API LXVSTPluginInfo : public PluginInfo
 	~LXVSTPluginInfo () {}
 
 	PluginPtr load (Session& session);
+	std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
 };
 
 } // namespace ARDOUR
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index 17ebf86..45f0176 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -66,7 +66,6 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream
 	float playback_buffer_load() const;
 	float capture_buffer_load() const;
 
-	void get_playback (MidiBuffer& dst, framecnt_t);
 	void flush_playback (framepos_t, framepos_t);
 
 	void set_record_enabled (bool yn);
@@ -138,6 +137,7 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream
 	static framecnt_t midi_readahead;
 
   private:
+	void get_playback (MidiBuffer& dst, framecnt_t);
 
 	/* The two central butler operations */
 	int do_flush (RunContext context, bool force = false);
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index b2e018c..21c67c2 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -287,7 +287,7 @@ public:
 	boost::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id);
 
 	void insert_silence_at_start (TimeType);
-	void transpose (TimeType, TimeType, int);
+	void transpose (NoteDiffCommand *, const NotePtr, int);
 
 	std::set<WeakNotePtr>& active_notes() { return _active_notes; }
 
diff --git a/libs/ardour/ardour/midi_patch_manager.h b/libs/ardour/ardour/midi_patch_manager.h
index 5ed648b..3c10a3a 100644
--- a/libs/ardour/ardour/midi_patch_manager.h
+++ b/libs/ardour/ardour/midi_patch_manager.h
@@ -22,12 +22,11 @@
 #define MIDI_PATCH_MANAGER_H_
 
 #include "midi++/midnam_patch.h"
+
 #include "pbd/signals.h"
-#include "ardour/session_handle.h"
+#include "pbd/search_path.h"
 
-namespace ARDOUR {
-	class Session;
-}
+#include "ardour/libardour_visibility.h"
 
 namespace MIDI
 {
@@ -35,7 +34,7 @@ namespace MIDI
 namespace Name
 {
 
-class LIBARDOUR_API MidiPatchManager : public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr
+class LIBARDOUR_API MidiPatchManager
 {
 	/// Singleton
 private:
@@ -58,7 +57,9 @@ public:
 		return *_manager;
 	}
 
-	void set_session (ARDOUR::Session*);
+	void add_search_path (const PBD::Searchpath& search_path);
+
+	void remove_search_path (const PBD::Searchpath& search_path);
 
 	boost::shared_ptr<MIDINameDocument> document_by_model(std::string model_name)
 		{ return _documents[model_name]; }
@@ -138,9 +139,14 @@ public:
 	const DeviceNamesByMaker& devices_by_manufacturer() const { return _devices_by_manufacturer; }
 
 private:
-	void session_going_away();
-	void refresh();
-	void add_session_patches();
+	bool add_midi_name_document(const std::string& file_path);
+	bool remove_midi_name_document(const std::string& file_path);
+
+	void add_midnam_files_from_directory(const std::string& directory_path);
+	void remove_midnam_files_from_directory(const std::string& directory_path);
+
+private:
+	PBD::Searchpath                         _search_path;
 
 	MidiNameDocuments                       _documents;
 	MIDINameDocument::MasterDeviceNamesList _master_devices_by_model;
diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h
index 87e89c6..250a58a 100644
--- a/libs/ardour/ardour/midi_region.h
+++ b/libs/ardour/ardour/midi_region.h
@@ -101,7 +101,6 @@ class LIBARDOUR_API MidiRegion : public Region
 	boost::shared_ptr<const MidiModel> model() const;
 
 	void fix_negative_start ();
-	void transpose (int);
 
   protected:
 
diff --git a/libs/ardour/ardour/midi_scene_changer.h b/libs/ardour/ardour/midi_scene_changer.h
index 6eff899..792f4fb 100644
--- a/libs/ardour/ardour/midi_scene_changer.h
+++ b/libs/ardour/ardour/midi_scene_changer.h
@@ -36,7 +36,7 @@ class MIDISceneChanger : public SceneChanger
 	~MIDISceneChanger ();
 
 	void run (framepos_t start, framepos_t end);
-	void set_input_port (MIDI::Port*);
+	void set_input_port (boost::shared_ptr<MidiPort>);
 	void set_output_port (boost::shared_ptr<MidiPort>);
 
 	uint8_t bank_at (framepos_t, uint8_t channel);
@@ -56,7 +56,7 @@ class MIDISceneChanger : public SceneChanger
     private:
 	typedef std::multimap<framepos_t,boost::shared_ptr<MIDISceneChange> > Scenes;
 
-	MIDI::Port* input_port;
+	boost::shared_ptr<MidiPort> input_port;
 	boost::shared_ptr<MidiPort> output_port;
 	Glib::Threads::RWLock scene_lock;
 	Scenes scenes;
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index c48f384..ba41808 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -89,7 +89,9 @@ public:
 			, _route (route)
 		{}
 
-		void set_value (double val);
+		void set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
+		void set_value_unchecked (double);
+		bool writable() const { return true; }
 
 		MidiTrack* _route;
 	};
diff --git a/libs/ardour/ardour/midi_ui.h b/libs/ardour/ardour/midi_ui.h
index 2df5ea0..2f0f7d3 100644
--- a/libs/ardour/ardour/midi_ui.h
+++ b/libs/ardour/ardour/midi_ui.h
@@ -51,6 +51,7 @@ class LIBARDOUR_API MidiControlUI : public AbstractUI<MidiUIRequest>
 	~MidiControlUI ();
 
 	static MidiControlUI* instance() { return _instance; }
+	static void* request_factory (uint32_t num_requests);
 
 	void change_midi_ports ();
 
@@ -61,7 +62,7 @@ class LIBARDOUR_API MidiControlUI : public AbstractUI<MidiUIRequest>
   private:
 	ARDOUR::Session& _session;
 
-	bool midi_input_handler (Glib::IOCondition, AsyncMIDIPort*);
+	bool midi_input_handler (Glib::IOCondition, boost::shared_ptr<AsyncMIDIPort>);
 	void reset_ports ();
 	void clear_ports ();
 
diff --git a/libs/ardour/ardour/midiport_manager.h b/libs/ardour/ardour/midiport_manager.h
index 4e0f98c..2fb5d5a 100644
--- a/libs/ardour/ardour/midiport_manager.h
+++ b/libs/ardour/ardour/midiport_manager.h
@@ -53,18 +53,14 @@ class LIBARDOUR_API MidiPortManager {
      * callback.
      */
 
-    MIDI::Port* midi_input_port () const { return _midi_input_port; }
-    MIDI::Port* midi_output_port () const { return _midi_output_port; }
-    MIDI::Port* mmc_input_port () const { return _mmc_input_port; }
-    MIDI::Port* mmc_output_port () const { return _mmc_output_port; }
-    MIDI::Port* scene_input_port () const { return _scene_input_port; }
-    MIDI::Port* scene_output_port () const { return _scene_output_port; }
+    boost::shared_ptr<ARDOUR::Port> midi_input_port () const { return _midi_in; }
+    boost::shared_ptr<ARDOUR::Port> midi_output_port () const { return _midi_out; }
 
-    boost::shared_ptr<MidiPort> mmc_in() const { return boost::dynamic_pointer_cast<MidiPort>(_mmc_in); }
-    boost::shared_ptr<MidiPort> mmc_out() const { return boost::dynamic_pointer_cast<MidiPort>(_mmc_out); }
+    boost::shared_ptr<ARDOUR::Port> mmc_input_port() const { return boost::dynamic_pointer_cast<MidiPort>(_mmc_in); }
+    boost::shared_ptr<ARDOUR::Port> mmc_output_port() const { return boost::dynamic_pointer_cast<MidiPort>(_mmc_out); }
 
-    boost::shared_ptr<MidiPort> scene_in() const { return boost::dynamic_pointer_cast<MidiPort>(_scene_in); }
-    boost::shared_ptr<MidiPort> scene_out() const { return boost::dynamic_pointer_cast<MidiPort>(_scene_out); }
+    boost::shared_ptr<ARDOUR::Port> scene_input_port() const { return boost::dynamic_pointer_cast<MidiPort>(_scene_in); }
+    boost::shared_ptr<ARDOUR::Port> scene_output_port() const { return boost::dynamic_pointer_cast<MidiPort>(_scene_out); }
 
     /* Ports used for synchronization. These have their I/O handled inside the
      * process callback.
@@ -81,16 +77,7 @@ class LIBARDOUR_API MidiPortManager {
     PBD::Signal0<void> PortsChanged;
 
   protected:
-    /* asynchronously handled ports: MIDI::Port */
-    MIDI::Port* _midi_input_port;
-    MIDI::Port* _midi_output_port;
-    MIDI::Port* _mmc_input_port;
-    MIDI::Port* _mmc_output_port;
-    MIDI::Port* _scene_input_port;
-    MIDI::Port* _scene_output_port;
-    /* these point to the same objects as the members above,
-       but cast to their ARDOUR::Port base class
-    */
+    /* asynchronously handled ports: ARDOUR::AsyncMIDIPort */
     boost::shared_ptr<Port> _midi_in;
     boost::shared_ptr<Port> _midi_out;
     boost::shared_ptr<Port> _mmc_in;
diff --git a/libs/ardour/ardour/monitor_processor.h b/libs/ardour/ardour/monitor_processor.h
index c7d73dc..e971d0a 100644
--- a/libs/ardour/ardour/monitor_processor.h
+++ b/libs/ardour/ardour/monitor_processor.h
@@ -54,7 +54,7 @@ public:
 
 	/* Controllable API */
 
-	void set_value (double v) {
+	void set_value (double v, PBD::Controllable::GroupControlDisposition group_override) {
 		T newval = (T) v;
 		if (newval != _value) {
 			_value = std::max (_lower, std::min (_upper, newval));
@@ -154,6 +154,8 @@ public:
 	bool dim_all () const;
 	bool mono () const;
 
+	bool monitor_active () const { return _monitor_active; }
+
 	PBD::Signal0<void> Changed;
 
 	boost::shared_ptr<PBD::Controllable> channel_cut_control (uint32_t) const;
@@ -198,6 +200,8 @@ private:
 	std::vector<ChannelRecord*> _channels;
 
 	uint32_t             solo_cnt;
+	bool                 _monitor_active;
+
 
 	/* pointers - created first, but managed by boost::shared_ptr<> */
 
@@ -224,6 +228,7 @@ private:
 	MPControl<volatile gain_t>& _solo_boost_level;
 
 	void allocate_channels (uint32_t);
+	void update_monitor_state ();
 };
 
 } /* namespace */
diff --git a/libs/ardour/ardour/pan_controllable.h b/libs/ardour/ardour/pan_controllable.h
index 63ee9d3..77acbee 100644
--- a/libs/ardour/ardour/pan_controllable.h
+++ b/libs/ardour/ardour/pan_controllable.h
@@ -36,7 +36,7 @@ class Pannable;
 
 class LIBARDOUR_API PanControllable : public AutomationControl
 {
-public:
+  public:
 	PanControllable (Session& s, std::string name, Pannable* o, Evoral::Parameter param)
 		: AutomationControl (s,
 		                     param,
@@ -47,9 +47,10 @@ public:
 	{}
 
 	double lower () const;
-	void set_value (double);
+	void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+	void set_value_unchecked (double);
 
-private:
+  private:
 	Pannable* owner;
 };
 
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index de5a5dc..4ebec8d 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -141,6 +141,7 @@ public:
 	void partition (framepos_t start, framepos_t end, bool cut = false);
 	void duplicate (boost::shared_ptr<Region>, framepos_t position, float times);
 	void duplicate (boost::shared_ptr<Region>, framepos_t position, framecnt_t gap, float times);
+	void duplicate_until (boost::shared_ptr<Region>, framepos_t position, framecnt_t gap, framepos_t end);
 	void nudge_after (framepos_t start, framecnt_t distance, bool forwards);
 	boost::shared_ptr<Region> combine (const RegionList&);
 	void uncombine (boost::shared_ptr<Region>);
diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h
index 2554a68..44090c3 100644
--- a/libs/ardour/ardour/plugin.h
+++ b/libs/ardour/ardour/plugin.h
@@ -48,44 +48,9 @@ class Session;
 class BufferSet;
 class PluginInsert;
 class Plugin;
+class PluginInfo;
 
 typedef boost::shared_ptr<Plugin> PluginPtr;
-
-class LIBARDOUR_API PluginInfo {
-  public:
-	PluginInfo () { }
-	virtual ~PluginInfo () { }
-
-	std::string name;
-	std::string category;
-	std::string creator;
-	std::string path;
-	ChanCount n_inputs;
-	ChanCount n_outputs;
-	ARDOUR::PluginType type;
-
-	std::string unique_id;
-
-	virtual PluginPtr load (Session& session) = 0;
-	virtual bool is_instrument() const;
-
-	/* NOTE: this block of virtual methods looks like the interface
-	   to a Processor, but Plugin does not inherit from Processor.
-	   It is therefore not required that these precisely match
-	   the interface, but it is likely that they will evolve together.
-	*/
-
-	/* this returns true if the plugin can change its inputs or outputs on demand.
-	   LADSPA, LV2 and VST plugins cannot do this. AudioUnits can.
-	*/
-
-	virtual bool reconfigurable_io() const { return false; }
-
-  protected:
-	friend class PluginManager;
-	uint32_t index;
-};
-
 typedef boost::shared_ptr<PluginInfo> PluginInfoPtr;
 typedef std::list<PluginInfoPtr> PluginInfoList;
 
@@ -100,6 +65,7 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent
 	virtual int set_state (const XMLNode &, int version);
 
 	virtual void set_insert_id (PBD::ID id) {}
+	virtual void set_state_dir (const std::string& d = "") {}
 
 	virtual std::string unique_id() const = 0;
 	virtual const char * label() const = 0;
@@ -142,17 +108,17 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent
 	void monitoring_changed ();
 
 	struct PresetRecord {
-	    PresetRecord () : number (-1), user (true) {}
-	    PresetRecord (const std::string& u, const std::string& l, int n = -1, bool s = true) : uri (u), label (l), number (n), user (s)  {}
+	    PresetRecord () : valid (false) {}
+	    PresetRecord (const std::string& u, const std::string& l, bool s = true) : uri (u), label (l), user (s), valid (true)  {}
 
 	    bool operator!= (PresetRecord const & a) const {
-		    return number != a.number || uri != a.uri || label != a.label;
+		    return uri != a.uri || label != a.label;
 	    }
 
 	    std::string uri;
 	    std::string label;
-	    int number; // if <0, invalid
 	    bool user;
+	    bool valid;
 	};
 
 	PresetRecord save_preset (std::string);
@@ -205,13 +171,23 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent
 	PBD::Signal0<void> PresetAdded;
 	PBD::Signal0<void> PresetRemoved;
 
+	/** Emitted when any preset has been changed */
+	static PBD::Signal2<void, std::string, Plugin*> PresetsChanged;
+
 	/** Emitted when a preset has been loaded */
 	PBD::Signal0<void> PresetLoaded;
 
+	/** Emitted when a parameter is altered in a way that may have
+	 *  changed the settings with respect to any loaded preset.
+	 */
+	PBD::Signal0<void> PresetDirty;
+
 	virtual bool has_editor () const = 0;
 
-	/** Emitted when any parameter changes */
-	PBD::Signal2<void, uint32_t, float> ParameterChanged;
+	/** Emitted when a parameter is altered by something outside of our
+	 * control, most typically a Plugin GUI/editor
+	 */
+	PBD::Signal2<void, uint32_t, float> ParameterChangedExternally;
 
 	virtual bool configure_io (ChanCount /*in*/, ChanCount /*out*/) { return true; }
 
@@ -272,9 +248,18 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent
 protected:
 
 	friend class PluginInsert;
+	friend class Session;
 
+	/* Called when a parameter of the plugin is changed outside of this
+	 * host's control (typical via a plugin's own GUI/editor)
+	 */
+	void parameter_changed_externally (uint32_t which, float val);
+
+	/* should be overridden by plugin API specific derived types to
+	 * actually implement changing the parameter. The derived type should
+	 * call this after the change is made.
+	 */
 	virtual void set_parameter (uint32_t which, float val);
-	virtual void set_parameter_automated (uint32_t which, float val);
 
 	/** Do the actual saving of the current plugin settings to a preset of the provided name.
 	 *  Should return a URI on success, or an empty string on failure.
@@ -294,6 +279,8 @@ private:
 	/** Fill _presets with our presets */
 	virtual void find_presets () = 0;
 
+	void update_presets (std::string src_unique_id, Plugin* src );
+
 	/** Add state to an existing XMLNode */
 	virtual void add_state (XMLNode *) const = 0;
 
@@ -304,11 +291,70 @@ private:
 	PresetRecord _last_preset;
 	bool _parameter_changed_since_last_preset;
 
+	PBD::ScopedConnection _preset_connection;
+
 	void resolve_midi ();
 };
 
+struct PluginPreset {
+	PluginInfoPtr   _pip;
+	Plugin::PresetRecord _preset;
+
+	PluginPreset (PluginInfoPtr pip, const Plugin::PresetRecord *preset = NULL)
+		: _pip (pip)
+	{
+		if (preset) {
+			_preset.uri    = preset->uri;
+			_preset.label  = preset->label;
+			_preset.user   = preset->user;
+			_preset.valid  = preset->valid;
+		}
+	}
+};
+
+typedef boost::shared_ptr<PluginPreset> PluginPresetPtr;
+typedef std::list<PluginPresetPtr> PluginPresetList;
+
 PluginPtr find_plugin(ARDOUR::Session&, std::string unique_id, ARDOUR::PluginType);
 
+class LIBARDOUR_API PluginInfo {
+  public:
+	PluginInfo () { }
+	virtual ~PluginInfo () { }
+
+	std::string name;
+	std::string category;
+	std::string creator;
+	std::string path;
+	ChanCount n_inputs;
+	ChanCount n_outputs;
+	ARDOUR::PluginType type;
+
+	std::string unique_id;
+
+	virtual PluginPtr load (Session& session) = 0;
+	virtual bool is_instrument() const;
+	virtual bool in_category (const std::string &) const { return false; }
+
+	virtual std::vector<Plugin::PresetRecord> get_presets (bool user_only) const = 0;
+
+	/* NOTE: this block of virtual methods looks like the interface
+	   to a Processor, but Plugin does not inherit from Processor.
+	   It is therefore not required that these precisely match
+	   the interface, but it is likely that they will evolve together.
+	*/
+
+	/* this returns true if the plugin can change its inputs or outputs on demand.
+	   LADSPA, LV2 and VST plugins cannot do this. AudioUnits can.
+	*/
+
+	virtual bool reconfigurable_io() const { return false; }
+
+  protected:
+	friend class PluginManager;
+	uint32_t index;
+};
+
 } // namespace ARDOUR
 
 #endif /* __ardour_plugin_h__ */
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index 8788778..6b434be 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -54,6 +54,7 @@ class LIBARDOUR_API PluginInsert : public Processor
 	XMLNode& get_state(void);
 	int set_state(const XMLNode&, int version);
 	void update_id (PBD::ID);
+	void set_state_dir (const std::string& d = "");
 
 	void run (BufferSet& in, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);
 	void silence (framecnt_t nframes);
@@ -94,8 +95,10 @@ class LIBARDOUR_API PluginInsert : public Processor
 		               const ParameterDescriptor&        desc,
 		               boost::shared_ptr<AutomationList> list=boost::shared_ptr<AutomationList>());
 
-		void set_value (double val);
+		void set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
+		void set_value_unchecked (double);
 		double get_value (void) const;
+		void catch_up_with_external_value (double val);
 		XMLNode& get_state();
 
 	private:
@@ -110,8 +113,8 @@ class LIBARDOUR_API PluginInsert : public Processor
 		                       const ParameterDescriptor&        desc,
 		                       boost::shared_ptr<AutomationList> list=boost::shared_ptr<AutomationList>());
 
-		void set_value (const Variant& val);
-		void set_value (double val);
+		void set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
+		void set_value_unchecked (double);
 		double get_value (void) const;
 		XMLNode& get_state();
 
@@ -164,10 +167,9 @@ class LIBARDOUR_API PluginInsert : public Processor
 	/* disallow copy construction */
 	PluginInsert (const PluginInsert&);
 
-	void parameter_changed (uint32_t, float);
+	void parameter_changed_externally (uint32_t, float);
 
 	void  set_parameter (Evoral::Parameter param, float val);
-	float get_parameter (Evoral::Parameter param);
 
 	float default_parameter_value (const Evoral::Parameter& param);
 
diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h
index 2c081dd..e25a268 100644
--- a/libs/ardour/ardour/plugin_manager.h
+++ b/libs/ardour/ardour/plugin_manager.h
@@ -78,6 +78,8 @@ class LIBARDOUR_API PluginManager : public boost::noncopyable {
 
 	/** plugins were added to or removed from one of the PluginInfoLists */
 	PBD::Signal0<void> PluginListChanged;
+	/** Plugin Hidden/Favorite status changed */
+	PBD::Signal0<void> PluginStatusesChanged;
 
   private:
 	struct PluginStatus {
diff --git a/libs/ardour/ardour/proxy_controllable.h b/libs/ardour/ardour/proxy_controllable.h
index b2f230e..c60f5f1 100644
--- a/libs/ardour/ardour/proxy_controllable.h
+++ b/libs/ardour/ardour/proxy_controllable.h
@@ -31,7 +31,7 @@ namespace ARDOUR {
 */
 
 class LIBARDOUR_API ProxyControllable : public PBD::Controllable {
-public:
+  public:
 	ProxyControllable (const std::string& name, PBD::Controllable::Flag flags,
 			   boost::function1<bool,double> setter,
 			   boost::function0<double> getter)
@@ -40,7 +40,7 @@ public:
 		, _getter (getter)
 	{}
 
-	void set_value (double v) { if (_setter (v)) { Changed(); /* EMIT SIGNAL */ } }
+	void set_value (double v, PBD::Controllable::GroupControlDisposition /*group_override*/) { if (_setter (v)) { Changed(); /* EMIT SIGNAL */ } }
 	double get_value () const { return _getter (); }
 
 	double internal_to_user (double i) const { return accurate_coefficient_to_dB (i);}
@@ -51,7 +51,7 @@ public:
 		return std::string(theBuf);
 	}
 
-private:
+  private:
 	boost::function1<bool,double> _setter;
 	boost::function0<double> _getter;
 };
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index 0c155e2..39f7709 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -161,6 +161,7 @@ CONFIG_VARIABLE (bool, stop_recording_on_xrun, "stop-recording-on-xrun", false)
 CONFIG_VARIABLE (bool, create_xrun_marker, "create-xrun-marker", true)
 CONFIG_VARIABLE (bool, stop_at_session_end, "stop-at-session-end", false)
 CONFIG_VARIABLE (bool, seamless_loop, "seamless-loop", false)
+CONFIG_VARIABLE (float, preroll_seconds, "preroll-seconds", 1.0f)
 #ifdef USE_TRACKS_CODE_FEATURES
 CONFIG_VARIABLE (bool, loop_is_mode, "loop-is-mode", true)
 #else
@@ -236,6 +237,7 @@ CONFIG_VARIABLE (bool, discover_vst_on_start, "discover-vst-on-start", false)
 CONFIG_VARIABLE (bool, verbose_plugin_scan, "verbose-plugin-scan", true)
 CONFIG_VARIABLE (int, vst_scan_timeout, "vst-scan-timeout", 600) /* deciseconds, per plugin, <= 0 no timeout */
 CONFIG_VARIABLE (bool, discover_audio_units, "discover-audio-units", false)
+CONFIG_VARIABLE (bool, open_gui_after_adding_plugin, "open-gui-after-adding-plugin", true)
 
 /* custom user plugin paths */
 CONFIG_VARIABLE (std::string, plugin_path_vst, "plugin-path-vst", "@default@")
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index 60999bf..a8a1475 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -212,6 +212,7 @@ class LIBARDOUR_API Region
 	void set_length (framecnt_t);
 	void set_start (framepos_t);
 	void set_position (framepos_t);
+	void set_initial_position (framepos_t);
 	void special_set_position (framepos_t);
 	virtual void update_after_tempo_map_change ();
 	void nudge_position (frameoffset_t);
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 001accb..2086f32 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -101,7 +101,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 	void set_comment (std::string str, void *src);
 
 	bool set_name (const std::string& str);
-	static void set_name_in_state (XMLNode &, const std::string &);
+	static void set_name_in_state (XMLNode &, const std::string &, bool rename_playlist = true);
 
         uint32_t order_key () const;
         bool has_order_key () const;
@@ -383,22 +383,45 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 
 	/* Controls (not all directly owned by the Route */
 
+	class RouteAutomationControl : public AutomationControl {
+	public:
+		RouteAutomationControl (const std::string& name,
+		                        AutomationType atype,
+		                        boost::shared_ptr<AutomationList> alist,
+		                        boost::shared_ptr<Route> route);
+
+		void set_value (double val, PBD::Controllable::GroupControlDisposition group_override) {
+			boost::shared_ptr<Route> r = _route.lock();
+			if (r) {
+				r->set_control (*this, val, group_override);
+			}
+		}
+
+	protected:
+		friend class Route;
+
+		void route_set_value (double val) {
+			AutomationControl::set_value (val, Controllable::NoGroup);
+		}
+
+		boost::weak_ptr<Route> _route;
+	};
+
 	boost::shared_ptr<AutomationControl> get_control (const Evoral::Parameter& param);
 
-	class SoloControllable : public AutomationControl {
+	class SoloControllable : public RouteAutomationControl {
 	public:
 		SoloControllable (std::string name, boost::shared_ptr<Route>);
-		void set_value (double);
+		void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+		void set_value_unchecked (double);
 		double get_value () const;
-
-	private:
-		boost::weak_ptr<Route> _route;
 	};
 
-	struct MuteControllable : public AutomationControl {
+	struct MuteControllable : public RouteAutomationControl {
 	public:
 		MuteControllable (std::string name, boost::shared_ptr<Route>);
-		void set_value (double);
+		void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+		void set_value_unchecked (double);
 		double get_value () const;
 
 		/* Pretend to change value, but do not affect actual route mute. */
@@ -408,6 +431,19 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 		boost::weak_ptr<Route> _route;
 	};
 
+	class LIBARDOUR_API PhaseControllable : public RouteAutomationControl {
+	public:
+		PhaseControllable (std::string name, boost::shared_ptr<Route>);
+		void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
+		void set_channel (uint32_t);
+		double get_value () const;
+		uint32_t channel() const;
+	private:
+		uint32_t _current_phase;
+	};
+
+	void set_control (RouteAutomationControl&, double val, PBD::Controllable::GroupControlDisposition group_override);
+
 	boost::shared_ptr<SoloControllable> solo_control() const {
 		return _solo_control;
 	}
@@ -420,6 +456,10 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 		return _mute_master;
 	}
 
+	boost::shared_ptr<PhaseControllable> phase_control() const {
+		return _phase_control;
+	}
+
 	/* Route doesn't own these items, but sub-objects that it does own have them
 	   and to make UI code a bit simpler, we provide direct access to them
 	   here.
@@ -441,6 +481,50 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 	boost::shared_ptr<Processor> the_instrument() const;
         InstrumentInfo& instrument_info() { return _instrument_info; }
 
+        /* "well-known" controls for panning. Any or all of these may return
+         * null.
+         */
+
+        boost::shared_ptr<AutomationControl> pan_azimuth_control() const;
+        boost::shared_ptr<AutomationControl> pan_elevation_control() const;
+        boost::shared_ptr<AutomationControl> pan_width_control() const;
+        boost::shared_ptr<AutomationControl> pan_frontback_control() const;
+        boost::shared_ptr<AutomationControl> pan_lfe_control() const;
+
+        /* "well-known" controls for an EQ in this route. Any or all may
+         * be null. eq_band_cnt() must return 0 if there is no EQ present.
+         * Passing an @param band value >= eq_band_cnt() will guarantee the
+         * return of a null ptr (or an empty string for eq_band_name()).
+         */
+        uint32_t eq_band_cnt () const;
+        std::string eq_band_name (uint32_t) const;
+        boost::shared_ptr<AutomationControl> eq_gain_controllable (uint32_t band) const;
+        boost::shared_ptr<AutomationControl> eq_freq_controllable (uint32_t band) const;
+        boost::shared_ptr<AutomationControl> eq_q_controllable (uint32_t band) const;
+        boost::shared_ptr<AutomationControl> eq_shape_controllable (uint32_t band) const;
+        boost::shared_ptr<AutomationControl> eq_enable_controllable () const;
+        boost::shared_ptr<AutomationControl> eq_hpf_controllable () const;
+
+        /* "well-known" controls for a compressor in this route. Any or all may
+         * be null.
+         */
+        boost::shared_ptr<AutomationControl> comp_enable_controllable () const;
+        boost::shared_ptr<AutomationControl> comp_threshold_controllable () const;
+        boost::shared_ptr<AutomationControl> comp_speed_controllable () const;
+        boost::shared_ptr<AutomationControl> comp_mode_controllable () const;
+        boost::shared_ptr<AutomationControl> comp_makeup_controllable () const;
+        boost::shared_ptr<AutomationControl> comp_redux_controllable () const;
+
+        /* @param mode must be supplied by the comp_mode_controllable(). All other values
+         * result in undefined behaviour
+         */
+        std::string comp_mode_name (uint32_t mode) const;
+        /* @param mode - as for comp mode name. This returns the name for the
+         * parameter/control accessed via comp_speed_controllable(), which can
+         * be mode dependent.
+         */
+        std::string comp_speed_name (uint32_t mode) const;
+
 	void protect_automation ();
 
 	enum {
@@ -468,7 +552,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 	bool has_external_redirects() const;
 
         /* can only be executed by a route for which is_monitor() is true
-   	   (i.e. the monitor out)
+	   (i.e. the monitor out)
         */
         void monitor_run (framepos_t start_frame, framepos_t end_frame,
 			  pframes_t nframes, int declick);
@@ -558,6 +642,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 	boost::shared_ptr<SoloControllable> _solo_control;
 	boost::shared_ptr<MuteControllable> _mute_control;
 	boost::shared_ptr<MuteMaster> _mute_master;
+	boost::shared_ptr<PhaseControllable> _phase_control;
 
 	virtual void act_on_mute () {}
 
@@ -601,7 +686,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 	int set_state_2X (const XMLNode&, int);
 	void set_processor_state_2X (XMLNodeList const &, int);
 
- 	uint32_t _order_key;
+	uint32_t _order_key;
 	bool _has_order_key;
         uint32_t _remote_control_id;
 
@@ -636,6 +721,8 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 	void setup_invisible_processors ();
 	void unpan ();
 
+	void set_plugin_state_dir (boost::weak_ptr<Processor>, const std::string&);
+
 	boost::shared_ptr<CapturingProcessor> _capturing_processor;
 
 	/** A handy class to keep processor state while we attempt a reconfiguration
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 054862c..385eadb 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -57,11 +57,13 @@
 #include "ardour/chan_count.h"
 #include "ardour/delivery.h"
 #include "ardour/interthread_info.h"
+#include "ardour/location.h"
+#include "ardour/monitor_processor.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/session_configuration.h"
 #include "ardour/session_event.h"
-#include "ardour/location.h"
 #include "ardour/interpolation.h"
+#include "ardour/route.h"
 #include "ardour/route_graph.h"
 
 
@@ -173,6 +175,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	virtual ~Session ();
 
 	static int get_info_from_path (const std::string& xmlpath, float& sample_rate, SampleFormat& data_format);
+	static std::string get_snapshot_from_instant (const std::string& session_dir);
 
 	std::string path() const { return _path; }
 	std::string name() const { return _name; }
@@ -180,8 +183,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	std::string raid_path () const;
 	bool path_is_within_session (const std::string&);
 
-	void set_snap_name ();
-
 	bool writable() const { return _writable; }
 	void set_dirty ();
 	void set_clean ();
@@ -218,7 +219,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	std::string new_audio_source_path_for_embedded (const std::string& existing_path);
 	std::string new_audio_source_path (const std::string&, uint32_t nchans, uint32_t chan, bool destructive, bool take_required);
 	std::string new_midi_source_path (const std::string&);
-	RouteList new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name);
+	RouteList new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name, PlaylistDisposition pd = NewPlaylist);
+	RouteList new_route_from_template (uint32_t how_many, XMLNode&, const std::string& name, PlaylistDisposition pd = NewPlaylist);
 	std::vector<std::string> get_paths_for_new_sources (bool allow_replacing, const std::string& import_file_path, uint32_t channels);
 
 	int bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,std::string)> callback);
@@ -378,8 +380,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	void goto_start ();
 	void use_rf_shuttle_speed ();
 	void allow_auto_play (bool yn);
-	void request_transport_speed (double speed, bool as_default = false);
-	void request_transport_speed_nonzero (double, bool as_default = false);
+	void request_transport_speed (double speed, bool as_default = true);
+	void request_transport_speed_nonzero (double, bool as_default = true);
 	void request_overwrite_buffer (Track *);
 	void adjust_playback_buffering();
 	void adjust_capture_buffering();
@@ -459,7 +461,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	int save_as (SaveAs&);
 	int save_state (std::string snapshot_name, bool pending = false, bool switch_to_snapshot = false, bool template_only = false);
 	int restore_state (std::string snapshot_name);
-	int save_template (std::string template_name);
+	int save_template (std::string template_name, bool replace_existing = false);
 	int save_history (std::string snapshot_name = "");
 	int restore_history (std::string snapshot_name);
 	void remove_state (std::string snapshot_name);
@@ -749,6 +751,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	PBD::Signal1<void,bool> SoloActive;
 	PBD::Signal0<void> SoloChanged;
 	PBD::Signal0<void> IsolatedChanged;
+	PBD::Signal0<void> MonitorChanged;
 
 	PBD::Signal0<void> session_routes_reconnected;
 
@@ -757,6 +760,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	void add_monitor_section ();
 	void reset_monitor_section ();
 	void remove_monitor_section ();
+	bool monitor_active() const { return (_monitor_out && _monitor_out->monitor_control () && _monitor_out->monitor_control ()->monitor_active()); }
 
 	boost::shared_ptr<Route> monitor_out() const { return _monitor_out; }
 	boost::shared_ptr<Route> master_out() const { return _master_out; }
@@ -1009,27 +1013,26 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
 	SceneChanger* scene_changer() const { return _scene_changer; }
 
-	boost::shared_ptr<Port> ltc_input_port() const;
-	boost::shared_ptr<Port> ltc_output_port() const;
-
-	boost::shared_ptr<IO> ltc_input_io() { return _ltc_input; }
-	boost::shared_ptr<IO> ltc_output_io() { return _ltc_output; }
+	/* asynchronous MIDI control ports */
 
-	MIDI::Port* midi_input_port () const;
-	MIDI::Port* midi_output_port () const;
-	MIDI::Port* mmc_output_port () const;
-	MIDI::Port* mmc_input_port () const;
+	boost::shared_ptr<Port> midi_input_port () const;
+	boost::shared_ptr<Port> midi_output_port () const;
+	boost::shared_ptr<Port> mmc_output_port () const;
+	boost::shared_ptr<Port> mmc_input_port () const;
+	boost::shared_ptr<Port> scene_input_port () const;
+	boost::shared_ptr<Port> scene_output_port () const;
 
-	MIDI::Port* scene_input_port () const;
-	MIDI::Port* scene_output_port () const;
-
-	boost::shared_ptr<MidiPort> scene_in () const;
-	boost::shared_ptr<MidiPort> scene_out () const;
+	/* synchronous MIDI ports used for synchronization */
 
 	boost::shared_ptr<MidiPort> midi_clock_output_port () const;
 	boost::shared_ptr<MidiPort> midi_clock_input_port () const;
 	boost::shared_ptr<MidiPort> mtc_output_port () const;
 	boost::shared_ptr<MidiPort> mtc_input_port () const;
+	boost::shared_ptr<Port> ltc_input_port() const;
+	boost::shared_ptr<Port> ltc_output_port() const;
+
+	boost::shared_ptr<IO> ltc_input_io() { return _ltc_input; }
+	boost::shared_ptr<IO> ltc_output_io() { return _ltc_output; }
 
 	MIDI::MachineControl& mmc() { return *_mmc; }
 
@@ -1237,6 +1240,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 	void graph_reordered ();
 
 	/** current snapshot name, without the .ardour suffix */
+	void set_snapshot_name (const std::string &);
+	void save_snapshot_name (const std::string &);
 	std::string _current_snapshot_name;
 
 	XMLTree*         state_tree;
@@ -1838,6 +1843,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
 	static int get_session_info_from_path (XMLTree& state_tree, const std::string& xmlpath);
 	static const uint32_t session_end_shift;
+
+	std::string _template_state_dir;
 };
 
 
diff --git a/libs/ardour/ardour/session_directory.h b/libs/ardour/ardour/session_directory.h
index 685f087..6f4126e 100644
--- a/libs/ardour/ardour/session_directory.h
+++ b/libs/ardour/ardour/session_directory.h
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <vector>
+#include <map>
 
 #include "ardour/libardour_visibility.h"
 
@@ -151,6 +152,8 @@ private:
 
 	/// The path to the root of the session directory.
 	std::string m_root_path;
+
+	static std::map<std::string,std::string> root_cache;
 };
 
 } // namespace ARDOUR
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index 31ae261..5bf887f 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -206,7 +206,8 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream
 	struct RecEnableControl : public AutomationControl {
 		RecEnableControl (boost::shared_ptr<Track> t);
 
-		void set_value (double);
+		void set_value (double, PBD::Controllable::GroupControlDisposition);
+		void set_value_unchecked (double);
 		double get_value (void) const;
 
 		boost::weak_ptr<Track> track;
diff --git a/libs/ardour/ardour/analyser.h b/libs/ardour/ardour/transpose.h
similarity index 51%
copy from libs/ardour/ardour/analyser.h
copy to libs/ardour/ardour/transpose.h
index 8e757ef..17f8328 100644
--- a/libs/ardour/ardour/analyser.h
+++ b/libs/ardour/ardour/transpose.h
@@ -1,5 +1,6 @@
 /*
-    Copyright (C) 2012 Paul Davis
+    Copyright (C) 2015 Paul Davis
+    Author: André Nusser
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -14,43 +15,34 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
 */
 
-#ifndef __ardour_analyser_h__
-#define __ardour_analyser_h__
-
-#include <glibmm/threads.h>
-#include <boost/shared_ptr.hpp>
+#ifndef __ardour_transpose_h__
+#define __ardour_transpose_h__
 
 #include "ardour/libardour_visibility.h"
+#include "ardour/midi_model.h"
+#include "ardour/midi_operator.h"
 
 namespace ARDOUR {
 
-class AudioFileSource;
-class Source;
-class TransientDetector;
+class LIBARDOUR_API Transpose : public MidiOperator {
+public:
+	typedef Evoral::Sequence<Evoral::Beats>::NotePtr     NotePtr;
+	typedef Evoral::Sequence<Evoral::Beats>::Notes       Notes;
 
-class LIBARDOUR_API Analyser {
+	Transpose (int semitones);
 
-  public:
-	Analyser();
-	~Analyser ();
+	Command* operator() (boost::shared_ptr<ARDOUR::MidiModel> model,
+	                     Evoral::Beats                        position,
+	                     std::vector<Notes>&                  seqs);
 
-	static void init ();
-	static void queue_source_for_analysis (boost::shared_ptr<Source>, bool force);
-	static void work ();
+	std::string name () const { return std::string ("transpose"); }
 
-  private:
-	static Analyser* the_analyser;
-        static Glib::Threads::Mutex analysis_queue_lock;
-        static Glib::Threads::Cond  SourcesToAnalyse;
-	static std::list<boost::weak_ptr<Source> > analysis_queue;
-
-	static void analyse_audio_file_source (boost::shared_ptr<AudioFileSource>);
+private:
+	int _semitones;
 };
 
+} /* namespace */
 
-}
-
-#endif /* __ardour_analyser_h__ */
+#endif /* __ardour_transpose_h__ */
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index d4c65f3..a7f9b5b 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -140,6 +140,20 @@ namespace ARDOUR {
 		EnvelopeAutomation,
 		RecEnableAutomation,
 		TrimAutomation,
+		PhaseAutomation,
+		SendAutomation,
+		EQGain,
+		EQFrequency,
+		EQQ,
+		EQShape,
+		EQHPF,
+		EQEnable,
+		CompThreshold,
+		CompSpeed,
+		CompMode,
+		CompMakeup,
+		CompRedux,
+		CompEnable,
 	};
 
 	enum AutoState {
@@ -645,6 +659,12 @@ namespace ARDOUR {
 		RegionSelectionStart = 0x8,
 	};
 
+	enum PlaylistDisposition {
+		CopyPlaylist,
+		NewPlaylist,
+		SharePlaylist
+	};
+
 } // namespace ARDOUR
 
 
diff --git a/libs/ardour/ardour/windows_vst_plugin.h b/libs/ardour/ardour/windows_vst_plugin.h
index c464856..7566eab 100644
--- a/libs/ardour/ardour/windows_vst_plugin.h
+++ b/libs/ardour/ardour/windows_vst_plugin.h
@@ -47,6 +47,7 @@ public:
 	~WindowsVSTPluginInfo () {}
 
 	PluginPtr load (Session& session);
+	std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
 };
 
 } // namespace ARDOUR
diff --git a/libs/ardour/ardour/worker.h b/libs/ardour/ardour/worker.h
index c9ff2f2..c83f006 100644
--- a/libs/ardour/ardour/worker.h
+++ b/libs/ardour/ardour/worker.h
@@ -25,7 +25,7 @@
 #include <glibmm/threads.h>
 
 #include "pbd/ringbuffer.h"
-#include "pbd/semaphore.h"
+#include "pbd/semutils.h"
 
 #include "ardour/libardour_visibility.h"
 
@@ -92,7 +92,7 @@ private:
 	RingBuffer<uint8_t>*   _requests;
 	RingBuffer<uint8_t>*   _responses;
 	uint8_t*               _response;
-	PBD::Semaphore         _sem;
+	PBD::Semaphore  _sem;
 	bool                   _exit;
 	Glib::Threads::Thread* _thread;
 
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 99115d5..5e4a3bf 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -56,6 +56,9 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
 
 AudioTrack::~AudioTrack ()
 {
+	if (_freeze_record.playlist && !_session.deletion_in_progress()) {
+		_freeze_record.playlist->release();
+	}
 }
 
 boost::shared_ptr<Diskstream>
@@ -287,6 +290,7 @@ AudioTrack::set_state_part_two ()
 			boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
 			if (pl) {
 				_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
+				_freeze_record.playlist->use();
 			} else {
 				_freeze_record.playlist.reset ();
 				_freeze_record.state = NoFreeze;
@@ -374,9 +378,9 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram
 		bool        valid = false;
 		const float mute  = _mute_control->list()->rt_safe_eval(transport_frame, valid);
 		if (mute >= 0.5 && !muted()) {
-			_mute_control->set_value(1.0);  // mute
+			_mute_control->set_value_unchecked(1.0);  // mute
 		} else if (mute < 0.5 && muted()) {
-			_mute_control->set_value(0.0);  // unmute
+			_mute_control->set_value_unchecked(0.0);  // unmute
 		}
 	}
 
@@ -621,6 +625,8 @@ AudioTrack::freeze_me (InterThreadInfo& itt)
 	diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
 	diskstream->set_record_enabled (false);
 
+	_freeze_record.playlist->use(); // prevent deletion
+
 	/* reset stuff that has already been accounted for in the freeze process */
 
 	set_gain (GAIN_COEFF_UNITY, this);
@@ -635,6 +641,7 @@ void
 AudioTrack::unfreeze ()
 {
 	if (_freeze_record.playlist) {
+		_freeze_record.playlist->release();
 		audio_diskstream()->use_playlist (_freeze_record.playlist);
 
 		{
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
index 73277a1..779bda5 100644
--- a/libs/ardour/audio_unit.cc
+++ b/libs/ardour/audio_unit.cc
@@ -50,8 +50,8 @@
 #include "ardour/tempo.h"
 #include "ardour/utils.h"
 
-#include "appleutility/CAAudioUnit.h"
-#include "appleutility/CAAUParameter.h"
+#include "CAAudioUnit.h"
+#include "CAAUParameter.h"
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreServices/CoreServices.h>
@@ -61,6 +61,16 @@
 #include <Carbon/Carbon.h>
 #endif
 
+#ifdef COREAUDIO105
+#define ArdourComponent Component
+#define ArdourDescription ComponentDescription
+#define ArdourFindNext FindNextComponent
+#else
+#define ArdourComponent AudioComponent
+#define ArdourDescription AudioComponentDescription
+#define ArdourFindNext AudioComponentFindNext
+#endif
+
 #include "i18n.h"
 
 using namespace std;
@@ -339,8 +349,8 @@ get_preset_name_in_plist (CFPropertyListRef plist)
 //--------------------------------------------------------------------------
 // general implementation for ComponentDescriptionsMatch() and ComponentDescriptionsMatch_Loosely()
 // if inIgnoreType is true, then the type code is ignored in the ComponentDescriptions
-Boolean ComponentDescriptionsMatch_General(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2, Boolean inIgnoreType);
-Boolean ComponentDescriptionsMatch_General(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2, Boolean inIgnoreType)
+Boolean ComponentDescriptionsMatch_General(const ArdourDescription * inComponentDescription1, const ArdourDescription * inComponentDescription2, Boolean inIgnoreType);
+Boolean ComponentDescriptionsMatch_General(const ArdourDescription * inComponentDescription1, const ArdourDescription * inComponentDescription2, Boolean inIgnoreType)
 {
 	if ( (inComponentDescription1 == NULL) || (inComponentDescription2 == NULL) )
 		return FALSE;
@@ -362,17 +372,21 @@ Boolean ComponentDescriptionsMatch_General(const ComponentDescription * inCompon
 //--------------------------------------------------------------------------
 // general implementation for ComponentAndDescriptionMatch() and ComponentAndDescriptionMatch_Loosely()
 // if inIgnoreType is true, then the type code is ignored in the ComponentDescriptions
-Boolean ComponentAndDescriptionMatch_General(Component inComponent, const ComponentDescription * inComponentDescription, Boolean inIgnoreType);
-Boolean ComponentAndDescriptionMatch_General(Component inComponent, const ComponentDescription * inComponentDescription, Boolean inIgnoreType)
+Boolean ComponentAndDescriptionMatch_General(ArdourComponent inComponent, const ArdourDescription * inComponentDescription, Boolean inIgnoreType);
+Boolean ComponentAndDescriptionMatch_General(ArdourComponent inComponent, const ArdourDescription * inComponentDescription, Boolean inIgnoreType)
 {
 	OSErr status;
-	ComponentDescription desc;
+	ArdourDescription desc;
 
 	if ( (inComponent == NULL) || (inComponentDescription == NULL) )
 		return FALSE;
 
 	// get the ComponentDescription of the input Component
+#ifdef COREAUDIO105
 	status = GetComponentInfo(inComponent, &desc, NULL, NULL, NULL);
+#else
+	status = AudioComponentGetDescription (inComponent, &desc);
+#endif
 	if (status != noErr)
 		return FALSE;
 
@@ -384,28 +398,28 @@ Boolean ComponentAndDescriptionMatch_General(Component inComponent, const Compon
 // determine if 2 ComponentDescriptions are basically equal
 // (by that, I mean that the important identifying values are compared,
 // but not the ComponentDescription flags)
-Boolean ComponentDescriptionsMatch(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2)
+Boolean ComponentDescriptionsMatch(const ArdourDescription * inComponentDescription1, const ArdourDescription * inComponentDescription2)
 {
 	return ComponentDescriptionsMatch_General(inComponentDescription1, inComponentDescription2, FALSE);
 }
 
 //--------------------------------------------------------------------------
 // determine if 2 ComponentDescriptions have matching sub-type and manufacturer codes
-Boolean ComponentDescriptionsMatch_Loose(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2)
+Boolean ComponentDescriptionsMatch_Loose(const ArdourDescription * inComponentDescription1, const ArdourDescription * inComponentDescription2)
 {
 	return ComponentDescriptionsMatch_General(inComponentDescription1, inComponentDescription2, TRUE);
 }
 
 //--------------------------------------------------------------------------
 // determine if a ComponentDescription basically matches that of a particular Component
-Boolean ComponentAndDescriptionMatch(Component inComponent, const ComponentDescription * inComponentDescription)
+Boolean ComponentAndDescriptionMatch(ArdourComponent inComponent, const ArdourDescription * inComponentDescription)
 {
 	return ComponentAndDescriptionMatch_General(inComponent, inComponentDescription, FALSE);
 }
 
 //--------------------------------------------------------------------------
 // determine if a ComponentDescription matches only the sub-type and manufacturer codes of a particular Component
-Boolean ComponentAndDescriptionMatch_Loosely(Component inComponent, const ComponentDescription * inComponentDescription)
+Boolean ComponentAndDescriptionMatch_Loosely(ArdourComponent inComponent, const ArdourDescription * inComponentDescription)
 {
 	return ComponentAndDescriptionMatch_General(inComponent, inComponentDescription, TRUE);
 }
@@ -533,7 +547,11 @@ AUPlugin::init ()
 	output_channels = -1;
 	{
 		CAComponentDescription temp;
+#ifdef COREAUDIO105
 		GetComponentInfo (comp.get()->Comp(), &temp, NULL, NULL, NULL);
+#else
+		AudioComponentGetDescription (comp.get()->Comp(), &temp);
+#endif
 		CFStringRef compTypeString = UTCreateStringForOSType(temp.componentType);
 		CFStringRef compSubTypeString = UTCreateStringForOSType(temp.componentSubType);
 		CFStringRef compManufacturerString = UTCreateStringForOSType(temp.componentManufacturer);
@@ -842,7 +860,7 @@ AUPlugin::maybe_fix_broken_au_id (const std::string& id)
 
 	return s.str();
 
-  err:
+err:
 	return string();
 }
 
@@ -906,7 +924,8 @@ AUPlugin::set_parameter (uint32_t which, float val)
 	theEvent.mArgument.mParameter.mElement = d.element;
 
 	DEBUG_TRACE (DEBUG::AudioUnits, "notify about parameter change\n");
-	AUEventListenerNotify (NULL, NULL, &theEvent);
+        /* Note the 1st argument, which means "Don't notify us about a change we made ourselves" */
+        AUEventListenerNotify (_parameter_listener, NULL, &theEvent);
 
 	Plugin::set_parameter (which, val);
 }
@@ -1421,7 +1440,7 @@ AUPlugin::render_callback(AudioUnitRenderActionFlags*,
 	/* not much to do with audio - the data is already in the buffers given to us in connect_and_run() */
 
 	// DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1: render callback, frames %2 bufs %3\n",
-        // name(), inNumberFrames, ioData->mNumberBuffers));
+	// name(), inNumberFrames, ioData->mNumberBuffers));
 
 	if (input_maxbuf == 0) {
 		error << _("AUPlugin: render callback called illegally!") << endmsg;
@@ -1434,9 +1453,9 @@ AUPlugin::render_callback(AudioUnitRenderActionFlags*,
 		ioData->mBuffers[i].mDataByteSize = sizeof (Sample) * inNumberFrames;
 
 		/* we don't use the channel mapping because audiounits are
-		   never replicated. one plugin instance uses all channels/buffers
-		   passed to PluginInsert::connect_and_run()
-		*/
+		 * never replicated. one plugin instance uses all channels/buffers
+		 * passed to PluginInsert::connect_and_run()
+		 */
 
 		ioData->mBuffers[i].mData = input_buffers->get_audio (i).data (cb_offset + input_offset);
 	}
@@ -1461,12 +1480,12 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_
 	}
 
 	DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 in %2 out %3 MIDI %4 bufs %5 (available %6)\n",
-							name(), input_channels, output_channels, _has_midi_input,
-							bufs.count(), bufs.available()));
+				name(), input_channels, output_channels, _has_midi_input,
+				bufs.count(), bufs.available()));
 
 	/* the apparent number of buffers matches our input configuration, but we know that the bufferset
 	   has the capacity to handle our outputs.
-	*/
+	   */
 
 	assert (bufs.available() >= ChanCount (DataType::AUDIO, output_channels));
 
@@ -1481,12 +1500,12 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_
 		buffers->mBuffers[i].mNumberChannels = 1;
 		buffers->mBuffers[i].mDataByteSize = nframes * sizeof (Sample);
 		/* setting this to 0 indicates to the AU that it can provide buffers here
-		   if necessary. if it can process in-place, it will use the buffers provided
-		   as input by ::render_callback() above.
-
-                   a non-null values tells the plugin to render into the buffer pointed
-                   at by the value.
-		*/
+		 * if necessary. if it can process in-place, it will use the buffers provided
+		 * as input by ::render_callback() above.
+		 *
+		 * a non-null values tells the plugin to render into the buffer pointed
+		 * at by the value.
+		 */
 		buffers->mBuffers[i].mData = 0;
 	}
 
@@ -1515,13 +1534,13 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_
 	}
 
 	/* does this really mean anything ?
-	 */
+	*/
 
 	ts.mSampleTime = frames_processed;
 	ts.mFlags = kAudioTimeStampSampleTimeValid;
 
 	DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 render flags=%2 time=%3 nframes=%4 buffers=%5\n",
-                                                        name(), flags, frames_processed, nframes, buffers->mNumberBuffers));
+				name(), flags, frames_processed, nframes, buffers->mNumberBuffers));
 
 	if ((err = unit->Render (&flags, &ts, 0, nframes, buffers)) == noErr) {
 
@@ -1529,7 +1548,7 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_
 		frames_processed += nframes;
 
 		DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 rendered %2 buffers of %3\n",
-								name(), buffers->mNumberBuffers, output_channels));
+					name(), buffers->mNumberBuffers, output_channels));
 
 		int32_t limit = min ((int32_t) buffers->mNumberBuffers, output_channels);
 		int32_t i;
@@ -1538,14 +1557,14 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_
 			Sample* expected_buffer_address= bufs.get_audio (i).data (offset);
 			if (expected_buffer_address != buffers->mBuffers[i].mData) {
 				/* plugin provided its own buffer for output so copy it back to where we want it
-				 */
+				*/
 				memcpy (expected_buffer_address, buffers->mBuffers[i].mData, nframes * sizeof (Sample));
 			}
 		}
 
 		/* now silence any buffers that were passed in but the that the plugin
-		   did not fill/touch/use.
-		*/
+		 * did not fill/touch/use.
+		 */
 
 		for (;i < output_channels; ++i) {
 			memset (bufs.get_audio (i).data (offset), 0, nframes * sizeof (Sample));
@@ -2048,10 +2067,10 @@ GetDictionarySInt32Value(CFDictionaryRef inAUStateDictionary, CFStringRef inDict
 }
 
 static OSStatus
-GetAUComponentDescriptionFromStateData(CFPropertyListRef inAUStateData, ComponentDescription * outComponentDescription)
+GetAUComponentDescriptionFromStateData(CFPropertyListRef inAUStateData, ArdourDescription * outComponentDescription)
 {
 	CFDictionaryRef auStateDictionary;
-	ComponentDescription tempDesc = {0,0,0,0,0};
+	ArdourDescription tempDesc = {0,0,0,0,0};
 	SInt32 versionValue;
 	Boolean gotValue;
 
@@ -2105,16 +2124,16 @@ static bool au_preset_filter (const string& str, void* arg)
 		   include "<manufacturer>/<plugin-name>" in their path.
 		*/
 
-		Plugin* p = (Plugin *) arg;
-		string match = p->maker();
+		AUPluginInfo* p = (AUPluginInfo *) arg;
+		string match = p->creator;
 		match += '/';
-		match += p->name();
+		match += p->name;
 
 		ret = str.find (match) != string::npos;
 
 		if (ret == false) {
-			string m = p->maker ();
-			string n = p->name ();
+			string m = p->creator;
+			string n = p->name;
 			strip_whitespace_edges (m);
 			strip_whitespace_edges (n);
 			match = m;
@@ -2128,12 +2147,12 @@ static bool au_preset_filter (const string& str, void* arg)
 	return ret;
 }
 
-bool
-check_and_get_preset_name (Component component, const string& pathstr, string& preset_name)
+static bool
+check_and_get_preset_name (ArdourComponent component, const string& pathstr, string& preset_name)
 {
 	OSStatus status;
 	CFPropertyListRef plist;
-	ComponentDescription presetDesc;
+	ArdourDescription presetDesc;
 	bool ret = false;
 
 	plist = load_property_list (pathstr);
@@ -2176,6 +2195,73 @@ check_and_get_preset_name (Component component, const string& pathstr, string& p
 	return true;
 }
 
+
+static void
+#ifdef COREAUDIO105
+get_names (CAComponentDescription& comp_desc, std::string& name, std::string& maker)
+#else
+get_names (ArdourComponent& comp, std::string& name, std::string& maker)
+#endif
+{
+	CFStringRef itemName = NULL;
+	// Marc Poirier-style item name
+#ifdef COREAUDIO105
+	CAComponent auComponent (comp_desc);
+	if (auComponent.IsValid()) {
+		CAComponentDescription dummydesc;
+		Handle nameHandle = NewHandle(sizeof(void*));
+		if (nameHandle != NULL) {
+			OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL);
+			if (err == noErr) {
+				ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
+				if (nameString != NULL) {
+					itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
+				}
+			}
+			DisposeHandle(nameHandle);
+		}
+	}
+#else
+	assert (comp);
+	AudioComponentCopyName (comp, &itemName);
+#endif
+
+	// if Marc-style fails, do the original way
+	if (itemName == NULL) {
+#ifndef COREAUDIO105
+		CAComponentDescription comp_desc;
+		AudioComponentGetDescription (comp, &comp_desc);
+#endif
+		CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType);
+		CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType);
+		CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer);
+
+		itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"),
+				compTypeString, compManufacturerString, compSubTypeString);
+
+		if (compTypeString != NULL)
+			CFRelease(compTypeString);
+		if (compSubTypeString != NULL)
+			CFRelease(compSubTypeString);
+		if (compManufacturerString != NULL)
+			CFRelease(compManufacturerString);
+	}
+
+	string str = CFStringRefToStdString(itemName);
+	string::size_type colon = str.find (':');
+
+	if (colon) {
+		name = str.substr (colon+1);
+		maker = str.substr (0, colon);
+		strip_whitespace_edges (maker);
+		strip_whitespace_edges (name);
+	} else {
+		name = str;
+		maker = "unknown";
+		strip_whitespace_edges (name);
+	}
+}
+
 std::string
 AUPlugin::current_preset() const
 {
@@ -2199,11 +2285,13 @@ AUPlugin::find_presets ()
 
 	user_preset_map.clear ();
 
-	find_files_matching_filter (preset_files, preset_search_path, au_preset_filter, this, true, true, true);
+	PluginInfoPtr nfo = get_info();
+	find_files_matching_filter (preset_files, preset_search_path, au_preset_filter,
+			boost::dynamic_pointer_cast<AUPluginInfo> (nfo).get(),
+			true, true, true);
 
 	if (preset_files.empty()) {
 		DEBUG_TRACE (DEBUG::AudioUnits, "AU No Preset Files found for given plugin.\n");
-		return;
 	}
 
 	for (vector<string>::iterator x = preset_files.begin(); x != preset_files.end(); ++x) {
@@ -2242,7 +2330,7 @@ AUPlugin::find_presets ()
 	for (FactoryPresetMap::iterator i = factory_preset_map.begin(); i != factory_preset_map.end(); ++i) {
 		/* XXX: dubious */
 		string const uri = string_compose ("%1", _presets.size ());
-		_presets.insert (make_pair (uri, Plugin::PresetRecord (uri, i->first, i->second)));
+		_presets.insert (make_pair (uri, Plugin::PresetRecord (uri, i->first, false)));
 		DEBUG_TRACE (DEBUG::AudioUnits, string_compose("AU Adding Factory Preset: %1 > %2\n", i->first, i->second));
 	}
 }
@@ -2295,10 +2383,90 @@ AUPluginInfo::load (Session& session)
 	}
 }
 
+std::vector<Plugin::PresetRecord>
+AUPluginInfo::get_presets (bool user_only) const
+{
+	std::vector<Plugin::PresetRecord> p;
+	boost::shared_ptr<CAComponent> comp;
+#ifndef NO_PLUGIN_STATE
+	try {
+		comp = boost::shared_ptr<CAComponent>(new CAComponent(*descriptor));
+		if (!comp->IsValid()) {
+			throw failed_constructor();
+		}
+	} catch (failed_constructor& err) {
+		return p;
+	}
+
+	// user presets
+
+	if (!preset_search_path_initialized) {
+		Glib::ustring p = Glib::get_home_dir();
+		p += "/Library/Audio/Presets:";
+		p += preset_search_path;
+		preset_search_path = p;
+		preset_search_path_initialized = true;
+		DEBUG_TRACE (DEBUG::AudioUnits, string_compose("AU Preset Path: %1\n", preset_search_path));
+	}
+
+	vector<string> preset_files;
+	find_files_matching_filter (preset_files, preset_search_path, au_preset_filter, const_cast<AUPluginInfo*>(this), true, true, true);
+
+	for (vector<string>::iterator x = preset_files.begin(); x != preset_files.end(); ++x) {
+		string path = *x;
+		string preset_name;
+		preset_name = Glib::path_get_basename (path);
+		preset_name = preset_name.substr (0, preset_name.find_last_of ('.'));
+		if (check_and_get_preset_name (comp.get()->Comp(), path, preset_name)) {
+			p.push_back (Plugin::PresetRecord (path, preset_name));
+		}
+	}
+
+	if (user_only) {
+		return p;
+	}
+
+	// factory presets
+
+	CFArrayRef presets;
+	UInt32 dataSize;
+	Boolean isWritable;
+
+	boost::shared_ptr<CAAudioUnit> unit (new CAAudioUnit);
+	if (noErr != CAAudioUnit::Open (*(comp.get()), *unit)) {
+		return p;
+	}
+	if (noErr != unit->GetPropertyInfo (kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, &dataSize, &isWritable)) {
+		unit->Uninitialize ();
+		return p;
+	}
+	if (noErr != unit->GetProperty (kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, (void*) &presets, &dataSize)) {
+		unit->Uninitialize ();
+		return p;
+	}
+	if (!presets) {
+		unit->Uninitialize ();
+		return p;
+	}
+
+	CFIndex cnt = CFArrayGetCount (presets);
+	for (CFIndex i = 0; i < cnt; ++i) {
+		AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (presets, i);
+		string const uri = string_compose ("%1", i);
+		string name = CFStringRefToStdString (preset->presetName);
+		p.push_back (Plugin::PresetRecord (uri, name, false));
+	}
+	CFRelease (presets);
+	unit->Uninitialize ();
+
+#endif // NO_PLUGIN_STATE
+	return p;
+}
+
 Glib::ustring
 AUPluginInfo::au_cache_path ()
 {
-	return Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
+	return Glib::build_filename (ARDOUR::user_cache_directory(), "au_cache");
 }
 
 PluginInfoList*
@@ -2441,14 +2609,18 @@ AUPluginInfo::au_crashlog (std::string msg)
 void
 AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescription& desc)
 {
-	Component comp = 0;
+	ArdourComponent comp = 0;
 	au_crashlog(string_compose("Start AU discovery for Type: %1", (int)desc.componentType));
 
-	comp = FindNextComponent (NULL, &desc);
+	comp = ArdourFindNext (NULL, &desc);
 
 	while (comp != NULL) {
 		CAComponentDescription temp;
+#ifdef COREAUDIO105
 		GetComponentInfo (comp, &temp, NULL, NULL, NULL);
+#else
+		AudioComponentGetDescription (comp, &temp);
+#endif
 		CFStringRef itemName = NULL;
 
 		{
@@ -2469,7 +2641,7 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
 
 		if (is_blacklisted(CFStringRefToStdString(itemName))) {
 			info << string_compose (_("Skipped blacklisted AU plugin %1 "), CFStringRefToStdString(itemName)) << endmsg;
-			comp = FindNextComponent (comp, &desc);
+			comp = ArdourFindNext (comp, &desc);
 			continue;
 		}
 
@@ -2489,7 +2661,7 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
 		case kAudioUnitType_Panner:
 		case kAudioUnitType_OfflineEffect:
 		case kAudioUnitType_FormatConverter:
-			comp = FindNextComponent (comp, &desc);
+			comp = ArdourFindNext (comp, &desc);
 			continue;
 
 		case kAudioUnitType_Output:
@@ -2516,7 +2688,11 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
 		}
 
 		au_blacklist(CFStringRefToStdString(itemName));
-		AUPluginInfo::get_names (temp, info->name, info->creator);
+#ifdef COREAUDIO105
+		get_names (temp, info->name, info->creator);
+#else
+		get_names (comp, info->name, info->creator);
+#endif
 		ARDOUR::PluginScanMessage(_("AU"), info->name, false);
 		au_crashlog(string_compose("Plugin: %1", info->name));
 
@@ -2528,7 +2704,12 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
 
 		CAComponent cacomp (*info->descriptor);
 
-		if (cacomp.GetResourceVersion (info->version) != noErr) {
+#ifdef COREAUDIO105
+		if (cacomp.GetResourceVersion (info->version) != noErr)
+#else
+		if (cacomp.GetVersion (info->version) != noErr)
+#endif
+		{
 			info->version = 0;
 		}
 
@@ -2575,7 +2756,7 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
 
 		au_unblacklist(CFStringRefToStdString(itemName));
 		au_crashlog("Success.");
-		comp = FindNextComponent (comp, &desc);
+		comp = ArdourFindNext (comp, &desc);
 		if (itemName != NULL) CFRelease(itemName); itemName = NULL;
 	}
 	au_crashlog(string_compose("End AU discovery for Type: %1", (int)desc.componentType));
@@ -2810,59 +2991,6 @@ AUPluginInfo::load_cached_info ()
 	return 0;
 }
 
-void
-AUPluginInfo::get_names (CAComponentDescription& comp_desc, std::string& name, std::string& maker)
-{
-	CFStringRef itemName = NULL;
-
-	// Marc Poirier-style item name
-	CAComponent auComponent (comp_desc);
-	if (auComponent.IsValid()) {
-		CAComponentDescription dummydesc;
-		Handle nameHandle = NewHandle(sizeof(void*));
-		if (nameHandle != NULL) {
-			OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL);
-			if (err == noErr) {
-				ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
-				if (nameString != NULL) {
-					itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
-				}
-			}
-			DisposeHandle(nameHandle);
-		}
-	}
-
-	// if Marc-style fails, do the original way
-	if (itemName == NULL) {
-		CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType);
-		CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType);
-		CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer);
-
-		itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"),
-			compTypeString, compManufacturerString, compSubTypeString);
-
-		if (compTypeString != NULL)
-			CFRelease(compTypeString);
-		if (compSubTypeString != NULL)
-			CFRelease(compSubTypeString);
-		if (compManufacturerString != NULL)
-			CFRelease(compManufacturerString);
-	}
-
-	string str = CFStringRefToStdString(itemName);
-	string::size_type colon = str.find (':');
-
-	if (colon) {
-		name = str.substr (colon+1);
-		maker = str.substr (0, colon);
-		strip_whitespace_edges (maker);
-		strip_whitespace_edges (name);
-	} else {
-		name = str;
-		maker = "unknown";
-		strip_whitespace_edges (name);
-	}
-}
 
 std::string
 AUPluginInfo::stringify_descriptor (const CAComponentDescription& desc)
@@ -3033,7 +3161,7 @@ AUPlugin::_parameter_change_listener (void* arg, void* src, const AudioUnitEvent
 }
 
 void
-AUPlugin::parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 /*host_time*/, Float32 new_value)
+AUPlugin::parameter_change_listener (void* /*arg*/, void* src, const AudioUnitEvent* event, UInt64 /*host_time*/, Float32 new_value)
 {
         ParameterMap::iterator i;
 
@@ -3049,7 +3177,10 @@ AUPlugin::parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUn
                 EndTouch (i->second);
                 break;
         case kAudioUnitEvent_ParameterValueChange:
-                ParameterChanged (i->second, new_value);
+                /* whenever we change a parameter, we request that we are NOT notified of the change, so anytime we arrive here, it
+                   means that something else (i.e. the plugin GUI) made the change.
+                */
+                ParameterChangedExternally (i->second, new_value);
                 break;
         default:
                 break;
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 69db73a..9c8407e 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -215,6 +215,26 @@ AudioEngine::process_callback (pframes_t nframes)
 		return 0;
 	}
 
+	/* The coreaudio-backend calls thread_init_callback() if
+	 * the hardware changes or pthread_self() changes.
+	 *
+	 * However there are cases when neither holds true, yet
+	 * the thread-pool changes: e.g. connect a headphone to
+	 * a shared mic/headphone jack.
+	 * It's probably related to, or caused by clocksource changes.
+	 *
+	 * For reasons yet unknown Glib::Threads::Private() can
+	 * use a different thread-private in the same pthread
+	 * (coreaudio render callback).
+	 *
+	 * Coreaudio must set something which influences
+	 * pthread_key_t uniqness or reset the key using
+	 * pthread_getspecific().
+	 */
+	if (! SessionEvent::has_per_thread_pool ()) {
+		thread_init_callback (NULL);
+	}
+
 	bool return_after_remove_check = false;
 
 	if (_measuring_latency == MeasureAudio && _mtdm) {
@@ -867,6 +887,8 @@ AudioEngine::start (bool for_latency)
 int
 AudioEngine::stop (bool for_latency)
 {
+	bool stop_engine = true;
+
 	if (!_backend) {
 		return 0;
 	}
@@ -877,15 +899,20 @@ AudioEngine::stop (bool for_latency)
 		pl.acquire ();
 	}
 
-	if (_backend->stop ()) {
-		return -1;
+	if (for_latency && _backend->can_change_systemic_latency_when_running()) {
+		stop_engine = false;
+	} else {
+		if (_backend->stop ()) {
+			pl.release ();
+			return -1;
+		}
 	}
 
 	if (pl.locked ()) {
 		pl.release ();
 	}
 
-	if (_session && _running &&
+	if (_session && _running && stop_engine &&
 	    (_session->state_of_the_state() & Session::Loading) == 0 &&
 	    (_session->state_of_the_state() & Session::Deletion) == 0) {
 		// it's not a halt, but should be handled the same way:
@@ -893,16 +920,20 @@ AudioEngine::stop (bool for_latency)
 		_session->engine_halted ();
 	}
 
-	_running = false;
+	if (stop_engine) {
+		_running = false;
+	}
 	_processed_frames = 0;
 	_measuring_latency = MeasureNone;
 	_latency_output_port = 0;
 	_latency_input_port = 0;
 	_started_for_latency = false;
 
-	Port::PortDrop ();
+	if (stop_engine) {
+		Port::PortDrop ();
+	}
 
-	if (!for_latency) {
+	if (!for_latency && stop_engine) {
 		Stopped (); /* EMIT SIGNAL */
 	}
 
@@ -1195,8 +1226,7 @@ AudioEngine::thread_init_callback (void* arg)
 
 	SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
 
-	PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
-	PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
+	PBD::notify_event_loops_about_thread_creation (pthread_self(), X_("AudioEngine"), 4096);
 
 	AsyncMIDIPort::set_process_thread (pthread_self());
 
@@ -1272,15 +1302,28 @@ AudioEngine::setup_required () const
 int
 AudioEngine::prepare_for_latency_measurement ()
 {
+	if (!_backend) {
+		return -1;
+	}
+
+	if (_backend->can_change_systemic_latency_when_running()) {
+		if (start()) {
+			return -1;
+		}
+		_backend->set_systemic_input_latency (0);
+		_backend->set_systemic_output_latency (0);
+		return 0;
+	}
+
 	if (running()) {
 		_stopped_for_latency = true;
 		stop (true);
 	}
 
 	if (start (true)) {
-		_started_for_latency = true;
 		return -1;
 	}
+	_started_for_latency = true;
 
 	return 0;
 }
@@ -1288,10 +1331,8 @@ AudioEngine::prepare_for_latency_measurement ()
 int
 AudioEngine::start_latency_detection (bool for_midi)
 {
-	if (!running()) {
-		if (prepare_for_latency_measurement ()) {
-			return -1;
-		}
+	if (prepare_for_latency_measurement ()) {
+		return -1;
 	}
 
 	PortEngine& pe (port_engine());
@@ -1398,7 +1439,9 @@ AudioEngine::stop_latency_detection ()
 		_latency_input_port = 0;
 	}
 
-	stop (true);
+	if (!_backend->can_change_systemic_latency_when_running()) {
+		stop (true);
+	}
 
 	if (_stopped_for_latency) {
 		start ();
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 8f5228a..ddd152b 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -109,11 +109,9 @@ generate_db_fade (boost::shared_ptr<Evoral::ControlList> dst, double len, int nu
 
 	//generate a fade-out curve by successively applying a gain drop
 	float fade_speed = dB_to_coefficient(dB_drop / (float) num_steps);
+	float coeff = GAIN_COEFF_UNITY;
 	for (int i = 1; i < (num_steps-1); i++) {
-		float coeff = GAIN_COEFF_UNITY;
-		for (int j = 0; j < i; j++) {
-			coeff *= fade_speed;
-		}
+		coeff *= fade_speed;
 		dst->fast_simple_add (len*(double)i/(double)num_steps, coeff);
 	}
 
diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc
index e7d81fe..9d90d05 100644
--- a/libs/ardour/audiosource.cc
+++ b/libs/ardour/audiosource.cc
@@ -238,6 +238,7 @@ AudioSource::rename_peakfile (string newpath)
 int
 AudioSource::initialize_peakfile (const string& audio_path, const bool in_session)
 {
+	Glib::Threads::Mutex::Lock lm (_initialize_peaks_lock);
 	GStatBuf statbuf;
 
 	_peakpath = construct_peak_filepath (audio_path, in_session);
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 0b31689..9670f68 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -394,16 +394,21 @@ Automatable::transport_stopped (framepos_t now)
 		   when the transport is re-started, a touch will magically
 		   be happening without it ever have being started in the usual way.
 		*/
+		const bool list_did_write = !l->in_new_write_pass ();
+
 		l->stop_touch (true, now);
-		l->write_pass_finished (now, Config->get_automation_thinning_factor());
 
-		if (l->automation_playback()) {
-			c->set_value(c->list()->eval(now));
-		}
+		c->commit_transaction (list_did_write);
+
+		l->write_pass_finished (now, Config->get_automation_thinning_factor ());
 
-		if (l->automation_state() == Write) {
+		if (l->automation_state () == Write) {
 			l->set_automation_state (Touch);
 		}
+
+		if (l->automation_playback ()) {
+			c->set_value_unchecked (c->list ()->eval (now));
+		}
 	}
 }
 
diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc
index 26ea53c..583f388 100644
--- a/libs/ardour/automation_control.cc
+++ b/libs/ardour/automation_control.cc
@@ -25,6 +25,7 @@
 #include "ardour/session.h"
 
 #include "pbd/memento_command.h"
+#include "pbd/stacktrace.h"
 
 #include "i18n.h"
 
@@ -48,6 +49,16 @@ AutomationControl::~AutomationControl ()
 {
 }
 
+bool
+AutomationControl::writable() const
+{
+	boost::shared_ptr<AutomationList> al = alist();
+	if (al) {
+		return al->automation_state() != Play;
+	}
+	return true;
+}
+
 /** Get the current effective `user' value based on automation state */
 double
 AutomationControl::get_value() const
@@ -61,7 +72,7 @@ AutomationControl::get_value() const
  *  @param value `user' value
  */
 void
-AutomationControl::set_value (double value)
+AutomationControl::set_value (double value, PBD::Controllable::GroupControlDisposition /* group_override */)
 {
 	bool to_list = _list && ((AutomationList*)_list.get())->automation_write();
 
@@ -88,8 +99,6 @@ AutomationControl::set_automation_state (AutoState as)
 		}
 
 		if (as == Write) {
-			/* get state for undo */
-			_before = &alist ()->get_state ();
 			AutomationWatch::instance().add_automation_watch (shared_from_this());
 		} else if (as == Touch) {
 			if (!touching()) {
@@ -126,8 +135,7 @@ AutomationControl::start_touch(double when)
 
 		if (alist()->automation_state() == Touch) {
 			/* subtle. aligns the user value with the playback */
-			set_value (get_value ());
-			_before = &alist ()->get_state ();
+			set_value (get_value (), Controllable::NoGroup);
 			alist()->start_touch (when);
 			if (!_desc.toggled) {
 				AutomationWatch::instance().add_automation_watch (shared_from_this());
@@ -144,22 +152,26 @@ AutomationControl::stop_touch(bool mark, double when)
 	if (touching()) {
 		set_touching (false);
 
-		if (alist()->automation_state() == Write) {
-			_session.begin_reversible_command (string_compose (_("write %1 automation"), name ()));
-			_session.add_command (new MementoCommand<AutomationList> (*alist ().get (), _before, &alist ()->get_state ()));
-			_session.commit_reversible_command ();
-		}
-
 		if (alist()->automation_state() == Touch) {
 			alist()->stop_touch (mark, when);
 			if (!_desc.toggled) {
 				AutomationWatch::instance().remove_automation_watch (shared_from_this());
+
 			}
+		}
+	}
+}
 
-			_session.begin_reversible_command (string_compose (_("touch %1 automation"), name ()));
-			_session.add_command (new MementoCommand<AutomationList> (*alist ().get (), _before, &alist ()->get_state ()));
-			_session.commit_reversible_command ();
+void
+AutomationControl::commit_transaction (bool did_write)
+{
+	if (did_write) {
+		if (alist ()->before ()) {
+			_session.begin_reversible_command (string_compose (_("record %1 automation"), name ()));
+			_session.commit_reversible_command (new MementoCommand<AutomationList> (*alist ().get (), alist ()->before (), &alist ()->get_state ()));
 		}
+	} else {
+		alist ()->clear_history ();
 	}
 }
 
diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc
index 91609f6..bc8ca8e 100644
--- a/libs/ardour/automation_list.cc
+++ b/libs/ardour/automation_list.cc
@@ -50,6 +50,7 @@ static void dumpit (const AutomationList& al, string prefix = "")
 #endif
 AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc)
 	: ControlList(id, desc)
+	, _before (0)
 {
 	_state = Off;
 	_style = Absolute;
@@ -63,6 +64,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::Param
 
 AutomationList::AutomationList (const Evoral::Parameter& id)
 	: ControlList(id, ARDOUR::ParameterDescriptor(id))
+	, _before (0)
 {
 	_state = Off;
 	_style = Absolute;
@@ -77,6 +79,7 @@ AutomationList::AutomationList (const Evoral::Parameter& id)
 AutomationList::AutomationList (const AutomationList& other)
 	: StatefulDestructible()
 	, ControlList(other)
+	, _before (0)
 {
 	_style = other._style;
 	_state = other._state;
@@ -90,6 +93,7 @@ AutomationList::AutomationList (const AutomationList& other)
 
 AutomationList::AutomationList (const AutomationList& other, double start, double end)
 	: ControlList(other, start, end)
+	, _before (0)
 {
 	_style = other._style;
 	_state = other._state;
@@ -106,6 +110,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
  */
 AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
 	: ControlList(id, ARDOUR::ParameterDescriptor(id))
+	, _before (0)
 {
 	g_atomic_int_set (&_touching, 0);
 	_state = Off;
@@ -186,6 +191,9 @@ AutomationList::set_automation_state (AutoState s)
 {
 	if (s != _state) {
 		_state = s;
+		if (s == Write && _desc.toggled) {
+			_before = &get_state ();
+		}
 		automation_state_changed (s); /* EMIT SIGNAL */
 	}
 }
@@ -200,6 +208,23 @@ AutomationList::set_automation_style (AutoStyle s)
 }
 
 void
+AutomationList::start_write_pass (double when)
+{
+	if (in_new_write_pass ()) {
+		_before = &get_state ();
+	}
+	ControlList::start_write_pass (when);
+}
+
+void
+AutomationList::write_pass_finished (double when, double thinning_factor)
+{
+	ControlList::write_pass_finished (when, thinning_factor);
+	/* automation control has deleted this or it is now owned by the session undo stack */
+	_before = 0;
+}
+
+void
 AutomationList::start_touch (double when)
 {
         if (_state == Touch) {
@@ -232,6 +257,16 @@ AutomationList::stop_touch (bool mark, double)
         }
 }
 
+/* _before may be owned by the undo stack,
+ * so we have to be careful about doing this.
+*/
+void
+AutomationList::clear_history ()
+{
+	delete _before;
+	_before = 0;
+}
+
 void
 AutomationList::thaw ()
 {
diff --git a/libs/ardour/automation_watch.cc b/libs/ardour/automation_watch.cc
index 6ebf1aa..4152c5d 100644
--- a/libs/ardour/automation_watch.cc
+++ b/libs/ardour/automation_watch.cc
@@ -135,7 +135,7 @@ AutomationWatch::timer ()
 										(*aw)->alist()->automation_write()));
 				(*aw)->list()->set_in_write_pass (false);
 				if ( (*aw)->alist()->automation_write() ) {
-					(*aw)->list()->set_in_write_pass (true);
+					(*aw)->list()->set_in_write_pass (true, time);
 				}
 			}
 		}
diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc
index 4e2cb7d..7423d3b 100644
--- a/libs/ardour/control_protocol_manager.cc
+++ b/libs/ardour/control_protocol_manager.cc
@@ -22,6 +22,7 @@
 #include <glibmm/fileutils.h>
 
 #include "pbd/compose.h"
+#include "pbd/event_loop.h"
 #include "pbd/file_utils.h"
 #include "pbd/error.h"
 
@@ -192,6 +193,18 @@ int
 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
 {
 	if (!cpi.protocol) {
+
+		/* we could still have a descriptor even if the protocol was
+		   never instantiated. Close the associated module (shared
+		   object/DLL) and make sure we forget about it.
+		*/
+
+		if (cpi.descriptor) {
+			cerr << "Closing descriptor for CPI anyway\n";
+			delete (Glib::Module*) cpi.descriptor->module;
+			cpi.descriptor = 0;
+		}
+
 		return 0;
 	}
 
@@ -222,9 +235,15 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
 	}
 
 	cpi.protocol = 0;
+
 	delete cpi.state;
 	cpi.state = 0;
-	delete (Glib::Module*)cpi.descriptor->module;
+	delete (Glib::Module*) cpi.descriptor->module;
+	/* cpi->descriptor is now inaccessible since dlclose() or equivalent
+	 * has been performed, and the descriptor is (or could be) a static
+	 * object made accessible by dlopen().
+	 */
+	cpi.descriptor = 0;
 
 	ProtocolStatusChange (&cpi);
 
@@ -331,8 +350,6 @@ ControlProtocolManager::control_protocol_discover (string path)
 			DEBUG_TRACE (DEBUG::ControlProtocols,
 				     string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
 		}
-
-		delete (Glib::Module*)descriptor->module;
 	}
 
 	return 0;
@@ -364,8 +381,6 @@ ControlProtocolManager::get_descriptor (string path)
 
 	if (descriptor) {
 		descriptor->module = (void*)module;
-	} else {
-		delete module;
 	}
 
 	return descriptor;
@@ -487,3 +502,21 @@ ControlProtocolManager::midi_connectivity_established ()
 		(*p)->midi_connectivity_established ();
 	}
 }
+
+void
+ControlProtocolManager::register_request_buffer_factories ()
+{
+	Glib::Threads::Mutex::Lock lm (protocols_lock);
+
+	for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+
+		if ((*i)->descriptor == 0) {
+			warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
+			continue;
+		}
+
+		if ((*i)->descriptor->request_buffer_factory) {
+			EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);
+		}
+	}
+}
diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc
index 33753f4..3bb00f7 100644
--- a/libs/ardour/coreaudiosource.cc
+++ b/libs/ardour/coreaudiosource.cc
@@ -25,8 +25,12 @@
 #include "ardour/coreaudiosource.h"
 #include "ardour/utils.h"
 
-#include <appleutility/CAAudioFile.h>
-#include <appleutility/CAStreamBasicDescription.h>
+#ifdef COREAUDIO105
+#include "CAAudioFile.h"
+#else
+#include "CAExtAudioFile.h"
+#endif
+#include "CAStreamBasicDescription.h"
 
 #include <glibmm/fileutils.h>
 
@@ -241,12 +245,15 @@ CoreAudioSource::update_header (framepos_t, struct tm&, time_t)
 int
 CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string&)
 {
+#ifdef COREAUDIO105
 	FSRef ref;
+#endif
 	ExtAudioFileRef af = 0;
 	UInt32 size;
 	CFStringRef name;
 	int ret = -1;
 
+#ifdef COREAUDIO105
 	if (FSPathMakeRef ((UInt8*)path.c_str(), &ref, 0) != noErr) {
 		goto out;
 	}
@@ -254,6 +261,15 @@ CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string&)
 	if (ExtAudioFileOpen(&ref, &af) != noErr) {
 		goto out;
 	}
+#else
+	CFURLRef url = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8*)path.c_str (), strlen (path.c_str ()), false);
+	OSStatus res = ExtAudioFileOpenURL(url, &af);
+	if (url) CFRelease (url);
+
+	if (res != noErr) {
+		goto out;
+	}
+#endif
 
 	AudioStreamBasicDescription absd;
 	memset(&absd, 0, sizeof(absd));
@@ -311,66 +327,66 @@ CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string&)
 	}
 
 	switch (absd.mFormatID) {
-	case kAudioFormatLinearPCM:
-		_info.format_name += "PCM";
-		break;
-
-	case kAudioFormatAC3:
-		_info.format_name += "AC3";
-		break;
-
-	case kAudioFormat60958AC3:
-		_info.format_name += "60958 AC3";
-		break;
-
-	case kAudioFormatMPEGLayer1:
-		_info.format_name += "MPEG-1";
-		break;
-
-	case kAudioFormatMPEGLayer2:
-		_info.format_name += "MPEG-2";
-		break;
-
-	case kAudioFormatMPEGLayer3:
-		_info.format_name += "MPEG-3";
-		break;
-
-	case kAudioFormatAppleIMA4:
-		_info.format_name += "IMA-4";
-		break;
-
-	case kAudioFormatMPEG4AAC:
-		_info.format_name += "AAC";
-		break;
-
-	case kAudioFormatMPEG4CELP:
-		_info.format_name += "CELP";
-		break;
-
-	case kAudioFormatMPEG4HVXC:
-		_info.format_name += "HVXC";
-		break;
-
-	case kAudioFormatMPEG4TwinVQ:
-		_info.format_name += "TwinVQ";
-		break;
-
-	/* these really shouldn't show up, but we should do something
-	   somewhere else to make sure that doesn't happen. until
-	   that is guaranteed, print something anyway.
-	*/
-
-	case kAudioFormatTimeCode:
-		_info.format_name += "timecode";
-		break;
-
-	case kAudioFormatMIDIStream:
-		_info.format_name += "MIDI";
-		break;
-
-	case kAudioFormatParameterValueStream:
-		_info.format_name += "parameter values";
-		break;
+		case kAudioFormatLinearPCM:
+			_info.format_name += "PCM";
+			break;
+
+		case kAudioFormatAC3:
+			_info.format_name += "AC3";
+			break;
+
+		case kAudioFormat60958AC3:
+			_info.format_name += "60958 AC3";
+			break;
+
+		case kAudioFormatMPEGLayer1:
+			_info.format_name += "MPEG-1";
+			break;
+
+		case kAudioFormatMPEGLayer2:
+			_info.format_name += "MPEG-2";
+			break;
+
+		case kAudioFormatMPEGLayer3:
+			_info.format_name += "MPEG-3";
+			break;
+
+		case kAudioFormatAppleIMA4:
+			_info.format_name += "IMA-4";
+			break;
+
+		case kAudioFormatMPEG4AAC:
+			_info.format_name += "AAC";
+			break;
+
+		case kAudioFormatMPEG4CELP:
+			_info.format_name += "CELP";
+			break;
+
+		case kAudioFormatMPEG4HVXC:
+			_info.format_name += "HVXC";
+			break;
+
+		case kAudioFormatMPEG4TwinVQ:
+			_info.format_name += "TwinVQ";
+			break;
+
+			/* these really shouldn't show up, but we should do something
+			   somewhere else to make sure that doesn't happen. until
+			   that is guaranteed, print something anyway.
+			   */
+
+		case kAudioFormatTimeCode:
+			_info.format_name += "timecode";
+			break;
+
+		case kAudioFormatMIDIStream:
+			_info.format_name += "MIDI";
+			break;
+
+		case kAudioFormatParameterValueStream:
+			_info.format_name += "parameter values";
+			break;
 	}
 
 	// XXX it would be nice to find a way to get this information if it exists
@@ -378,7 +394,7 @@ CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string&)
 	_info.timecode = 0;
 	ret = 0;
 
-  out:
+out:
 	ExtAudioFileDispose (af);
 	return ret;
 
diff --git a/libs/ardour/debug.cc b/libs/ardour/debug.cc
index 54b6741..86afaf6 100644
--- a/libs/ardour/debug.cc
+++ b/libs/ardour/debug.cc
@@ -73,3 +73,4 @@ PBD::DebugBits PBD::DEBUG::BackendTiming = PBD::new_debug_bit ("backendtiming");
 PBD::DebugBits PBD::DEBUG::BackendThreads = PBD::new_debug_bit ("backendthreads");
 PBD::DebugBits PBD::DEBUG::BackendPorts = PBD::new_debug_bit ("backendports");
 PBD::DebugBits PBD::DEBUG::VSTCallbacks = PBD::new_debug_bit ("vstcallbacks");
+PBD::DebugBits PBD::DEBUG::FaderPort = PBD::new_debug_bit ("faderport");
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index b70d86a..b2cdc0b 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -300,7 +300,7 @@ Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pf
 		// MIDI data will not have been delivered by the panner
 
 		if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
-			_output->copy_to_outputs (bufs, DataType::MIDI, nframes, 0);
+			_output->copy_to_outputs (bufs, DataType::MIDI, nframes, ports.port(0)->port_offset());
 		}
 
 	} else {
@@ -312,7 +312,7 @@ Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pf
                 }
 
 		if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
-			_output->copy_to_outputs (bufs, DataType::MIDI, nframes, 0);
+			_output->copy_to_outputs (bufs, DataType::MIDI, nframes, ports.port(0)->port_offset());
 		}
 	}
 
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index fda55c2..7f42140 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -864,4 +864,3 @@ Diskstream::get_buffering_presets (BufferingPreset bp,
 
 	return true;
 }
-
diff --git a/libs/ardour/ebur128_analysis.cc b/libs/ardour/ebur128_analysis.cc
new file mode 100644
index 0000000..3788e02
--- /dev/null
+++ b/libs/ardour/ebur128_analysis.cc
@@ -0,0 +1,114 @@
+/*
+    Copyright (C) 2015 Robin Gareus
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <cmath>
+#include <cstring>
+
+#include "ardour/ebur128_analysis.h"
+
+#include "i18n.h"
+
+using namespace Vamp;
+using namespace ARDOUR;
+using namespace std;
+
+/* need a static initializer function for this */
+
+EBUr128Analysis::EBUr128Analysis (float sr)
+	: AudioAnalyser (sr, X_("libardourvampplugins:ebur128"))
+	, _loudness (0)
+	, _loudness_range (0)
+{
+}
+
+EBUr128Analysis::~EBUr128Analysis()
+{
+}
+
+int
+EBUr128Analysis::run (Readable* src)
+{
+	int ret = -1;
+	bool done = false;
+	framecnt_t len = src->readable_length();
+	framepos_t pos = 0;
+	uint32_t n_channels = src->n_channels();
+	Plugin::FeatureSet features;
+
+	plugin->reset ();
+	if (!plugin->initialise (n_channels, stepsize, bufsize)) {
+		return -1;
+	}
+
+	float** bufs = (float**) malloc(n_channels * sizeof(float*));
+	for (uint32_t c = 0; c < n_channels; ++c) {
+		bufs[c] = (float*) malloc(bufsize * sizeof(float));
+	}
+
+	while (!done) {
+		framecnt_t to_read;
+		to_read = min ((len - pos), (framecnt_t) bufsize);
+
+		for (uint32_t c = 0; c < n_channels; ++c) {
+			if (src->read (bufs[c], pos, to_read, c) != to_read) {
+				goto out;
+			}
+			/* zero fill buffer if necessary */
+			if (to_read != bufsize) {
+				memset (bufs[c] + to_read, 0, (bufsize - to_read) * sizeof (float));
+			}
+		}
+
+		plugin->process (bufs, RealTime::fromSeconds ((double) pos / sample_rate));
+
+		pos += min (stepsize, to_read);
+
+		if (pos >= len) {
+			done = true;
+		}
+	}
+
+	features = plugin->getRemainingFeatures ();
+
+	if (use_features (features, 0)) {
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	for (uint32_t c = 0; c < n_channels; ++c) {
+		free (bufs[c]);
+	}
+	free (bufs);
+
+	return ret;
+}
+
+int
+EBUr128Analysis::use_features (Plugin::FeatureSet& features, ostream* out)
+{
+	if (features.empty() || features.size() != 2) {
+		return 0;
+	}
+	_loudness = features[0][0].values[0];
+	_loudness_range = features[1][0].values[0];
+
+	return 0;
+}
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 8fdb846..50eed75 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -308,12 +308,12 @@ setup_enum_writer ()
 	REGISTER (_LayerModel);
 
 	REGISTER_ENUM (InsertMergeReject);
-        REGISTER_ENUM (InsertMergeRelax);
-        REGISTER_ENUM (InsertMergeReplace);
-        REGISTER_ENUM (InsertMergeTruncateExisting);
-        REGISTER_ENUM (InsertMergeTruncateAddition);
-        REGISTER_ENUM (InsertMergeExtend);
-        REGISTER (_InsertMergePolicy);
+	REGISTER_ENUM (InsertMergeRelax);
+	REGISTER_ENUM (InsertMergeReplace);
+	REGISTER_ENUM (InsertMergeTruncateExisting);
+	REGISTER_ENUM (InsertMergeTruncateAddition);
+	REGISTER_ENUM (InsertMergeExtend);
+	REGISTER (_InsertMergePolicy);
 
 	REGISTER_ENUM (AfterFaderListen);
 	REGISTER_ENUM (PreFaderListen);
diff --git a/libs/ardour/export_formats.cc b/libs/ardour/export_formats.cc
index 463a094..47f68fe 100644
--- a/libs/ardour/export_formats.cc
+++ b/libs/ardour/export_formats.cc
@@ -156,19 +156,19 @@ HasSampleFormat::get_sample_format_name (ExportFormatBase::SampleFormat format)
 {
 	switch (format) {
 	  case ExportFormatBase::SF_8:
-		return _("8bit");
+		return _("8-bit");
 	  case ExportFormatBase::SF_16:
-		return _("16bit");
+		return _("16-bit");
 	  case ExportFormatBase::SF_24:
-		return _("24bit");
+		return _("24-bit");
 	  case ExportFormatBase::SF_32:
-		return _("32bit");
+		return _("32-bit");
 	  case ExportFormatBase::SF_Float:
 		return _("float");
 	  case ExportFormatBase::SF_Double:
 		return _("double");
 	  case ExportFormatBase::SF_U8:
-		return _("8bit unsigned");
+		return _("8-bit unsigned");
 	  case ExportFormatBase::SF_Vorbis:
 		return _("Vorbis sample format");
 	  case ExportFormatBase::SF_None:
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 0a1d0cd..9f4a139 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -41,6 +41,7 @@
 #include "pbd/gstdio_compat.h"
 
 #ifdef PLATFORM_WINDOWS
+#include <stdio.h> // for _setmaxstdio
 #include <windows.h> // for LARGE_INTEGER
 #endif
 
@@ -96,6 +97,7 @@
 #include "ardour/event_type_map.h"
 #include "ardour/filesystem_paths.h"
 #include "ardour/midi_region.h"
+#include "ardour/midi_ui.h"
 #include "ardour/midiport_manager.h"
 #include "ardour/mix.h"
 #include "ardour/operations.h"
@@ -273,6 +275,21 @@ lotsa_files_please ()
 	} else {
 		error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
 	}
+#else
+	/* this only affects stdio. 2048 is the maxium possible (512 the default).
+	 *
+	 * If we want more, we'll have to replaces the POSIX I/O interfaces with
+	 * Win32 API calls (CreateFile, WriteFile, etc) which allows for 16K.
+	 *
+	 * see http://stackoverflow.com/questions/870173/is-there-a-limit-on-number-of-open-files-in-windows
+	 * and http://bugs.mysql.com/bug.php?id=24509
+	 */
+	int newmax = _setmaxstdio (2048);
+	if (newmax > 0) {
+		info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, newmax) << endmsg;
+	} else {
+		error << string_compose (_("Could not set system open files limit. Current limit is %1 open files"), _getmaxstdio)  << endmsg;
+	}
 #endif
 }
 
@@ -497,6 +514,22 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
 #endif
 	(void) EventTypeMap::instance();
 
+	ControlProtocolManager::instance().discover_control_protocols ();
+
+	/* for each control protocol, check for a request buffer factory method
+	   and if it exists, store it in the EventLoop list of such
+	   methods. This allows the relevant threads to register themselves
+	   with EventLoops so that signal emission can be RT-safe.
+	*/
+
+	ControlProtocolManager::instance().register_request_buffer_factories ();
+	/* it would be nice if this could auto-register itself in the
+	   constructor, since MidiControlUI is a singleton, but it can't be
+	   created until after the engine is running. Therefore we have to
+	   explicitly register it here.
+	*/
+	EventLoop::register_request_buffer_factory (X_("midiUI"), MidiControlUI::request_factory);
+
         ProcessThread::init ();
 	/* the + 4 is a bit of a handwave. i don't actually know
 	   how many more per-thread buffer sets we need above
@@ -537,8 +570,6 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
 void
 ARDOUR::init_post_engine ()
 {
-	ControlProtocolManager::instance().discover_control_protocols ();
-
 	XMLNode* node;
 	if ((node = Config->control_protocol_state()) != 0) {
 		ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
diff --git a/libs/ardour/i18n.h b/libs/ardour/i18n.h
index 43ae07c..b04c96d 100644
--- a/libs/ardour/i18n.h
+++ b/libs/ardour/i18n.h
@@ -17,4 +17,8 @@
  */
 #define S_(Text) PBD::sgettext (PACKAGE, Text)
 
+/** Use this to translate strings with plural forms
+ */
+#define P_(Singular,Plural,HowMany) dngettext (PACKAGE, (Singular), (Plural), (HowMany))
+
 #endif // __i18n_h__
diff --git a/libs/ardour/instrument_info.cc b/libs/ardour/instrument_info.cc
index c673170..c30994b 100644
--- a/libs/ardour/instrument_info.cc
+++ b/libs/ardour/instrument_info.cc
@@ -175,12 +175,8 @@ InstrumentInfo::plugin_programs_to_channel_name_set (boost::shared_ptr<Processor
 		std::vector<Plugin::PresetRecord>::iterator i;
 		int n;
 
-		/* XXX note the assumption that plugin presets start their numbering at
-		 * zero
-		 */
-
 		for (n = 0, i = presets.begin(); i != presets.end(); ++i, ++n) {
-			if ((*i).number >= 0) {
+			if ((*i).valid) {
 				patch_list.push_back (boost::shared_ptr<Patch> (new Patch ((*i).label, n)));
 			} else {
 				patch_list.push_back (boost::shared_ptr<Patch> (new Patch (string_compose ("program %1", n), n)));
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index 88f40c1..f30925a 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -738,6 +738,29 @@ LadspaPluginInfo::load (Session& session)
 	}
 }
 
+std::vector<Plugin::PresetRecord>
+LadspaPluginInfo::get_presets (bool /*user_only*/) const
+{
+	std::vector<Plugin::PresetRecord> p;
+#if (defined HAVE_LRDF && !defined NO_PLUGIN_STATE)
+	if (!isdigit (unique_id[0])) {
+		return p;
+	}
+	uint32_t id = atol (unique_id);
+	lrdf_uris* set_uris = lrdf_get_setting_uris(id);
+
+	if (set_uris) {
+		for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
+			if (char* label = lrdf_get_label (set_uris->items[i])) {
+				p.push_back (Plugin::PresetRecord (set_uris->items[i], label));
+			}
+		}
+		lrdf_free_uris(set_uris);
+	}
+#endif
+	return p;
+}
+
 LadspaPluginInfo::LadspaPluginInfo()
 {
        type = ARDOUR::LADSPA;
diff --git a/libs/ardour/legatize.cc b/libs/ardour/legatize.cc
index 0c118a6..4d3d0f7 100644
--- a/libs/ardour/legatize.cc
+++ b/libs/ardour/legatize.cc
@@ -34,7 +34,7 @@ Legatize::operator()(boost::shared_ptr<ARDOUR::MidiModel> model,
                      Evoral::Beats                        position,
                      std::vector<Legatize::Notes>&        seqs)
 {
-	MidiModel::NoteDiffCommand* cmd = new MidiModel::NoteDiffCommand(model, "legatize");
+	MidiModel::NoteDiffCommand* cmd = new MidiModel::NoteDiffCommand(model, name ());
 
 	for (std::vector<Legatize::Notes>::iterator s = seqs.begin(); s != seqs.end(); ++s) {
 		for (Legatize::Notes::iterator i = (*s).begin(); i != (*s).end();) {
diff --git a/libs/ardour/load-save-session-collection.sh b/libs/ardour/load-save-session-collection.sh
new file mode 100755
index 0000000..ee2957f
--- /dev/null
+++ b/libs/ardour/load-save-session-collection.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# This script will run the load-save-session.sh script over each session in a
+# directory containing session directories.
+#
+# This script only supports the default option of the load-save-session.sh
+# script, so no valgind or gdb options as it isn't useful on more than a single
+# session at a time, use load-save-session.sh directly for that.
+
+DIR_PATH=$1
+if [ "$DIR_PATH" == "" ]; then
+	echo "Syntax: load-save-session-collection.sh <session collection dir>"
+	exit 1
+fi
+
+for SESSION_DIR in `find $DIR_PATH -mindepth 1 -maxdepth 1 -type d`; do
+	./load-save-session.sh $SESSION_DIR
+done
diff --git a/libs/ardour/load-save-session.sh b/libs/ardour/load-save-session.sh
new file mode 100755
index 0000000..cfa1ef5
--- /dev/null
+++ b/libs/ardour/load-save-session.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+#
+# Run load-save-session utility program on an existing session, as the session
+# may be modified I would not use this utility on a session that you care
+# about.
+#
+# The utility outputs some basic timing information and can be used to look at
+# changes in the Session file resulting from the save if for instance the
+# session is contained in a git repository.
+#
+
+TOP=`dirname "$0"`/../..
+. $TOP/build/gtk2_ardour/ardev_common_waf.sh
+ARDOUR_LIBS_DIR=$TOP/build/libs/ardour
+PROGRAM_NAME=load-save-session
+
+if [ ! -f './tempo.cc' ];
+	then echo "This script must be run from within the libs/ardour directory";
+	exit 1;
+fi
+
+OPTION=""
+if [ "$1" == "--debug" -o "$1" == "--valgrind" -o "$1" == "--massif" ]; then
+	OPTION=$1
+	shift 1
+fi
+
+DIR_PATH=$1
+if [ "$DIR_PATH" == "" ]; then
+	echo "Syntax: load-save-session.sh <session dir>"
+	exit 1
+fi
+
+NAME=`basename $DIR_PATH`
+
+if [ "$OPTION" == "--debug" ]; then
+	gdb --args $ARDOUR_LIBS_DIR/$PROGRAM_NAME $DIR_PATH $NAME
+elif [ "$OPTION" == "--valgrind" ]; then
+	MEMCHECK_OPTIONS="--leak-check=full"
+	valgrind $MEMCHECK_OPTIONS \
+	$ARDOUR_LIBS_DIR/$PROGRAM_NAME $DIR_PATH $NAME
+elif [ "$OPTION" == "--massif" ]; then
+	MASSIF_OPTIONS="--time-unit=ms --massif-out-file=massif.out.$NAME"
+	valgrind --tool=massif $MASSIF_OPTIONS \
+	$ARDOUR_LIBS_DIR/$PROGRAM_NAME $DIR_PATH $NAME
+else
+	$ARDOUR_LIBS_DIR/$PROGRAM_NAME $DIR_PATH $NAME
+fi
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 6867646..c39e40c 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -155,6 +155,7 @@ public:
 	LilvNode* units_midiNote;
 	LilvNode* patch_writable;
 	LilvNode* patch_Message;
+	LilvNode* lv2_noSampleAccurateCtrl;
 #ifdef HAVE_LV2_1_2_0
 	LilvNode* bufz_powerOf2BlockLength;
 	LilvNode* bufz_fixedBlockLength;
@@ -239,10 +240,14 @@ log_printf(LV2_Log_Handle handle,
 struct LV2Plugin::Impl {
 	Impl() : plugin(0), ui(0), ui_type(0), name(0), author(0), instance(0)
 	       , work_iface(0)
+#ifdef HAVE_LV2_1_2_0
 	       , opts_iface(0)
+#endif
 	       , state(0)
 	       , block_length(0)
+#ifdef HAVE_LV2_1_2_0
 	       , options(0)
+#endif
 	{}
 
 	/** Find the LV2 input port with the given designation.
@@ -257,12 +262,16 @@ struct LV2Plugin::Impl {
 	LilvNode*                    author;
 	LilvInstance*                instance;
 	const LV2_Worker_Interface*  work_iface;
+#ifdef HAVE_LV2_1_2_0
 	const LV2_Options_Interface* opts_iface;
+#endif
 	LilvState*                   state;
 	LV2_Atom_Forge               forge;
 	LV2_Atom_Forge               ui_forge;
 	int32_t                      block_length;
+#ifdef HAVE_LV2_1_2_0
 	LV2_Options_Option*          options;
+#endif
 };
 
 LV2Plugin::LV2Plugin (AudioEngine& engine,
@@ -278,6 +287,7 @@ LV2Plugin::LV2Plugin (AudioEngine& engine,
 	, _patch_port_in_index((uint32_t)-1)
 	, _patch_port_out_index((uint32_t)-1)
 	, _uri_map(URIMap::instance())
+	, _no_sample_accurate_ctrl (false)
 {
 	init(c_plugin, rate);
 }
@@ -292,6 +302,7 @@ LV2Plugin::LV2Plugin (const LV2Plugin& other)
 	, _patch_port_in_index((uint32_t)-1)
 	, _patch_port_out_index((uint32_t)-1)
 	, _uri_map(URIMap::instance())
+	, _no_sample_accurate_ctrl (false)
 {
 	init(other._impl->plugin, other._sample_rate);
 
@@ -441,12 +452,14 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
 	lilv_node_free(worker_iface_uri);
 
 
+#ifdef HAVE_LV2_1_2_0
 	LilvNode* options_iface_uri = lilv_new_uri(_world.world, LV2_OPTIONS__interface);
 	if (lilv_plugin_has_extension_data(plugin, options_iface_uri)) {
 		_impl->opts_iface = (const LV2_Options_Interface*)extension_data(
 			LV2_OPTIONS__interface);
 	}
 	lilv_node_free(options_iface_uri);
+#endif
 
 	if (lilv_plugin_has_feature(plugin, _world.lv2_inPlaceBroken)) {
 		error << string_compose(
@@ -471,6 +484,12 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
 		throw failed_constructor();
 	}
 	lilv_nodes_free(required_features);
+
+	LilvNodes* optional_features = lilv_plugin_get_optional_features (plugin);
+	if (lilv_nodes_contains (optional_features, _world.lv2_noSampleAccurateCtrl)) {
+		_no_sample_accurate_ctrl = true;
+	}
+	lilv_nodes_free(optional_features);
 #endif
 
 #ifdef HAVE_LILV_0_16_0
@@ -675,6 +694,25 @@ LV2Plugin::set_block_size (pframes_t nframes)
 	return 0;
 }
 
+bool
+LV2Plugin::requires_fixed_sized_buffers () const
+{
+	/* This controls if Ardour will split the plugin's run()
+	 * on automation events in order to pass sample-accurate automation
+	 * via standard control-ports.
+	 *
+	 * When returning true Ardour will *not* sub-divide the process-cycle.
+	 * Automation events that happen between cycle-start and cycle-end will be
+	 * ignored (ctrl values are interpolated to cycle-start).
+	 * NB. Atom Sequences are still sample accurate.
+	 *
+	 * Note: This does not guarantee a fixed block-size.
+	 * e.g The process cycle may be split when looping, also
+	 * the period-size may change any time: see set_block_size()
+	 */
+	return _no_sample_accurate_ctrl;
+}
+
 LV2Plugin::~LV2Plugin ()
 {
 	DEBUG_TRACE(DEBUG::LV2, string_compose("%1 destroy\n", name()));
@@ -686,7 +724,9 @@ LV2Plugin::~LV2Plugin ()
 	lilv_state_free(_impl->state);
 	lilv_node_free(_impl->name);
 	lilv_node_free(_impl->author);
+#ifdef HAVE_LV2_1_2_0
 	free(_impl->options);
+#endif
 
 	free(_features);
 	free(_make_path_feature.data);
@@ -928,7 +968,11 @@ LV2Plugin::c_ui_type()
 const std::string
 LV2Plugin::plugin_dir() const
 {
-	return Glib::build_filename(_session.plugins_dir(), _insert_id.to_s());
+	if (!_plugin_state_dir.empty ()){
+		return Glib::build_filename(_plugin_state_dir, _insert_id.to_s());
+	} else {
+		return Glib::build_filename(_session.plugins_dir(), _insert_id.to_s());
+	}
 }
 
 /** Directory for files created by the plugin (except during save). */
@@ -983,7 +1027,7 @@ LV2Plugin::add_state(XMLNode* root) const
 	assert(_insert_id != PBD::ID("0"));
 
 	XMLNode*    child;
-	char        buf[16];
+	char        buf[32];
 	LocaleGuard lg(X_("C"));
 
 	for (uint32_t i = 0; i < parameter_count(); ++i) {
@@ -996,6 +1040,10 @@ LV2Plugin::add_state(XMLNode* root) const
 		}
 	}
 
+	if (!_plugin_state_dir.empty()) {
+		root->add_property("template-dir", _plugin_state_dir);
+	}
+
 	if (_has_state_interface) {
 		// Provisionally increment state version and create directory
 		const std::string new_dir = state_dir(++_state_version);
@@ -1061,11 +1109,13 @@ LV2Plugin::find_presets()
 		const LilvNode* preset = lilv_nodes_get(presets, i);
 		lilv_world_load_resource(_world.world, preset);
 		LilvNode* name = get_value(_world.world, preset, rdfs_label);
+		bool userpreset = true; // TODO
 		if (name) {
 			_presets.insert(std::make_pair(lilv_node_as_string(preset),
 			                               Plugin::PresetRecord(
 				                               lilv_node_as_string(preset),
-				                               lilv_node_as_string(name))));
+				                               lilv_node_as_string(name),
+				                               userpreset)));
 			lilv_node_free(name);
 		} else {
 			warning << string_compose(
@@ -1624,7 +1674,19 @@ LV2Plugin::work_response(uint32_t size, const void* data)
 void
 LV2Plugin::set_insert_id(PBD::ID id)
 {
-	_insert_id = id;
+	if (_insert_id == "0") {
+		_insert_id = id;
+	} else if (_insert_id != id) {
+		lilv_state_free(_impl->state);
+		_impl->state = NULL;
+		_insert_id   = id;
+	}
+}
+
+void
+LV2Plugin::set_state_dir (const std::string& d)
+{
+	_plugin_state_dir = d;
 }
 
 int
@@ -1682,6 +1744,10 @@ LV2Plugin::set_state(const XMLNode& node, int version)
 		set_parameter(port_id, atof(value));
 	}
 
+	if ((prop = node.property("template-dir")) != 0) {
+		set_state_dir (prop->value ());
+	}
+
 	_state_version = 0;
 	if ((prop = node.property("state-dir")) != 0) {
 		if (sscanf(prop->value().c_str(), "state%u", &_state_version) != 1) {
@@ -1702,6 +1768,13 @@ LV2Plugin::set_state(const XMLNode& node, int version)
 		_impl->state = state;
 	}
 
+	if (!_plugin_state_dir.empty ()) {
+		// force save with session, next time (increment counter)
+		lilv_state_free (_impl->state);
+		_impl->state = NULL;
+		set_state_dir ("");
+	}
+
 	latency_compute_run();
 #endif
 
@@ -1842,7 +1915,6 @@ LV2Plugin::cleanup()
 {
 	DEBUG_TRACE(DEBUG::LV2, string_compose("%1 cleanup\n", name()));
 
-	activate();
 	deactivate();
 	lilv_instance_free(_impl->instance);
 	_impl->instance = NULL;
@@ -2436,6 +2508,7 @@ LV2World::LV2World()
 	units_db           = lilv_new_uri(world, LV2_UNITS__db);
 	patch_writable     = lilv_new_uri(world, LV2_PATCH__writable);
 	patch_Message      = lilv_new_uri(world, LV2_PATCH__Message);
+	lv2_noSampleAccurateCtrl = lilv_new_uri(world, LV2_CORE_PREFIX "noSampleAccurateControls");
 #ifdef HAVE_LV2_1_2_0
 	bufz_powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength);
 	bufz_fixedBlockLength    = lilv_new_uri(world, LV2_BUF_SIZE__fixedBlockLength);
@@ -2451,6 +2524,7 @@ LV2World::~LV2World()
 	lilv_node_free(bufz_fixedBlockLength);
 	lilv_node_free(bufz_powerOf2BlockLength);
 #endif
+	lilv_node_free(lv2_noSampleAccurateCtrl);
 	lilv_node_free(patch_Message);
 	lilv_node_free(patch_writable);
 	lilv_node_free(units_hz);
@@ -2549,6 +2623,76 @@ LV2PluginInfo::load(Session& session)
 	return PluginPtr();
 }
 
+std::vector<Plugin::PresetRecord>
+LV2PluginInfo::get_presets (bool /*user_only*/) const
+{
+	std::vector<Plugin::PresetRecord> p;
+#ifndef NO_PLUGIN_STATE
+	const LilvPlugin* lp = NULL;
+	try {
+		PluginPtr plugin;
+		const LilvPlugins* plugins = lilv_world_get_all_plugins(_world.world);
+		LilvNode* uri = lilv_new_uri(_world.world, _plugin_uri);
+		if (!uri) { throw failed_constructor(); }
+		lp = lilv_plugins_get_by_uri(plugins, uri);
+		if (!lp) { throw failed_constructor(); }
+		lilv_node_free(uri);
+	} catch (failed_constructor& err) {
+		return p;
+	}
+	assert (lp);
+	// see LV2Plugin::find_presets
+	LilvNode* lv2_appliesTo = lilv_new_uri(_world.world, LV2_CORE__appliesTo);
+	LilvNode* pset_Preset   = lilv_new_uri(_world.world, LV2_PRESETS__Preset);
+	LilvNode* rdfs_label    = lilv_new_uri(_world.world, LILV_NS_RDFS "label");
+
+	LilvNodes* presets = lilv_plugin_get_related(lp, pset_Preset);
+	LILV_FOREACH(nodes, i, presets) {
+		const LilvNode* preset = lilv_nodes_get(presets, i);
+		lilv_world_load_resource(_world.world, preset);
+		LilvNode* name = get_value(_world.world, preset, rdfs_label);
+		bool userpreset = true; // TODO
+		if (name) {
+			p.push_back (Plugin::PresetRecord (lilv_node_as_string(preset), lilv_node_as_string(name), userpreset));
+			lilv_node_free(name);
+		}
+	}
+	lilv_nodes_free(presets);
+	lilv_node_free(rdfs_label);
+	lilv_node_free(pset_Preset);
+	lilv_node_free(lv2_appliesTo);
+#endif
+	return p;
+}
+
+bool
+LV2PluginInfo::in_category (const std::string &c) const
+{
+	// TODO use untranslated lilv_plugin_get_class()
+	// match gtk2_ardour/plugin_selector.cc
+	if (category == c) {
+		return true;
+	}
+	return false;
+}
+
+bool
+LV2PluginInfo::is_instrument () const
+{
+	if (category == "Instrument") {
+		return true;
+	}
+#if 1
+	/* until we make sure that category remains untranslated in the lv2.ttl spec
+	 * and until most instruments also classify themselves as such, there's a 2nd check:
+	 */
+	if (n_inputs.n_midi() > 0 && n_inputs.n_audio() == 0 && n_outputs.n_audio() > 0) {
+		return true;
+	}
+#endif
+	return false;
+}
+
 PluginInfoList*
 LV2PluginInfo::discover()
 {
diff --git a/libs/ardour/lxvst_plugin.cc b/libs/ardour/lxvst_plugin.cc
index 4bf6fca..2c50144 100644
--- a/libs/ardour/lxvst_plugin.cc
+++ b/libs/ardour/lxvst_plugin.cc
@@ -17,6 +17,10 @@
 
 */
 
+#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+
+#include "ardour/filesystem_paths.h"
 #include "ardour/linux_vst_support.h"
 #include "ardour/session.h"
 #include "ardour/lxvst_plugin.h"
@@ -94,6 +98,70 @@ LXVSTPluginInfo::load (Session& session)
 	}
 }
 
+std::vector<Plugin::PresetRecord>
+LXVSTPluginInfo::get_presets (bool user_only) const
+{
+	std::vector<Plugin::PresetRecord> p;
+#ifndef NO_PLUGIN_STATE
+	if (!Config->get_use_lxvst()) {
+		return p;
+	}
+
+	if (!user_only) {
+		// TODO - cache, instantiating the plugin can be heavy
+		/* Built-in presets */
+		VSTHandle* handle = vstfx_load(path.c_str());
+		Session::vst_current_loading_id = atoi (unique_id);
+		AEffect* plugin = handle->main_entry (Session::vst_callback);
+		Session::vst_current_loading_id = 0;
+
+		plugin->dispatcher (plugin, effOpen, 0, 0, 0, 0); // :(
+		int const vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0);
+
+		for (int i = 0; i < plugin->numPrograms; ++i) {
+			Plugin::PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id, i), "", false);
+			if (vst_version >= 2) {
+				char buf[256];
+				if (plugin->dispatcher (plugin, 29, i, 0, buf, 0) == 1) {
+					r.label = buf;
+				} else {
+					r.label = string_compose (_("Preset %1"), i);
+				}
+			} else {
+				r.label = string_compose (_("Preset %1"), i);
+			}
+			p.push_back (r);
+		}
+
+		plugin->dispatcher (plugin, effMainsChanged, 0, 0, 0, 0);
+		plugin->dispatcher (plugin, effClose, 0, 0, 0, 0); // :(
+
+		if (handle->plugincnt) {
+			handle->plugincnt--;
+		}
+		vstfx_unload (handle);
+	}
+
+	/* user presets */
+	XMLTree* t = new XMLTree;
+	std::string pf = Glib::build_filename (ARDOUR::user_config_directory (), "presets", string_compose ("vst-%1", unique_id));
+	if (Glib::file_test (pf, Glib::FILE_TEST_EXISTS)) {
+		t->set_filename (pf);
+		if (t->read ()) { // TODO read names only. skip parsing the actual data
+			XMLNode* root = t->root ();
+			for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
+				XMLProperty* uri = (*i)->property (X_("uri"));
+				XMLProperty* label = (*i)->property (X_("label"));
+				p.push_back (Plugin::PresetRecord (uri->value(), label->value(), true));
+			}
+		}
+	}
+	delete t;
+#endif
+
+	return p;
+}
+
 LXVSTPluginInfo::LXVSTPluginInfo()
 {
        type = ARDOUR::LXVST;
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index 71f3e53..3a03a03 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -26,6 +26,7 @@
 
 #include "ardour/debug.h"
 #include "ardour/midi_buffer.h"
+#include "ardour/port.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -35,6 +36,7 @@ using namespace PBD;
 MidiBuffer::MidiBuffer(size_t capacity)
 	: Buffer (DataType::MIDI)
 	, _data (0)
+	, _size (0)
 {
 	if (capacity) {
 		resize (capacity);
@@ -85,7 +87,7 @@ MidiBuffer::copy(const MidiBuffer& copy)
  * Note that offset and nframes refer to sample time, NOT buffer offsets or event counts.
  */
 void
-MidiBuffer::read_from (const Buffer& src, framecnt_t nframes, framecnt_t dst_offset, framecnt_t src_offset)
+MidiBuffer::read_from (const Buffer& src, framecnt_t nframes, framecnt_t dst_offset, framecnt_t /* src_offset*/)
 {
 	assert (src.type() == DataType::MIDI);
 	assert (&src != this);
@@ -99,15 +101,19 @@ MidiBuffer::read_from (const Buffer& src, framecnt_t nframes, framecnt_t dst_off
 		assert (_size == 0);
 	}
 
-	/* XXX use dst_offset somehow */
+	framecnt_t offset = Port::port_offset();
 
 	for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) {
 		const Evoral::MIDIEvent<TimeType> ev(*i, false);
-		if (ev.time() >= src_offset && ev.time() < (nframes+src_offset)) {
+		if (ev.time() >= offset && ev.time() < (nframes + offset)) {
 			push_back (ev);
 		} else {
 			cerr << "MIDI event @ " <<  ev.time() << " skipped, not within range "
-			     << src_offset << " .. " << (nframes + src_offset) << endl;
+			     << offset << " .. " << (nframes + offset) << ":";
+				for (size_t xx = 0; xx < ev.size(); ++xx) {
+					cerr << ' ' << hex << (int) ev.buffer()[xx];
+				}
+				cerr << dec << endl;
 		}
 	}
 
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 43239f0..485967b 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -1437,6 +1437,7 @@ MidiDiskstream::get_playback (MidiBuffer& dst, framecnt_t nframes)
         // cerr << "----------------\n";
 
 	size_t events_read = 0;
+	const size_t split_cycle_offset = Port::port_offset ();
 
 	if (loc) {
 		framepos_t effective_start;
@@ -1454,11 +1455,13 @@ MidiDiskstream::get_playback (MidiBuffer& dst, framecnt_t nframes)
 			   beyond the loop end.
 			*/
 
-			_playback_buf->resolve_tracker (dst, 0);
+			_playback_buf->resolve_tracker (dst, split_cycle_offset);
 		}
 
 		_playback_buf->skip_to (effective_start);
 
+		/* for split-cycles we need to offset the events */
+
 		if (loc->end() >= effective_start && loc->end() < effective_start + nframes) {
 			/* end of loop is within the range we are reading, so
 			   split the read in two, and lie about the location
@@ -1475,23 +1478,23 @@ MidiDiskstream::get_playback (MidiBuffer& dst, framecnt_t nframes)
 			if (first) {
 				DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #1, from %1 for %2\n",
 										      effective_start, first));
-				events_read = _playback_buf->read (dst, effective_start, first);
+				events_read = _playback_buf->read (dst, effective_start, first, split_cycle_offset);
 			}
 
 			if (second) {
 				DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #2, from %1 for %2\n",
 										      loc->start(), second));
-				events_read += _playback_buf->read (dst, loc->start(), second);
+				events_read += _playback_buf->read (dst, loc->start(), second, split_cycle_offset);
 			}
 
 		} else {
 			DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #3, adjusted start as %1 for %2\n",
 									      effective_start, nframes));
-			events_read = _playback_buf->read (dst, effective_start, effective_start + nframes);
+			events_read = _playback_buf->read (dst, effective_start, effective_start + nframes, split_cycle_offset);
 		}
 	} else {
 		_playback_buf->skip_to (playback_sample);
-		events_read = _playback_buf->read (dst, playback_sample, playback_sample + nframes);
+		events_read = _playback_buf->read (dst, playback_sample, playback_sample + nframes, split_cycle_offset);
 	}
 
 	DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose (
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index fd08428..1950fbe 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -1665,9 +1665,9 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
 
 		if ((sb > sa) && (eb <= ea)) {
 			overlap = OverlapInternal;
-		} else if ((eb >= sa) && (eb <= ea)) {
+		} else if ((eb > sa) && (eb <= ea)) {
 			overlap = OverlapStart;
-		} else if ((sb > sa) && (sb <= ea)) {
+		} else if ((sb > sa) && (sb < ea)) {
 			overlap = OverlapEnd;
 		} else if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
 			overlap = OverlapExternal;
@@ -1983,44 +1983,18 @@ MidiModel::insert_silence_at_start (TimeType t)
 	}
 }
 
-/** Transpose notes in a time range by a given number of semitones.  Notes
- *  will be clamped at 0 and 127 if the transposition would make them exceed
- *  that range.
- *
- *  @param from Start time.
- *  @param end End time.
- *  @param semitones Number of semitones to transpose by (+ve is higher, -ve is lower).
- */
 void
-MidiModel::transpose (TimeType from, TimeType to, int semitones)
+MidiModel::transpose (NoteDiffCommand* c, const NotePtr note_ptr, int semitones)
 {
-	boost::shared_ptr<const MidiSource> s = midi_source ();
-
-	NoteDiffCommand* c = new_note_diff_command (_("transpose"));
-
-	for (Notes::iterator i = notes().begin(); i != notes().end(); ++i) {
-
-		if ((*i)->time() >= to) {
-
-			/* finished */
-			break;
+	int new_note = note_ptr->note() + semitones;
 
-		} else if ((*i)->time() >= from) {
-
-			int new_note = (*i)->note() + semitones;
-
-			if (new_note < 0) {
-				new_note = 0;
-			} else if (new_note > 127) {
-				new_note = 127;
-			}
-
-			c->change (*i, NoteDiffCommand::NoteNumber, (uint8_t) new_note);
-
-		}
+	if (new_note < 0) {
+		new_note = 0;
+	} else if (new_note > 127) {
+		new_note = 127;
 	}
 
-	apply_command (s->session (), c);
+	c->change (note_ptr, NoteDiffCommand::NoteNumber, (uint8_t) new_note);
 }
 
 void
diff --git a/libs/ardour/midi_patch_manager.cc b/libs/ardour/midi_patch_manager.cc
index 4f5cff1..133f4ee 100644
--- a/libs/ardour/midi_patch_manager.cc
+++ b/libs/ardour/midi_patch_manager.cc
@@ -25,8 +25,6 @@
 #include "pbd/file_utils.h"
 #include "pbd/error.h"
 
-#include "ardour/session.h"
-#include "ardour/session_directory.h"
 #include "ardour/midi_patch_manager.h"
 
 #include "ardour/search_paths.h"
@@ -43,123 +41,153 @@ MidiPatchManager* MidiPatchManager::_manager = 0;
 
 MidiPatchManager::MidiPatchManager ()
 {
-	refresh ();
+	add_search_path(midi_patch_search_path ());
 }
 
 void
-MidiPatchManager::set_session (Session* s)
+MidiPatchManager::add_search_path (const Searchpath& search_path)
 {
-	SessionHandlePtr::set_session (s);
-	refresh ();
-	add_session_patches ();
+	for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
+
+		if (_search_path.contains(*i)) {
+			// already processed files from this path
+			continue;
+		}
+
+		if (!Glib::file_test (*i, Glib::FILE_TEST_EXISTS)) {
+			continue;
+		}
+
+		if (!Glib::file_test (*i, Glib::FILE_TEST_IS_DIR)) {
+			continue;
+		}
+
+		add_midnam_files_from_directory (*i);
+
+		_search_path.add_directory (*i);
+	}
 }
 
 void
-MidiPatchManager::add_session_patches ()
+MidiPatchManager::add_midnam_files_from_directory(const std::string& directory_path)
 {
-	if (!_session) {
-		return;
-	}
+	vector<std::string> result;
+	find_files_matching_pattern (result, directory_path, "*.midnam");
 
-	std::string path_to_patches = _session->session_directory().midi_patch_path();
+	info << string_compose(
+			P_("Loading %1 MIDI patch from %2", "Loading %1 MIDI patches from %2", result.size()),
+			result.size(), directory_path)
+	     << endmsg;
 
-	if (!Glib::file_test (path_to_patches, Glib::FILE_TEST_EXISTS)) {
-		return;
+	for (vector<std::string>::const_iterator i = result.begin(); i != result.end(); ++i) {
+		add_midi_name_document (*i);
 	}
+}
 
-	assert (Glib::file_test (path_to_patches, Glib::FILE_TEST_IS_DIR));
+void
+MidiPatchManager::remove_search_path (const Searchpath& search_path)
+{
+	for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
 
-	vector<std::string> result;
+		if (!_search_path.contains(*i)) {
+			continue;
+		}
 
-	find_files_matching_pattern (result, path_to_patches, "*.midnam");
-
-	info << "Loading " << result.size() << " MIDI patches from " << path_to_patches << endmsg;
-
-	for (vector<std::string>::iterator i = result.begin(); i != result.end(); ++i) {
-		boost::shared_ptr<MIDINameDocument> document(new MIDINameDocument(*i));
-		for (MIDINameDocument::MasterDeviceNamesList::const_iterator device =
-					document->master_device_names_by_model().begin();
-				device != document->master_device_names_by_model().end();
-				++device) {
-			//cerr << "got model " << device->first << endl;
-			// have access to the documents by model name
-			_documents[device->first] = document;
-			// build a list of all master devices from all documents
-			_master_devices_by_model[device->first] = device->second;
-			_all_models.insert(device->first);
-			const std::string& manufacturer = device->second->manufacturer();
-			if (_devices_by_manufacturer.find(manufacturer) == _devices_by_manufacturer.end()) {
-				MIDINameDocument::MasterDeviceNamesList empty;
-				_devices_by_manufacturer.insert(std::make_pair(manufacturer, empty));
-			}
-			_devices_by_manufacturer[manufacturer].insert(std::make_pair(device->first, device->second));
+		remove_midnam_files_from_directory(*i);
 
-			// make sure there are no double model names
-			// TODO: handle this gracefully.
-			assert(_documents.count(device->first) == 1);
-			assert(_master_devices_by_model.count(device->first) == 1);
-		}
+		_search_path.remove_directory (*i);
 	}
 }
 
 void
-MidiPatchManager::refresh()
+MidiPatchManager::remove_midnam_files_from_directory(const std::string& directory_path)
 {
-	_documents.clear();
-	_master_devices_by_model.clear();
-	_all_models.clear();
-	_devices_by_manufacturer.clear();
-
-	Searchpath search_path = midi_patch_search_path ();
 	vector<std::string> result;
+	find_files_matching_pattern (result, directory_path, "*.midnam");
 
-	find_files_matching_pattern (result, search_path, "*.midnam");
+	info << string_compose(
+			P_("Unloading %1 MIDI patch from %2", "Unloading %1 MIDI patches from %2", result.size()),
+			result.size(), directory_path)
+	     << endmsg;
 
-	info << "Loading " << result.size() << " MIDI patches from " << search_path.to_string() << endmsg;
+	for (vector<std::string>::const_iterator i = result.begin(); i != result.end(); ++i) {
+		remove_midi_name_document (*i);
+	}
+}
 
-	for (vector<std::string>::iterator i = result.begin(); i != result.end(); ++i) {
-		boost::shared_ptr<MIDINameDocument> document;
-		try {
-			document = boost::shared_ptr<MIDINameDocument>(new MIDINameDocument(*i));
-		} catch (...) {
-			error << "Error parsing MIDI patch file " << *i << endmsg;
+bool
+MidiPatchManager::add_midi_name_document (const std::string& file_path)
+{
+	boost::shared_ptr<MIDINameDocument> document;
+	try {
+		document = boost::shared_ptr<MIDINameDocument>(new MIDINameDocument(file_path));
+	}
+	catch (...) {
+		error << string_compose(_("Error parsing MIDI patch file %1"), file_path)
+		      << endmsg;
+		return false;
+	}
+	for (MIDINameDocument::MasterDeviceNamesList::const_iterator device =
+	         document->master_device_names_by_model().begin();
+	     device != document->master_device_names_by_model().end();
+	     ++device) {
+		if (_documents.find(device->first) != _documents.end()) {
+			warning << string_compose(_("Duplicate MIDI device `%1' in `%2' ignored"),
+			                          device->first,
+			                          file_path) << endmsg;
 			continue;
 		}
-		for (MIDINameDocument::MasterDeviceNamesList::const_iterator device =
-			     document->master_device_names_by_model().begin();
-		     device != document->master_device_names_by_model().end();
-		     ++device) {
-			if (_documents.find(device->first) != _documents.end()) {
-				warning << string_compose(_("Duplicate MIDI device `%1' in `%2' ignored"),
-				                          device->first, *i)
-				        << endmsg;
-				continue;
-			}
 
-			_documents[device->first]               = document;
-			_master_devices_by_model[device->first] = device->second;
+		_documents[device->first] = document;
+		_master_devices_by_model[device->first] = device->second;
 
-			_all_models.insert(device->first);
-			const std::string& manufacturer = device->second->manufacturer();
-			if (_devices_by_manufacturer.find(manufacturer) == _devices_by_manufacturer.end()) {
-				MIDINameDocument::MasterDeviceNamesList empty;
-				_devices_by_manufacturer.insert(std::make_pair(manufacturer, empty));
-			}
-			_devices_by_manufacturer[manufacturer].insert(std::make_pair(device->first, device->second));
+		_all_models.insert(device->first);
+		const std::string& manufacturer = device->second->manufacturer();
+		if (_devices_by_manufacturer.find(manufacturer) ==
+		    _devices_by_manufacturer.end()) {
+			MIDINameDocument::MasterDeviceNamesList empty;
+			_devices_by_manufacturer.insert(std::make_pair(manufacturer, empty));
 		}
-	}
+		_devices_by_manufacturer[manufacturer].insert(
+		    std::make_pair(device->first, device->second));
 
-	if (_session) {
-		add_session_patches ();
+		// TODO: handle this gracefully.
+		assert(_documents.count(device->first) == 1);
+		assert(_master_devices_by_model.count(device->first) == 1);
 	}
+	return true;
 }
 
-void
-MidiPatchManager::session_going_away ()
+bool
+MidiPatchManager::remove_midi_name_document (const std::string& file_path)
 {
-	SessionHandlePtr::session_going_away ();
-	_documents.clear();
-	_master_devices_by_model.clear();
-	_all_models.clear();
-	_devices_by_manufacturer.clear();
+	bool removed = false;
+	for (MidiNameDocuments::iterator i = _documents.begin(); i != _documents.end();) {
+		if (i->second->file_path() == file_path) {
+
+			boost::shared_ptr<MIDINameDocument> document = i->second;
+
+			info << string_compose(_("Removing MIDI patch file %1"), file_path) << endmsg;
+
+			_documents.erase(i++);
+
+			for (MIDINameDocument::MasterDeviceNamesList::const_iterator device =
+			         document->master_device_names_by_model().begin();
+			     device != document->master_device_names_by_model().end();
+			     ++device) {
+
+				_master_devices_by_model.erase(device->first);
+
+				_all_models.erase(device->first);
+
+				const std::string& manufacturer = device->second->manufacturer();
+
+				_devices_by_manufacturer[manufacturer].erase(device->first);
+			}
+			removed = true;
+		} else {
+			++i;
+		}
+	}
+	return removed;
 }
diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc
index d959ff9..2942ade 100644
--- a/libs/ardour/midi_port.cc
+++ b/libs/ardour/midi_port.cc
@@ -180,7 +180,7 @@ MidiPort::resolve_notes (void* port_buffer, MidiBuffer::TimeType when)
 
 		ev[1] = MIDI_CTL_ALL_NOTES_OFF;
 
-		if (port_engine.midi_event_put (port_buffer, 0, ev, 3) != 0) {
+		if (port_engine.midi_event_put (port_buffer, when, ev, 3) != 0) {
 			cerr << "failed to deliver ALL NOTES OFF on channel " << (int)channel << " on port " << name() << endl;
 		}
 	}
@@ -196,7 +196,7 @@ MidiPort::flush_buffers (pframes_t nframes)
 		if (_resolve_required) {
 			port_buffer = port_engine.get_buffer (_port_handle, nframes);
 			/* resolve all notes at the start of the buffer */
-			resolve_notes (port_buffer, 0);
+			resolve_notes (port_buffer, _global_port_buffer_offset);
 			_resolve_required = false;
 		}
 
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index 3e4a656..56472e4 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -458,14 +458,6 @@ MidiRegion::fix_negative_start ()
 	_start_beats = Evoral::Beats();
 }
 
-/** Transpose the notes in this region by a given number of semitones */
-void
-MidiRegion::transpose (int semitones)
-{
-	BeatsFramesConverter c (_session.tempo_map(), _start);
-	model()->transpose (c.from (_start), c.from (_start + _length), semitones);
-}
-
 void
 MidiRegion::set_start_internal (framecnt_t s)
 {
diff --git a/libs/ardour/midi_scene_changer.cc b/libs/ardour/midi_scene_changer.cc
index f586206..7f6c865 100644
--- a/libs/ardour/midi_scene_changer.cc
+++ b/libs/ardour/midi_scene_changer.cc
@@ -226,13 +226,16 @@ MIDISceneChanger::locate (framepos_t pos)
 }
 
 void
-MIDISceneChanger::set_input_port (MIDI::Port* mp)
+MIDISceneChanger::set_input_port (boost::shared_ptr<MidiPort> mp)
 {
-	input_port = mp;
-
 	incoming_connections.drop_connections();
+	input_port.reset ();
+
+	boost::shared_ptr<AsyncMIDIPort> async = boost::dynamic_pointer_cast<AsyncMIDIPort> (mp);
+
+	if (async) {
 
-	if (input_port) {
+		input_port = mp;
 
 		/* midi port is asynchronous. MIDI parsing will be carried out
 		 * by the MIDI UI thread which will emit the relevant signals
@@ -240,8 +243,8 @@ MIDISceneChanger::set_input_port (MIDI::Port* mp)
 		 */
 
 		for (int channel = 0; channel < 16; ++channel) {
-			input_port->parser()->channel_bank_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::bank_change_input, this, _1, _2, channel));
-			input_port->parser()->channel_program_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::program_change_input, this, _1, _2, channel));
+			async->parser()->channel_bank_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::bank_change_input, this, _1, _2, channel));
+			async->parser()->channel_program_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::program_change_input, this, _1, _2, channel));
 		}
 	}
 }
@@ -286,7 +289,7 @@ MIDISceneChanger::program_change_input (MIDI::Parser& parser, MIDI::byte program
 
 		int bank = -1;
 		if (have_seen_bank_changes) {
-			bank = input_port->channel (channel)->bank();
+			bank = boost::dynamic_pointer_cast<AsyncMIDIPort>(input_port)->channel (channel)->bank();
 		}
 
 		jump_to (bank, program);
@@ -317,7 +320,7 @@ MIDISceneChanger::program_change_input (MIDI::Parser& parser, MIDI::byte program
 
 	int bank = -1;
 	if (have_seen_bank_changes) {
-		bank = input_port->channel (channel)->bank();
+		bank = boost::dynamic_pointer_cast<AsyncMIDIPort>(input_port)->channel (channel)->bank();
 	}
 
 	MIDISceneChange* msc =new MIDISceneChange (channel, bank, program & 0x7f);
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index f3bc2c4..69d10c4 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -394,6 +394,16 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
 		return dret;
 	}
 
+	if (_mute_control->list() && _mute_control->automation_playback()) {
+		bool        valid = false;
+		const float mute  = _mute_control->list()->rt_safe_eval(transport_frame, valid);
+		if (mute >= 0.5 && !muted()) {
+			_mute_control->set_value_unchecked(1.0);  // mute
+		} else if (mute < 0.5 && muted()) {
+			_mute_control->set_value_unchecked(0.0);  // unmute
+		}
+	}
+
 	BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
 
 	fill_buffers_with_input (bufs, _input, nframes);
@@ -533,7 +543,7 @@ MidiTrack::non_realtime_locate (framepos_t pos)
 		    (rcontrol = region->control(tcontrol->parameter()))) {
 			const Evoral::Beats pos_beats = bfc.from(pos - origin);
 			if (rcontrol->list()->size() > 0) {
-				tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()));
+				tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup);
 			}
 		}
 	}
@@ -715,7 +725,15 @@ MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState st
 }
 
 void
-MidiTrack::MidiControl::set_value(double val)
+MidiTrack::MidiControl::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+{
+	if (writable()) {
+		set_value_unchecked (val);
+	}
+}
+
+void
+MidiTrack::MidiControl::set_value_unchecked(double val)
 {
 	const Evoral::Parameter &parameter = _list ? _list->parameter() : Control::parameter();
 	const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
@@ -772,7 +790,7 @@ MidiTrack::MidiControl::set_value(double val)
 		_route->write_immediate_event(size,  ev);
 	}
 
-	AutomationControl::set_value(val);
+	AutomationControl::set_value(val, Controllable::NoGroup);
 }
 
 void
@@ -927,7 +945,7 @@ MidiTrack::act_on_mute ()
 		}
 
 		/* Resolve active notes. */
-		midi_diskstream()->resolve_tracker(_immediate_events, 0);
+		midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset());
 	}
 }
 
diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc
index 59c718a..1d2fe7c 100644
--- a/libs/ardour/midi_ui.cc
+++ b/libs/ardour/midi_ui.cc
@@ -44,7 +44,7 @@ MidiControlUI* MidiControlUI::_instance = 0;
 #include "pbd/abstract_ui.cc"  /* instantiate the template */
 
 MidiControlUI::MidiControlUI (Session& s)
-	: AbstractUI<MidiUIRequest> (X_("midiui"))
+	: AbstractUI<MidiUIRequest> (X_("midiUI"))
 	, _session (s)
 {
 	_instance = this;
@@ -60,6 +60,17 @@ MidiControlUI::~MidiControlUI ()
 	_instance = 0;
 }
 
+void*
+MidiControlUI::request_factory (uint32_t num_requests)
+{
+	/* AbstractUI<T>::request_buffer_factory() is a template method only
+	   instantiated in this source module. To provide something visible for
+	   use when registering the factory, we have this static method that is
+	   template-free.
+	*/
+	return request_buffer_factory (num_requests);
+}
+
 void
 MidiControlUI::do_request (MidiUIRequest* req)
 {
@@ -71,9 +82,9 @@ MidiControlUI::do_request (MidiUIRequest* req)
 }
 
 bool
-MidiControlUI::midi_input_handler (IOCondition ioc, AsyncMIDIPort* port)
+MidiControlUI::midi_input_handler (IOCondition ioc, boost::shared_ptr<AsyncMIDIPort> port)
 {
-	DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on  %1\n", ((ARDOUR::Port*)port)->name()));
+	DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on  %1\n", boost::shared_ptr<ARDOUR::Port> (port)->name()));
 
 	if (ioc & ~IO_IN) {
 		return false;
@@ -81,12 +92,8 @@ MidiControlUI::midi_input_handler (IOCondition ioc, AsyncMIDIPort* port)
 
 	if (ioc & IO_IN) {
 
-		AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*> (port);
-		if (asp) {
-			asp->clear ();
-		}
-
-		DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", ((ARDOUR::Port*)port)->name()));
+		port->clear ();
+		DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", boost::shared_ptr<ARDOUR::Port>(port)->name()));
 		framepos_t now = _session.engine().sample_time();
 		port->parse (now);
 	}
@@ -102,19 +109,19 @@ MidiControlUI::clear_ports ()
 void
 MidiControlUI::reset_ports ()
 {
-	vector<AsyncMIDIPort*> ports;
-	AsyncMIDIPort* p;
+	vector<boost::shared_ptr<AsyncMIDIPort> > ports;
+	boost::shared_ptr<AsyncMIDIPort> p;
 
-	if ((p = dynamic_cast<AsyncMIDIPort*> (_session.midi_input_port()))) {
+	if ((p = boost::dynamic_pointer_cast<AsyncMIDIPort> (_session.midi_input_port()))) {
 		ports.push_back (p);
 	}
 
 
-	if ((p = dynamic_cast<AsyncMIDIPort*> (_session.mmc_input_port()))) {
+	if ((p = boost::dynamic_pointer_cast<AsyncMIDIPort> (_session.mmc_input_port()))) {
 		ports.push_back (p);
 	}
 
-	if ((p = dynamic_cast<AsyncMIDIPort*> (_session.scene_input_port()))) {
+	if ((p = boost::dynamic_pointer_cast<AsyncMIDIPort> (_session.scene_input_port()))) {
 		ports.push_back (p);
 	}
 
@@ -122,7 +129,7 @@ MidiControlUI::reset_ports ()
 		return;
 	}
 
-	for (vector<AsyncMIDIPort*>::const_iterator pi = ports.begin(); pi != ports.end(); ++pi) {
+	for (vector<boost::shared_ptr<AsyncMIDIPort> >::const_iterator pi = ports.begin(); pi != ports.end(); ++pi) {
 		(*pi)->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), *pi));
 		(*pi)->xthread().attach (_main_loop->get_context());
 	}
@@ -135,8 +142,8 @@ MidiControlUI::thread_init ()
 
 	pthread_set_name (X_("midiUI"));
 
-	PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MIDI"), 2048);
-	SessionEvent::create_per_thread_pool (X_("MIDI I/O"), 128);
+	PBD::notify_event_loops_about_thread_creation (pthread_self(), X_("midiUI"), 2048);
+	SessionEvent::create_per_thread_pool (X_("midiUI"), 128);
 
 	memset (&rtparam, 0, sizeof (rtparam));
 	rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
diff --git a/libs/ardour/midiport_manager.cc b/libs/ardour/midiport_manager.cc
index 5460df3..7f3f05a 100644
--- a/libs/ardour/midiport_manager.cc
+++ b/libs/ardour/midiport_manager.cc
@@ -83,23 +83,6 @@ MidiPortManager::create_ports ()
 	_scene_in  = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("Scene in"), true);
 	_scene_out = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("Scene out"), true);
 
-	/* XXX nasty type conversion needed because of the mixed inheritance
-	 * required to integrate MIDI::IPMidiPort and ARDOUR::AsyncMIDIPort.
-	 *
-	 * At some point, we'll move IPMidiPort into Ardour and make it
-	 * inherit from ARDOUR::MidiPort not MIDI::Port, and then this
-	 * mess can go away
-	 */
-
-	_midi_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_in).get();
-	_midi_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_out).get();
-
-	_mmc_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_in).get();
-	_mmc_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_out).get();
-
-	_scene_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_scene_in).get();
-	_scene_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_scene_out).get();
-
 	/* Now register ports used for sync (MTC and MIDI Clock)
 	 */
 
@@ -137,12 +120,12 @@ MidiPortManager::set_midi_port_states (const XMLNodeList&nodes)
 	ports.insert (make_pair (_mtc_output_port->name(), _mtc_output_port));
 	ports.insert (make_pair (_midi_clock_input_port->name(), _midi_clock_input_port));
 	ports.insert (make_pair (_midi_clock_output_port->name(), _midi_clock_output_port));
-	ports.insert (make_pair (_midi_input_port->name(), _midi_in));
-	ports.insert (make_pair (_midi_output_port->name(), _midi_out));
-	ports.insert (make_pair (_mmc_input_port->name(), _mmc_in));
-	ports.insert (make_pair (_mmc_output_port->name(), _mmc_out));
-	ports.insert (make_pair (_scene_output_port->name(), _scene_out));
-	ports.insert (make_pair (_scene_input_port->name(), _scene_in));
+	ports.insert (make_pair (_midi_in->name(), _midi_in));
+	ports.insert (make_pair (_midi_out->name(), _midi_out));
+	ports.insert (make_pair (_mmc_in->name(), _mmc_in));
+	ports.insert (make_pair (_mmc_out->name(), _mmc_out));
+	ports.insert (make_pair (_scene_out->name(), _scene_out));
+	ports.insert (make_pair (_scene_in->name(), _scene_in));
 
 	for (XMLNodeList::const_iterator n = nodes.begin(); n != nodes.end(); ++n) {
 		if ((prop = (*n)->property (X_("name"))) == 0) {
@@ -169,12 +152,12 @@ MidiPortManager::get_midi_port_states () const
 	ports.insert (make_pair (_mtc_output_port->name(), _mtc_output_port));
 	ports.insert (make_pair (_midi_clock_input_port->name(), _midi_clock_input_port));
 	ports.insert (make_pair (_midi_clock_output_port->name(), _midi_clock_output_port));
-	ports.insert (make_pair (_midi_input_port->name(), _midi_in));
-	ports.insert (make_pair (_midi_output_port->name(), _midi_out));
-	ports.insert (make_pair (_mmc_input_port->name(), _mmc_in));
-	ports.insert (make_pair (_mmc_output_port->name(), _mmc_out));
-	ports.insert (make_pair (_scene_output_port->name(), _scene_out));
-	ports.insert (make_pair (_scene_input_port->name(), _scene_in));
+	ports.insert (make_pair (_midi_in->name(), _midi_in));
+	ports.insert (make_pair (_midi_out->name(), _midi_out));
+	ports.insert (make_pair (_mmc_in->name(), _mmc_in));
+	ports.insert (make_pair (_mmc_out->name(), _mmc_out));
+	ports.insert (make_pair (_scene_out->name(), _scene_out));
+	ports.insert (make_pair (_scene_in->name(), _scene_in));
 
 	for (PortMap::const_iterator p = ports.begin(); p != ports.end(); ++p) {
 		s.push_back (&p->second->get_state());
diff --git a/libs/ardour/monitor_processor.cc b/libs/ardour/monitor_processor.cc
index 92beed5..6b73af6 100644
--- a/libs/ardour/monitor_processor.cc
+++ b/libs/ardour/monitor_processor.cc
@@ -37,7 +37,7 @@ using namespace std;
 /* specialize for bool because of set_value() semantics */
 
 namespace ARDOUR {
-        template<> void MPControl<bool>::set_value (double v) {
+	template<> void MPControl<bool>::set_value (double v, PBD::Controllable::GroupControlDisposition /*group_override*/) {
                 bool newval = fabs (v) >= 0.5;
                 if (newval != _value) {
                         _value = newval;
@@ -49,6 +49,7 @@ namespace ARDOUR {
 MonitorProcessor::MonitorProcessor (Session& s)
         : Processor (s, X_("MonitorOut"))
         , solo_cnt (0)
+        , _monitor_active (false)
 
         , _dim_all_ptr (new MPControl<bool> (false, _("monitor dim"), Controllable::Toggle))
         , _cut_all_ptr (new MPControl<bool> (false, _("monitor cut"), Controllable::Toggle))
@@ -218,7 +219,8 @@ MonitorProcessor::set_state (const XMLNode& node, int version)
                 }
         }
 
-        return 0;
+	update_monitor_state ();
+	return 0;
 }
 
 XMLNode&
@@ -363,61 +365,68 @@ MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount&
 void
 MonitorProcessor::set_polarity (uint32_t chn, bool invert)
 {
-        if (invert) {
-                _channels[chn]->polarity = -1.0f;
-        } else {
-                _channels[chn]->polarity = 1.0f;
-        }
+	if (invert) {
+		_channels[chn]->polarity = -1.0f;
+	} else {
+		_channels[chn]->polarity = 1.0f;
+	}
+	update_monitor_state ();
 }
 
 void
 MonitorProcessor::set_dim (uint32_t chn, bool yn)
 {
-        _channels[chn]->dim = yn;
+	_channels[chn]->dim = yn;
+	update_monitor_state ();
 }
 
 void
 MonitorProcessor::set_cut (uint32_t chn, bool yn)
 {
-        if (yn) {
-                _channels[chn]->cut = GAIN_COEFF_ZERO;
-        } else {
-                _channels[chn]->cut = GAIN_COEFF_UNITY;
-        }
+	if (yn) {
+		_channels[chn]->cut = GAIN_COEFF_ZERO;
+	} else {
+		_channels[chn]->cut = GAIN_COEFF_UNITY;
+	}
+	update_monitor_state ();
 }
 
 void
 MonitorProcessor::set_solo (uint32_t chn, bool solo)
 {
-        if (solo != _channels[chn]->soloed) {
-                _channels[chn]->soloed = solo;
-
-                if (solo) {
-                        solo_cnt++;
-                } else {
-                        if (solo_cnt > 0) {
-                                solo_cnt--;
-                        }
-                }
-        }
+	if (solo != _channels[chn]->soloed) {
+		_channels[chn]->soloed = solo;
+
+		if (solo) {
+			solo_cnt++;
+		} else {
+			if (solo_cnt > 0) {
+				solo_cnt--;
+			}
+		}
+	}
+	update_monitor_state ();
 }
 
 void
 MonitorProcessor::set_mono (bool yn)
 {
-        _mono = yn;
+	_mono = yn;
+	update_monitor_state ();
 }
 
 void
 MonitorProcessor::set_cut_all (bool yn)
 {
-        _cut_all = yn;
+	_cut_all = yn;
+	update_monitor_state ();
 }
 
 void
 MonitorProcessor::set_dim_all (bool yn)
 {
-        _dim_all = yn;
+	_dim_all = yn;
+	update_monitor_state ();
 }
 
 bool
@@ -470,6 +479,29 @@ MonitorProcessor::cut_all () const
         return _cut_all;
 }
 
+void
+MonitorProcessor::update_monitor_state ()
+{
+	bool en = false;
+
+	if (_cut_all || _dim_all || _mono) {
+		en = true;
+	}
+
+	const uint32_t nchans = _channels.size();
+	for (uint32_t i = 0; i < nchans && !en; ++i) {
+		if (cut (i) || dimmed (i) || soloed (i) || inverted (i)) {
+			en = true;
+			break;
+		}
+	}
+
+	if (_monitor_active != en) {
+		_monitor_active = en;
+		_session.MonitorChanged();
+	}
+}
+
 boost::shared_ptr<Controllable>
 MonitorProcessor::channel_cut_control (uint32_t chn) const
 {
diff --git a/libs/ardour/pan_controllable.cc b/libs/ardour/pan_controllable.cc
index ecffa17..faf04cc 100644
--- a/libs/ardour/pan_controllable.cc
+++ b/libs/ardour/pan_controllable.cc
@@ -35,13 +35,21 @@ PanControllable::lower () const
 }
 
 void
-PanControllable::set_value (double v)
+PanControllable::set_value (double v, PBD::Controllable::GroupControlDisposition /* group_override */)
 {
-        boost::shared_ptr<Panner> p = owner->panner();
+	if (writable()) {
+		set_value_unchecked (v);
+	}
+}
+
+void
+PanControllable::set_value_unchecked (double v)
+{
+	boost::shared_ptr<Panner> p = owner->panner();
 
         if (!p) {
                 /* no panner: just do it */
-                AutomationControl::set_value (v);
+	        AutomationControl::set_value (v, Controllable::NoGroup);
                 return;
         }
 
@@ -62,7 +70,7 @@ PanControllable::set_value (double v)
         }
 
         if (can_set) {
-                AutomationControl::set_value (v);
+	        AutomationControl::set_value (v, Controllable::NoGroup);
         }
 }
 
diff --git a/libs/ardour/pannable.cc b/libs/ardour/pannable.cc
index 247397d..f589024 100644
--- a/libs/ardour/pannable.cc
+++ b/libs/ardour/pannable.cc
@@ -242,27 +242,27 @@ Pannable::set_state (const XMLNode& root, int version)
 			if ((*niter)->name() == X_("azimuth")) {
 				prop = (*niter)->property (X_("value"));
 				if (prop) {
-					pan_azimuth_control->set_value (atof (prop->value()));
+					pan_azimuth_control->set_value (atof (prop->value()), Controllable::NoGroup);
 				}
 			} else if ((*niter)->name() == X_("width")) {
 				prop = (*niter)->property (X_("value"));
 				if (prop) {
-					pan_width_control->set_value (atof (prop->value()));
+					pan_width_control->set_value (atof (prop->value()), Controllable::NoGroup);
 				}
 			} else if ((*niter)->name() == X_("elevation")) {
 				prop = (*niter)->property (X_("value"));
 				if (prop) {
-					pan_elevation_control->set_value (atof (prop->value()));
+					pan_elevation_control->set_value (atof (prop->value()), Controllable::NoGroup);
 				}
 			} else if ((*niter)->name() == X_("frontback")) {
 				prop = (*niter)->property (X_("value"));
 				if (prop) {
-					pan_frontback_control->set_value (atof (prop->value()));
+					pan_frontback_control->set_value (atof (prop->value()), Controllable::NoGroup);
 				}
 			} else if ((*niter)->name() == X_("lfe")) {
 				prop = (*niter)->property (X_("value"));
 				if (prop) {
-					pan_lfe_control->set_value (atof (prop->value()));
+					pan_lfe_control->set_value (atof (prop->value()), Controllable::NoGroup);
 				}
 			}
 		}
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 0e58b4b..a4860eb 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -1256,13 +1256,12 @@ Playlist::flush_notifications (bool from_undo)
 
 	 RegionWriteLock rl (this);
 	 int itimes = (int) floor (times);
-	 framepos_t pos = position + 1;
 
 	 while (itimes--) {
 		 boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
-		 add_region_internal (copy, pos);
+		 add_region_internal (copy, position);
 		 set_layer (copy, DBL_MAX);
-		 pos += gap;
+		 position += gap;
 	 }
 
 	 if (floor (times) != times) {
@@ -1278,12 +1277,45 @@ Playlist::flush_notifications (bool from_undo)
 			 plist.add (Properties::name, name);
 
 			 boost::shared_ptr<Region> sub = RegionFactory::create (region, plist);
-			 add_region_internal (sub, pos);
+			 add_region_internal (sub, position);
 			 set_layer (sub, DBL_MAX);
 		 }
 	 }
  }
 
+/** @param gap from the beginning of the region to the next beginning */
+/** @param end the first frame that does _not_ contain a duplicated frame */
+void
+Playlist::duplicate_until (boost::shared_ptr<Region> region, framepos_t position, framecnt_t gap, framepos_t end)
+{
+	 RegionWriteLock rl (this);
+
+	 while (position + region->length() - 1 < end) {
+		 boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
+		 add_region_internal (copy, position);
+		 set_layer (copy, DBL_MAX);
+		 position += gap;
+	 }
+
+	 if (position < end) {
+		 framecnt_t length = min (region->length(), end - position);
+		 string name;
+		 RegionFactory::region_name (name, region->name(), false);
+
+		 {
+			 PropertyList plist;
+
+			 plist.add (Properties::start, region->start());
+			 plist.add (Properties::length, length);
+			 plist.add (Properties::name, name);
+
+			 boost::shared_ptr<Region> sub = RegionFactory::create (region, plist);
+			 add_region_internal (sub, position);
+			 set_layer (sub, DBL_MAX);
+		 }
+	 }
+}
+
  void
  Playlist::shift (framepos_t at, frameoffset_t distance, bool move_intersected, bool ignore_music_glue)
  {
diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc
index f14c567..31e9e2e 100644
--- a/libs/ardour/plugin.cc
+++ b/libs/ardour/plugin.cc
@@ -50,6 +50,7 @@
 #include "ardour/midi_state_tracker.h"
 #include "ardour/plugin.h"
 #include "ardour/plugin_manager.h"
+#include "ardour/port.h"
 #include "ardour/session.h"
 #include "ardour/types.h"
 
@@ -77,6 +78,8 @@ static bool seen_get_state_message = false;
 static bool seen_set_state_message = false;
 #endif
 
+PBD::Signal2<void, std::string, Plugin*> Plugin::PresetsChanged;
+
 bool
 PluginInfo::is_instrument () const
 {
@@ -92,6 +95,7 @@ Plugin::Plugin (AudioEngine& e, Session& s)
 	, _parameter_changed_since_last_preset (false)
 {
 	_pending_stop_events.ensure_buffers (DataType::MIDI, 1, 4096);
+	PresetsChanged.connect_same_thread (_preset_connection, boost::bind (&Plugin::update_presets, this, _1 ,_2));
 }
 
 Plugin::Plugin (const Plugin& other)
@@ -106,6 +110,7 @@ Plugin::Plugin (const Plugin& other)
 	, _parameter_changed_since_last_preset (false)
 {
 	_pending_stop_events.ensure_buffers (DataType::MIDI, 1, 4096);
+	PresetsChanged.connect_same_thread (_preset_connection, boost::bind (&Plugin::update_presets, this, _1 ,_2));
 }
 
 Plugin::~Plugin ()
@@ -115,23 +120,36 @@ Plugin::~Plugin ()
 void
 Plugin::remove_preset (string name)
 {
+	Plugin::PresetRecord const * p = preset_by_label (name);
+	if (!p->user) {
+		PBD::error << _("Cannot remove plugin factory preset.") << endmsg;
+		return;
+	}
+
 	do_remove_preset (name);
 	_presets.erase (preset_by_label (name)->uri);
 
 	_last_preset.uri = "";
 	_parameter_changed_since_last_preset = false;
 	PresetRemoved (); /* EMIT SIGNAL */
+	PresetsChanged (unique_id(), this); /* EMIT SIGNAL */
 }
 
 /** @return PresetRecord with empty URI on failure */
 Plugin::PresetRecord
 Plugin::save_preset (string name)
 {
+	if (preset_by_label (name)) {
+		PBD::error << _("Preset with given name already exists.") << endmsg;
+		return Plugin::PresetRecord ();
+	}
+
 	string const uri = do_save_preset (name);
 
 	if (!uri.empty()) {
 		_presets.insert (make_pair (uri, PresetRecord (uri, name)));
 		PresetAdded (); /* EMIT SIGNAL */
+		PresetsChanged (unique_id(), this); /* EMIT SIGNAL */
 	}
 
 	return PresetRecord (uri, name);
@@ -304,10 +322,21 @@ Plugin::resolve_midi ()
 	*/
 
 	_pending_stop_events.get_midi(0).clear ();
-	_tracker.resolve_notes (_pending_stop_events.get_midi (0), 0);
+	_tracker.resolve_notes (_pending_stop_events.get_midi (0), /* split cycle offset*/ Port::port_offset());
 	_have_pending_stop_events = true;
 }
 
+void
+Plugin::update_presets (std::string src_unique_id, Plugin* src )
+{
+	if (src == this || unique_id() != src_unique_id) {
+		return;
+	}
+	_have_presets = false;
+	// TODO check if a preset was added/removed and emit the proper signal
+	// so far no subscriber distinguishes between PresetAdded and PresetRemoved
+	PresetAdded();
+}
 
 vector<Plugin::PresetRecord>
 Plugin::get_presets ()
@@ -356,19 +385,21 @@ Plugin::clear_preset ()
 	PresetLoaded (); /* EMIT SIGNAL */
 }
 
-/** @param val `plugin' value */
 void
-Plugin::set_parameter (uint32_t which, float)
+Plugin::set_parameter (uint32_t /* which */, float /* value */)
 {
 	_parameter_changed_since_last_preset = true;
 	_session.set_dirty ();
-	ParameterChanged (which, get_parameter (which)); /* EMIT SIGNAL */
+	PresetDirty (); /* EMIT SIGNAL */
 }
 
 void
-Plugin::set_parameter_automated (uint32_t which, float val)
+Plugin::parameter_changed_externally (uint32_t which, float /* value */)
 {
-	Plugin::set_parameter (which, val);
+	_parameter_changed_since_last_preset = true;
+	_session.set_dirty ();
+	ParameterChangedExternally (which, get_parameter (which)); /* EMIT SIGNAL */
+	PresetDirty (); /* EMIT SIGNAL */
 }
 
 int
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index 98ff9ab..02b802e 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -264,26 +264,53 @@ PluginInsert::create_automatable_parameters ()
 		}
 	}
 }
-
+/** Called when something outside of this host has modified a plugin
+ * parameter. Responsible for propagating the change to two places:
+ *
+ *   1) anything listening to the Control itself
+ *   2) any replicated plugins that make up this PluginInsert.
+ *
+ * The PluginInsert is connected to the ParameterChangedExternally signal for
+ * the first (primary) plugin, and here broadcasts that change to any others.
+ *
+ * XXX We should probably drop this whole replication idea (Paul, October 2015)
+ * since it isn't used by sensible plugin APIs (AU, LV2).
+ */
 void
-PluginInsert::parameter_changed (uint32_t which, float val)
+PluginInsert::parameter_changed_externally (uint32_t which, float val)
 {
 	boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, which));
 
-	if (ac) {
-		ac->set_value (val);
+	/* First propagation: alter the underlying value of the control,
+	 * without telling the plugin(s) that own/use it to set it.
+	 */
 
-                Plugins::iterator i = _plugins.begin();
+	if (!ac) {
+		return;
+	}
 
-                /* don't set the first plugin, just all the slaves */
+	boost::shared_ptr<PluginControl> pc = boost::dynamic_pointer_cast<PluginControl> (ac);
 
-                if (i != _plugins.end()) {
-                        ++i;
-                        for (; i != _plugins.end(); ++i) {
-                                (*i)->set_parameter (which, val);
-                        }
-                }
-        }
+	if (pc) {
+		pc->catch_up_with_external_value (val);
+	}
+
+	/* Second propagation: tell all plugins except the first to
+	   update the value of this parameter. For sane plugin APIs,
+	   there are no other plugins, so this is a no-op in those
+	   cases.
+	*/
+
+	Plugins::iterator i = _plugins.begin();
+
+	/* don't set the first plugin, just all the slaves */
+
+	if (i != _plugins.end()) {
+		++i;
+		for (; i != _plugins.end(); ++i) {
+			(*i)->set_parameter (which, val);
+		}
+	}
 }
 
 int
@@ -378,7 +405,16 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
 				const float val = c->list()->rt_safe_eval (now, valid);
 
 				if (valid) {
-					c->set_value(val);
+					/* This is the ONLY place where we are
+					 *  allowed to call
+					 *  AutomationControl::set_value_unchecked(). We
+					 *  know that the control is in
+					 *  automation playback mode, so no
+					 *  check on writable() is required
+					 *  (which must be done in AutomationControl::set_value()
+					 *
+					 */
+					c->set_value_unchecked(val);
 				}
 
 			}
@@ -507,41 +543,6 @@ PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t /*end_fra
 }
 
 void
-PluginInsert::set_parameter (Evoral::Parameter param, float val)
-{
-	if (param.type() != PluginAutomation) {
-		return;
-	}
-
-	/* the others will be set from the event triggered by this */
-
-	_plugins[0]->set_parameter (param.id(), val);
-
-	boost::shared_ptr<AutomationControl> ac
-			= boost::dynamic_pointer_cast<AutomationControl>(control(param));
-
-	if (ac) {
-		ac->set_value(val);
-	} else {
-		warning << "set_parameter called for nonexistent parameter "
-			<< EventTypeMap::instance().to_symbol(param) << endmsg;
-	}
-
-	_session.set_dirty();
-}
-
-float
-PluginInsert::get_parameter (Evoral::Parameter param)
-{
-	if (param.type() != PluginAutomation) {
-		return 0.0;
-	} else {
-		assert (!_plugins.empty ());
-		return _plugins[0]->get_parameter (param.id());
-	}
-}
-
-void
 PluginInsert::automation_run (BufferSet& bufs, framepos_t start, pframes_t nframes)
 {
 	Evoral::ControlEvent next_event (0, 0.0f);
@@ -659,7 +660,7 @@ PluginInsert::reset_parameters_to_default ()
 			continue;
 		}
 
-		ac->set_value (dflt);
+		ac->set_value (dflt, Controllable::NoGroup);
 	}
 	return all;
 }
@@ -951,6 +952,7 @@ PluginInsert::state (bool full)
 	node.add_child_nocopy (* _configured_in.state (X_("ConfiguredInput")));
 	node.add_child_nocopy (* _configured_out.state (X_("ConfiguredOutput")));
 
+	_plugins[0]->set_insert_id(this->id());
 	node.add_child_nocopy (_plugins[0]->get_state());
 
 	for (Controls::iterator c = controls().begin(); c != controls().end(); ++c) {
@@ -974,8 +976,20 @@ PluginInsert::set_control_ids (const XMLNode& node, int version)
 		if ((*iter)->name() == Controllable::xml_node_name) {
 			const XMLProperty* prop;
 
-			if ((prop = (*iter)->property (X_("parameter"))) != 0) {
-				uint32_t p = atoi (prop->value());
+			uint32_t p = (uint32_t)-1;
+#ifdef LV2_SUPPORT
+			if ((prop = (*iter)->property (X_("symbol"))) != 0) {
+				boost::shared_ptr<LV2Plugin> lv2plugin = boost::dynamic_pointer_cast<LV2Plugin> (_plugins[0]);
+				if (lv2plugin) {
+					p = lv2plugin->port_index(prop->value().c_str());
+				}
+			}
+#endif
+			if (p == (uint32_t)-1 && (prop = (*iter)->property (X_("parameter"))) != 0) {
+				p = atoi (prop->value());
+			}
+
+			if (p != (uint32_t)-1) {
 
 				/* this may create the new controllable */
 
@@ -1113,6 +1127,13 @@ PluginInsert::set_state(const XMLNode& node, int version)
 
 	Processor::set_state (node, version);
 
+	PBD::ID new_id = this->id();
+	PBD::ID old_id = this->id();
+
+	if ((prop = node.property ("id")) != 0) {
+		old_id = prop->value ();
+	}
+
 	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
 
 		/* find the node with the type-specific node name ("lv2", "ladspa", etc)
@@ -1122,7 +1143,27 @@ PluginInsert::set_state(const XMLNode& node, int version)
 		if ((*niter)->name() == plugin->state_node_name()) {
 
 			for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+				/* Plugin state can include external files which are named after the ID.
+				 *
+				 * If regenerate_xml_or_string_ids() is set, the ID will already have
+				 * been changed, so we need to use the old ID from the XML to load the
+				 * state and then update the ID.
+				 *
+				 * When copying a plugin-state, route_ui takes care of of updating the ID,
+				 * but we need to call set_insert_id() to clear the cached plugin-state
+				 * and force a change.
+				 */
+				if (!regenerate_xml_or_string_ids ()) {
+					(*i)->set_insert_id (new_id);
+				} else {
+					(*i)->set_insert_id (old_id);
+				}
+
 				(*i)->set_state (**niter, version);
+
+				if (regenerate_xml_or_string_ids ()) {
+					(*i)->set_insert_id (new_id);
+				}
 			}
 
 			break;
@@ -1167,6 +1208,13 @@ PluginInsert::update_id (PBD::ID id)
 }
 
 void
+PluginInsert::set_state_dir (const std::string& d)
+{
+	// state() only saves the state of the first plugin
+	_plugins[0]->set_state_dir (d);
+}
+
+void
 PluginInsert::set_parameter_state_2X (const XMLNode& node, int version)
 {
 	XMLNodeList nlist = node.children();
@@ -1301,7 +1349,15 @@ PluginInsert::PluginControl::PluginControl (PluginInsert*                     p,
 
 /** @param val `user' value */
 void
-PluginInsert::PluginControl::set_value (double user_val)
+PluginInsert::PluginControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition /* group_override */)
+{
+	if (writable()) {
+		set_value_unchecked (user_val);
+	}
+}
+
+void
+PluginInsert::PluginControl::set_value_unchecked (double user_val)
 {
 	/* FIXME: probably should be taking out some lock here.. */
 
@@ -1314,7 +1370,13 @@ PluginInsert::PluginControl::set_value (double user_val)
 		iasp->set_parameter (_list->parameter().id(), user_val);
 	}
 
-	AutomationControl::set_value (user_val);
+	AutomationControl::set_value (user_val, Controllable::NoGroup);
+}
+
+void
+PluginInsert::PluginControl::catch_up_with_external_value (double user_val)
+{
+	AutomationControl::set_value (user_val, Controllable::NoGroup);
 }
 
 XMLNode&
@@ -1325,6 +1387,12 @@ PluginInsert::PluginControl::get_state ()
 	XMLNode& node (AutomationControl::get_state());
 	ss << parameter().id();
 	node.add_property (X_("parameter"), ss.str());
+#ifdef LV2_SUPPORT
+	boost::shared_ptr<LV2Plugin> lv2plugin = boost::dynamic_pointer_cast<LV2Plugin> (_plugin->_plugins[0]);
+	if (lv2plugin) {
+		node.add_property (X_("symbol"), lv2plugin->port_symbol (parameter().id()));
+	}
+#endif
 
 	return node;
 }
@@ -1333,8 +1401,13 @@ PluginInsert::PluginControl::get_state ()
 double
 PluginInsert::PluginControl::get_value () const
 {
-	/* FIXME: probably should be taking out some lock here.. */
-	return _plugin->get_parameter (_list->parameter());
+	boost::shared_ptr<Plugin> plugin = _plugin->plugin (0);
+
+	if (!plugin) {
+		return 0.0;
+	}
+
+	return plugin->get_parameter (_list->parameter().id());
 }
 
 PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert*                     p,
@@ -1355,7 +1428,15 @@ PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert*
 }
 
 void
-PluginInsert::PluginPropertyControl::set_value (double user_val)
+PluginInsert::PluginPropertyControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition /* group_override*/)
+{
+	if (writable()) {
+		set_value_unchecked (user_val);
+	}
+}
+
+void
+PluginInsert::PluginPropertyControl::set_value_unchecked (double user_val)
 {
 	/* Old numeric set_value(), coerce to appropriate datatype if possible.
 	   This is lossy, but better than nothing until Ardour's automation system
@@ -1371,7 +1452,7 @@ PluginInsert::PluginPropertyControl::set_value (double user_val)
 	}
 
 	_value = value;
-	AutomationControl::set_value(user_val);
+	AutomationControl::set_value (user_val, Controllable::NoGroup);
 }
 
 XMLNode&
@@ -1430,7 +1511,7 @@ PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
                 /* first (and probably only) plugin instance - connect to relevant signals
                  */
 
-		plugin->ParameterChanged.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed, this, _1, _2));
+		plugin->ParameterChangedExternally.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed_externally, this, _1, _2));
                 plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1));
                 plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1));
 	}
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index 55c758c..53d73c4 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -831,13 +831,13 @@ static std::string dll_info (std::string path) {
 	type = *((uint16_t*) &buf[4]);
 	switch (type) {
 		case 0x014c:
-			rv = _("i386 (32bit)");
+			rv = _("i386 (32-bit)");
 			break;
 		case  0x0200:
 			rv = _("Itanium");
 			break;
 		case 0x8664:
-			rv = _("x64 (64bit)");
+			rv = _("x64 (64-bit)");
 			break;
 		case 0:
 			rv = _("Native Architecture");
@@ -1123,6 +1123,7 @@ PluginManager::save_statuses ()
 		ofs << endl;
 	}
 	g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
+	PluginStatusesChanged (); /* EMIT SIGNAL */
 }
 
 void
diff --git a/libs/ardour/po/de.po b/libs/ardour/po/de.po
index 06d8dcf..5056d59 100644
--- a/libs/ardour/po/de.po
+++ b/libs/ardour/po/de.po
@@ -6,8 +6,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-08-13 10:38+0200\n"
-"PO-Revision-Date: 2015-08-13 10:39+0200\n"
+"POT-Creation-Date: 2015-12-23 09:42+0100\n"
+"PO-Revision-Date: 2015-12-23 12:06+0100\n"
 "Last-Translator: Edgar Aichinger <edogawa at aon.at>\n"
 "Language-Team: German <ardour-dev at lists.ardour.org>\n"
 "Language: de\n"
@@ -17,28 +17,180 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Lokalize 1.5\n"
 
-#: amp.cc:62 automatable.cc:165
+#: amp.cc:62 automatable.cc:173
+msgid "Trim"
+msgstr "Anpassen"
+
+#: amp.cc:62 automatable.cc:171
 msgid "Fader"
 msgstr "Fader"
 
-#: amp.cc:445
+#: amp.cc:453
 #, c-format
 msgid "%3.1f dB"
 msgstr "%3.1f dB"
 
-#: amp.cc:486
+#: amp.cc:494
 #, c-format
 msgid "%.2fdB"
 msgstr "%.2fdB"
 
-#: analyser.cc:117 audioregion.cc:1764
+#: analyser.cc:119 audioregion.cc:1762
 msgid "Transient Analysis failed for %1."
 msgstr "Transientenanalyse für %1 fehlgeschlagen."
 
-#: analyser.cc:117
+#: analyser.cc:119
 msgid "Audio File Source"
 msgstr "Audiodateiquelle"
 
+#: audio_backend.cc:31
+msgid "No Error occurred"
+msgstr "Kein Fehler aufgetreten"
+
+#: audio_backend.cc:33
+msgid "Failed to initialize audio backend"
+msgstr "Konnte Audiobackend nicht initialisieren"
+
+#: audio_backend.cc:35
+msgid "Failed to deinitialize audio backend"
+msgstr "Konnte Audiobackend nicht deinitialisieren"
+
+#: audio_backend.cc:37
+msgid "Failed to reinitialize audio backend"
+msgstr "Konnte Audiobackend nicht reinitialisieren"
+
+#: audio_backend.cc:39
+msgid "Failed to open audio device"
+msgstr "Konnte Audiogerät nicht öffnen"
+
+#: audio_backend.cc:41
+msgid "Failed to close audio device"
+msgstr "Konnte Audiogerät nicht schließen"
+
+#: audio_backend.cc:43
+msgid "Audio device not valid"
+msgstr "Audiogerät ungültig"
+
+#: audio_backend.cc:45
+msgid "Audio device unavailable"
+msgstr "Audiogerät nicht verfügbar"
+
+#: audio_backend.cc:47
+msgid "Audio device not connected"
+msgstr "Audiogerät nicht verbunden"
+
+#: audio_backend.cc:49
+msgid "Failed to request and reserve audio device"
+msgstr "Konnte Audiogerät nicht anfordern/reservieren"
+
+#: audio_backend.cc:51
+msgid "Audio device Input/Output error"
+msgstr "Audiogerät E/A-Fehler"
+
+#: audio_backend.cc:53
+msgid "Failed to open MIDI device"
+msgstr "Konnte MIDI-Gerät nicht öffnen"
+
+#: audio_backend.cc:55
+msgid "Failed to close MIDI device"
+msgstr "Konnte MIDI-Gerät nicht schließen"
+
+#: audio_backend.cc:57
+msgid "MIDI device unavailable"
+msgstr "MIDI-Gerät nicht verfügbar"
+
+#: audio_backend.cc:59
+msgid "MIDI device not connected"
+msgstr "MIDI-Gerät nicht verbunden"
+
+#: audio_backend.cc:61
+msgid "MIDI device Input/Output error"
+msgstr "MIDI-Gerät E/A-Fehler"
+
+#: audio_backend.cc:63
+msgid "Sample format is not supported"
+msgstr "Sampleformat nicht unterstützt"
+
+#: audio_backend.cc:65
+msgid "Sample rate is not supported"
+msgstr "Samplerate nicht unterstützt"
+
+#: audio_backend.cc:67
+msgid "Requested input latency is not supported"
+msgstr "Angeforderte Eingangslatenz wird nicht unterstützt"
+
+#: audio_backend.cc:69
+msgid "Requested output latency is not supported"
+msgstr "Angeforderte Ausgangslatenz wird nicht unterstützt"
+
+#: audio_backend.cc:71
+msgid "Period size is not supported"
+msgstr "Periodengröße wird nicht unterstützt"
+
+#: audio_backend.cc:73
+msgid "Period count is not supported"
+msgstr "Periodenanzahl wird nicht unterstützt"
+
+#: audio_backend.cc:75
+msgid "Device configuration not supported"
+msgstr "Gerätekonfiguration wird nicht unterstützt"
+
+#: audio_backend.cc:77
+msgid "Channel count configuration not supported"
+msgstr "Kanalanzahl-Konfiguration wird nicht unterstützt"
+
+#: audio_backend.cc:79
+msgid "Input channel count configuration not supported"
+msgstr "Eingangs-Kanalanzahl-Konfiguration wird nicht unterstützt"
+
+#: audio_backend.cc:81
+msgid "Output channel count configuration not supported"
+msgstr "Ausgangs-Kanalanzahl-Konfiguration wird nicht unterstützt"
+
+#: audio_backend.cc:83
+msgid "Unable to aquire realtime permissions"
+msgstr "Kann keine Echtzeit-Berechtigung erlangen"
+
+#: audio_backend.cc:85
+msgid "Setting audio device thread priorities failed"
+msgstr "Konnte Thread-Prioritäten für das Audiogerät nicht setzen"
+
+#: audio_backend.cc:87
+msgid "Setting MIDI device thread priorities failed"
+msgstr "Konnte Thread-Prioritäten für das MIDI-erät nicht setzen"
+
+#: audio_backend.cc:89
+msgid "Failed to start process thread"
+msgstr "Konnte Prozess-Thread nicht starten"
+
+#: audio_backend.cc:91
+msgid "Failed to start freewheel thread"
+msgstr "Konnte Freewhee-Thread nicht starten"
+
+#: audio_backend.cc:93
+msgid "Failed to register audio/midi ports"
+msgstr "Konnte Audio/MIDI Ports nicht registrieren"
+
+#: audio_backend.cc:95
+msgid "Failed to re-connect audio/midi ports"
+msgstr "Konnte Audio/MIDI Ports nicht wiederverbinden"
+
+#: audio_backend.cc:97
+msgid "Out Of Memory Error"
+msgstr "Fehler: Speichermangel"
+
+#: audio_backend.cc:99
+msgid "Could not reconnect to Audio/MIDI engine"
+msgstr "Konnte nicht zur Audio/MIDI Engine wiederverbinden"
+
+#: audio_backend.cc:107 export_formats.cc:52 session.cc:6233 session.cc:6253
+msgid "None"
+msgstr "Kein"
+
+#: audio_backend.cc:109
+msgid "Default"
+msgstr "Voreinstellung"
+
 #: audio_diskstream.cc:257
 msgid "AudioDiskstream: Playlist \"%1\" isn't an audio playlist"
 msgstr ""
@@ -49,58 +201,58 @@ msgid "AudioDiskstream %1: there is no existing playlist to make a copy of!"
 msgstr ""
 "AudioDiskstream %1: es gibt keine Wiedergabeliste, die kopiert werden kann!"
 
-#: audio_diskstream.cc:879 audio_diskstream.cc:889
+#: audio_diskstream.cc:880 audio_diskstream.cc:890
 msgid ""
 "AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"
 msgstr ""
 "AudioDiskstream %1: Kann während des Befüllens %2 nicht aus Wiedergabeliste "
 "bei Frame %3 lesen"
 
-#: audio_diskstream.cc:1052
+#: audio_diskstream.cc:1053
 msgid "AudioDiskstream %1: cannot read %2 from playlist at frame %3"
 msgstr ""
 "AudioDiskstream %1: Kann %2 nicht aus Wiedergabeliste bei Frame %3 lesen"
 
-#: audio_diskstream.cc:1468 audio_diskstream.cc:1487
+#: audio_diskstream.cc:1469 audio_diskstream.cc:1488
 msgid "AudioDiskstream %1: cannot write to disk"
 msgstr "AudioDiskstream %1: Kann nicht auf Disk schreiben"
 
-#: audio_diskstream.cc:1530
+#: audio_diskstream.cc:1531
 msgid "AudioDiskstream \"%1\": cannot flush captured data to disk!"
 msgstr "AudioDiskstream %1: Kann aufgenommene Daten nicht auf Disk schreiben!"
 
-#: audio_diskstream.cc:1624
+#: audio_diskstream.cc:1627
 msgid "%1: could not create region for complete audio file"
 msgstr "%1: konnte keine Region für die komplette Audiodatei erzeugen"
 
-#: audio_diskstream.cc:1656
+#: audio_diskstream.cc:1659
 msgid "AudioDiskstream: could not create region for captured audio!"
 msgstr ""
 "AudioDiskstream: konnte keine Region für das aufgenommene Audiomaterial "
 "erzeugen!"
 
-#: audio_diskstream.cc:1764
+#: audio_diskstream.cc:1755
 msgid "programmer error: %1"
 msgstr "Programmierfehler: %1"
 
-#: audio_diskstream.cc:2021
+#: audio_diskstream.cc:2012
 msgid "AudioDiskstream: channel %1 out of range"
 msgstr "AudioDiskstream: Kanal %1 Bereichsüberschreitung"
 
-#: audio_diskstream.cc:2035 midi_diskstream.cc:1296
+#: audio_diskstream.cc:2026 midi_diskstream.cc:1295
 msgid "%1:%2 new capture file not initialized correctly"
 msgstr "%1:%2 neue Aufnahmedatei nicht korrekt initialisiert"
 
-#: audio_diskstream.cc:2314
+#: audio_diskstream.cc:2305
 msgid "%1: cannot restore pending capture source file %2"
 msgstr "%1: kann vorläufige Aufnahme-Quelldatei %2 nicht wiederherstellen"
 
-#: audio_diskstream.cc:2336
+#: audio_diskstream.cc:2327
 msgid "%1: incorrect number of pending sources listed - ignoring them all"
 msgstr ""
 "%1: Liste enthält falsche Anzahl vorläufiger Quellen - alle werden ignoriert"
 
-#: audio_diskstream.cc:2370
+#: audio_diskstream.cc:2361
 msgid "%1: cannot create whole-file region from pending capture sources"
 msgstr ""
 "%1: kann aus vorläufigen Aufnahmequellen keine Region für die komplette "
@@ -152,11 +304,11 @@ msgstr "schlecht geformtes XML in importierter Wiedergabeliste"
 msgid "Audio Playlists (unused)"
 msgstr "Audio-Wiedergabelisten (unbenutzt)"
 
-#: audio_playlist_source.cc:171 audiosource.cc:1002
+#: audio_playlist_source.cc:171 audiosource.cc:1046
 #: midi_playlist_source.cc:147 midi_playlist_source.cc:155
-#: midi_playlist_source.cc:162 midi_source.cc:356 plugin_insert.cc:704
-#: rb_effect.cc:327 session.cc:3475 session.cc:3508 session.cc:4905
-#: session_handle.cc:87 sndfilesource.cc:156
+#: midi_playlist_source.cc:162 midi_source.cc:398 plugin_insert.cc:705
+#: rb_effect.cc:327 session.cc:3545 session.cc:3583 session.cc:4893
+#: session_handle.cc:88 sndfilesource.cc:173
 msgid "programming error: %1"
 msgstr "Programmierfehler: %1"
 
@@ -184,27 +336,27 @@ msgstr ""
 "\n"
 "Kanäle: "
 
-#: audio_track.cc:173
+#: audio_track.cc:176
 msgid "Unknown bundle \"%1\" listed for input of %2"
 msgstr "Unbekanntes Bündel \"%1\" für Eingang von %2 genannt"
 
-#: audio_track.cc:175
+#: audio_track.cc:178
 msgid "in 1"
 msgstr "in 1"
 
-#: audio_track.cc:176
+#: audio_track.cc:179
 msgid "No input bundles available as a replacement"
 msgstr "Es gibt keine als Ersatz geeigneten Eingangs-Bündel"
 
-#: audio_track.cc:180
+#: audio_track.cc:183
 msgid "Bundle %1 was not available - \"in 1\" used instead"
 msgstr "Bündel %1 war nicht verfügbar - verwende statt dessen \"in 1\""
 
-#: audio_track.cc:189
+#: audio_track.cc:192
 msgid "improper input channel list in XML node (%1)"
 msgstr "XML-Knoten (%1) enthält ungeeignete Liste der Eingangskanäle"
 
-#: audio_track.cc:212 diskstream.cc:503 source.cc:149
+#: audio_track.cc:215 diskstream.cc:503 source.cc:149
 msgid "%1: this session uses destructive tracks, which are not supported"
 msgstr ""
 "%1: dieses Projekt benutzt destruktive Spuren, was aber nicht unterstützt "
@@ -230,23 +382,19 @@ msgstr "kann VAMP-Plugin \"%1\" nicht laden"
 msgid "VAMP Plugin \"%1\" could not be loaded"
 msgstr "VAMP-Plugin \"%1\" konnte nicht geladen werden"
 
-#: audioengine.cc:731
+#: audioengine.cc:753
 msgid "AudioEngine: cannot load module \"%1\" (%2)"
 msgstr "AudioEngine: kann Modul \"%1\" nicht laden (%2)"
 
-#: audioengine.cc:737
+#: audioengine.cc:759
 msgid "AudioEngine: backend at \"%1\" has no descriptor function."
 msgstr "AudioEngine: Backend an \"%1\" hat keine Beschreibungsfunktion."
 
-#: audioengine.cc:814
+#: audioengine.cc:838
 msgid "Could not create backend for %1: %2"
 msgstr "Konnte Backend für %1 nicht erzeugen: %2"
 
-#: audiofilesource.cc:176
-msgid "Odd audio file path: %1"
-msgstr "Seltsamer Audiodateipfad: %1"
-
-#: audioregion.cc:1720
+#: audioregion.cc:1718
 msgid ""
 "You have requested an operation that requires audio analysis.\n"
 "\n"
@@ -271,80 +419,80 @@ msgstr ""
 "und zukünftigen Operation(en) zur Transienten-Erkennung eine leichte "
 "Verzögerung bemerken.\n"
 
-#: audioregion.cc:1764
+#: audioregion.cc:1762
 msgid "Audio Region"
 msgstr "Audioregion"
 
-#: audiosource.cc:227
+#: audiosource.cc:228
 msgid "cannot rename peakfile for %1 from %2 to %3 (%4)"
 msgstr "kann Peakfile für %1 nicht von %2 auf %3 umbenennen (%4)"
 
-#: audiosource.cc:256
+#: audiosource.cc:262
 msgid "AudioSource: cannot stat peakfile \"%1\""
 msgstr "AudioSource: Peakfile \"%1\" nicht auffindbar"
 
-#: audiosource.cc:362
+#: audiosource.cc:368
 msgid "Cannot open peakfile @ %1 for size check (%2)"
 msgstr "Kann Peakdatei @ %1 nicht zur Größenermittung öffnen (%2)"
 
-#: audiosource.cc:383
+#: audiosource.cc:389
 msgid "peak file %1 is truncated from %2 to %3"
 msgstr "Peakdateei %1 ist von %2 zu %3 "
 
-#: audiosource.cc:386
+#: audiosource.cc:392
 msgid "Cannot open peakfile @ %1 for size check (%2) after rebuild"
 msgstr ""
 "Kann Peakdatei @ %1 nach Neuerstellung nicht zur Größenermittung öffnen (%2)"
 
-#: audiosource.cc:398
+#: audiosource.cc:404
 msgid "Cannot open peakfile @ %1 for reading (%2)"
 msgstr "Kann Peakdatei @ %1 nicht zum Lesen öffnen (%2)"
 
-#: audiosource.cc:432
+#: audiosource.cc:438
 msgid "cannot read sample data for unscaled peak computation"
 msgstr "kann Sampledaten für unskalierte Peaks-Berechnung nicht lesen"
 
-#: audiosource.cc:467 audiosource.cc:562
+#: audiosource.cc:473 audiosource.cc:568
 msgid "map failed - could not create file mapping for peakfile %1."
 msgstr ""
 "map ist gescheitert - konnte Dateimapping für Peakfile %1 nicht erzeugen."
 
-#: audiosource.cc:473 audiosource.cc:568
+#: audiosource.cc:479 audiosource.cc:574
 msgid "map failed - could not map peakfile %1."
 msgstr "map ist gescheitert - konnte Peakfile %1 nicht mappen."
 
-#: audiosource.cc:484 audiosource.cc:579
+#: audiosource.cc:490 audiosource.cc:585
 msgid "unmap failed - could not unmap peakfile %1."
 msgstr "unmap ist gescheitert - konnte Peakfile %1 nicht unmappen."
 
-#: audiosource.cc:490 audiosource.cc:585
+#: audiosource.cc:496 audiosource.cc:591
 msgid "map failed - could not mmap peakfile %1."
 msgstr "map ist gescheitert - konnte Peakfile %1 nicht mmap()pen."
 
-#: audiosource.cc:675
+#: audiosource.cc:681
 msgid ""
 "AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"
 msgstr ""
 "AudioSource[%1]: peak read - kann %2 Samples bei Offset %3 von %4 nicht "
 "lesen(%5)"
 
-#: audiosource.cc:742
+#: audiosource.cc:748
 msgid "%1: could not write read raw data for peak computation (%2)"
 msgstr "%1: konnte Rohdaten für Peakberechnung nicht lesen/schreiben  (%2)"
 
-#: audiosource.cc:779
-msgid "AudioSource: cannot open peakpath (c) \"%1\" (%2)"
-msgstr "AudioSource: kann Pfad für Peaks (c) \"%1\" nicht öffnen (%2)"
+#: audiosource.cc:815
+msgid "AudioSource: cannot open _peakpath (c) \"%1\" (%2)"
+msgstr "AudioSource: kann _peakpath (c) \"%1\" nicht öffnen (%2)"
 
-#: audiosource.cc:850 audiosource.cc:972
+#: audiosource.cc:894 audiosource.cc:1016
 msgid "%1: could not seek in peak file data (%2)"
 msgstr "%1: konnte in den Daten der Peakdatei nicht suchen (%2)"
 
-#: audiosource.cc:855 audiosource.cc:981
+#: audiosource.cc:899 audiosource.cc:1025
 msgid "%1: could not write peak file data (%2)"
 msgstr "%1: konnte Peak-Daten nicht in Datei schreiben (%2)"
 
-#: audiosource.cc:1014
+#: audiosource.cc:1058
 msgid "could not truncate peakfile %1 to %2 (error: %3)"
 msgstr "konnte Peakdatei %1 nicht auf %2 kürzen (Fehler: %3)"
 
@@ -376,50 +524,42 @@ msgstr "Vorhören anderer Regionen als Audio oder MIDI wird nicht unterstützt."
 msgid "Automation node has no path property"
 msgstr "Automationsknoten hat keine Eigenschaft \"Pfad\""
 
-#: automatable.cc:104
+#: automatable.cc:105
 msgid "cannot open %2 to load automation data (%3)"
 msgstr "kann %2 nicht öffnen, um Automationsdaten zu laden (%3)"
 
-#: automatable.cc:132
+#: automatable.cc:137
 msgid "cannot load automation data from %2"
 msgstr "kann Automationsdaten von %2 nicht laden"
 
-#: automatable.cc:167
-msgid "Trim"
-msgstr "Anpassen"
-
-#: automatable.cc:169
+#: automatable.cc:175
 msgid "Mute"
 msgstr "Stumm"
 
-#: automation_control.cc:148
-msgid "write %1 automation"
-msgstr "schreibe %1 Automation"
+#: automation_control.cc:170
+msgid "record %1 automation"
+msgstr "%1 Automation aufnehmen"
 
-#: automation_control.cc:159
-msgid "touch %1 automation"
-msgstr "ändere %1 Automation"
-
-#: automation_list.cc:361
+#: automation_list.cc:396
 msgid "automation list: cannot load coordinates from XML, all points ignored"
 msgstr ""
 "Automationsliste: kann Koordinaten aus XML nicht laden, alle Punkte ignoriert"
 
-#: automation_list.cc:407
+#: automation_list.cc:442
 msgid ""
 "automation list: no x-coordinate stored for control point (point ignored)"
 msgstr ""
 "Automationsliste: Keine X-Koordinate für Kontrollpunkt gespeichert (Punkt "
 "ignoriert)"
 
-#: automation_list.cc:413
+#: automation_list.cc:448
 msgid ""
 "automation list: no y-coordinate stored for control point (point ignored)"
 msgstr ""
 "Automationsliste: Keine Y-Koordinate für Kontrollpunkt gespeichert (Punkt "
 "ignoriert)"
 
-#: automation_list.cc:427
+#: automation_list.cc:462
 msgid ""
 "AutomationList: passed XML node called %1, not \"AutomationList\" - ignored"
 msgstr ""
@@ -430,43 +570,43 @@ msgstr ""
 msgid "Session: could not create butler thread"
 msgstr "Projekt: konnte Butler-Thread nicht erzeugen"
 
-#: butler.cc:253 butler.cc:254
+#: butler.cc:254 butler.cc:255
 msgid "Butler read ahead failure on dstream %1"
 msgstr "Butler-Lesefehler bei dstream %1"
 
-#: butler.cc:301 butler.cc:302
+#: butler.cc:344 butler.cc:345 butler.cc:393 butler.cc:394
 msgid "Butler write-behind failure on dstream %1"
 msgstr "Butler-Schreibfehler bei dstream %1"
 
-#: control_protocol_manager.cc:164
+#: control_protocol_manager.cc:173
 msgid "control protocol name \"%1\" has no descriptor"
 msgstr "Kontrollprotokollname \"%1\" hat keine Beschreibung"
 
-#: control_protocol_manager.cc:171
+#: control_protocol_manager.cc:180
 msgid "control protocol name \"%1\" could not be initialized"
 msgstr "Kontrollprotokoll \"%1\" konnte nicht initialisiert werden"
 
-#: control_protocol_manager.cc:237
+#: control_protocol_manager.cc:246
 msgid "Instantiating mandatory control protocol %1"
 msgstr "Instanziere erforderliches Kontrollprotokoll %1"
 
-#: control_protocol_manager.cc:281
+#: control_protocol_manager.cc:290
 msgid "looking for control protocols in %1\n"
 msgstr "suche nach Kontrollprotokollen in %1\n"
 
-#: control_protocol_manager.cc:306
+#: control_protocol_manager.cc:315
 msgid "Control protocol %1 not usable"
 msgstr "Kontrollprotokoll %1 nicht benutzbar"
 
-#: control_protocol_manager.cc:323
+#: control_protocol_manager.cc:332
 msgid "Control surface protocol discovered: \"%1\"\n"
 msgstr "Protokoll für Kontrolloberfläche entdeckt: \"%1\"\n"
 
-#: control_protocol_manager.cc:341
+#: control_protocol_manager.cc:350
 msgid "ControlProtocolManager: cannot load module \"%1\" (%2)"
 msgstr "ControlProtocolManager: kann Modul \"%1\" nicht laden (%2)"
 
-#: control_protocol_manager.cc:347
+#: control_protocol_manager.cc:356
 msgid "ControlProtocolManager: module \"%1\" has no descriptor function."
 msgstr ""
 "ControlProtocolManager: Modul \"%1\" hat keine Funktion zur Beschreibung."
@@ -487,7 +627,7 @@ msgstr "kann CPU-Takt in /proc/cpuinfo nicht finden"
 msgid "audio"
 msgstr "Audio"
 
-#: data_type.cc:28 session.cc:2271
+#: data_type.cc:28 session.cc:2307
 msgid "MIDI"
 msgstr "MIDI"
 
@@ -503,7 +643,7 @@ msgstr "Hauptausgänge"
 msgid "listen"
 msgstr "hören"
 
-#: diskstream.cc:312
+#: diskstream.cc:311
 msgid "Location \"%1\" not valid for track loop (start >= end)"
 msgstr "Zeitpunkt \"%1\" für Spurschleife ungültig (Start >= Ende)"
 
@@ -602,25 +742,21 @@ msgstr "Dreieck"
 msgid "Rectangular"
 msgstr "Rechteck"
 
-#: export_formats.cc:52 session.cc:6245 session.cc:6265
-msgid "None"
-msgstr "Kein"
-
 #: export_formats.cc:159
-msgid "8bit"
-msgstr "8bit"
+msgid "8-bit"
+msgstr "8-bit"
 
 #: export_formats.cc:161
-msgid "16bit"
-msgstr "16bit"
+msgid "16-bit"
+msgstr "16-bit"
 
 #: export_formats.cc:163
-msgid "24bit"
-msgstr "24bit"
+msgid "24-bit"
+msgstr "24-bit"
 
 #: export_formats.cc:165
-msgid "32bit"
-msgstr "32bit"
+msgid "32-bit"
+msgstr "32-bit"
 
 #: export_formats.cc:167
 msgid "float"
@@ -631,7 +767,7 @@ msgid "double"
 msgstr "double"
 
 #: export_formats.cc:171
-msgid "8bit unsigned"
+msgid "8-bit unsigned"
 msgstr "8bit unsigned"
 
 #: export_formats.cc:173
@@ -653,15 +789,11 @@ msgstr ""
 "das Hochladen nach Soundcloud ist gescheitert. Vielleicht sind E-mail-"
 "Adresse oder Passwort falsch?"
 
-#: export_handler.cc:429
-msgid "Editor: cannot open \"%1\" as export file for CD marker file"
-msgstr "Editor: kann \"%1\" als Export-Datei für CD-Marker nicht öffnen"
-
-#: export_handler.cc:508 export_handler.cc:511
+#: export_handler.cc:503 export_handler.cc:506
 msgid "an error occured while writing a TOC/CUE file: %1"
 msgstr "beim Schreiben einer TOC/CUE Datei trat ein Fehler auf:%1"
 
-#: export_handler.cc:801 export_handler.cc:859
+#: export_handler.cc:796 export_handler.cc:854
 msgid "Cannot convert %1 to Latin-1 text"
 msgstr "Kann %1 nicht zu Latin-1 Kodierung konvertieren"
 
@@ -681,53 +813,53 @@ msgstr "Kann Export-Preset %1 nicht entfernen: %2"
 msgid "Selection"
 msgstr "Auswahl"
 
-#: export_profile_manager.cc:613
+#: export_profile_manager.cc:616
 msgid "Unable to rename export format %1 to %2: %3"
 msgstr "Kann Export-Format %1 nicht nach %2 umbenennen: %3"
 
-#: export_profile_manager.cc:645
+#: export_profile_manager.cc:648
 msgid "Unable to remove export profile %1: %2"
 msgstr "Kann Export-Profil %1 nicht entfernen: %2"
 
-#: export_profile_manager.cc:663
+#: export_profile_manager.cc:666
 msgid "empty format"
 msgstr "leeres Format"
 
-#: export_profile_manager.cc:744
+#: export_profile_manager.cc:747
 msgid "Cannot load export format from %1"
 msgstr "Kann Exportformat aus %1 nicht laden"
 
-#: export_profile_manager.cc:750
+#: export_profile_manager.cc:753
 msgid "Cannot export format read from %1"
 msgstr "Kann Exportformat aus %1 nicht lesen"
 
-#: export_profile_manager.cc:844
+#: export_profile_manager.cc:847
 msgid "No timespan has been selected!"
 msgstr "Keine Zeitspanne ausgewählt!"
 
-#: export_profile_manager.cc:848
+#: export_profile_manager.cc:851
 msgid "No channels have been selected!"
 msgstr "Keine Kanäle ausgewählt!"
 
-#: export_profile_manager.cc:852
+#: export_profile_manager.cc:855
 msgid "Some channels are empty"
 msgstr "Einige Kanäle sind leer"
 
-#: export_profile_manager.cc:885
+#: export_profile_manager.cc:888
 msgid "No format selected!"
 msgstr "Kein Format ausgewählt!"
 
-#: export_profile_manager.cc:887
+#: export_profile_manager.cc:890
 msgid "All channels are empty!"
 msgstr "Alle Kanäle sind leer!"
 
-#: export_profile_manager.cc:889
+#: export_profile_manager.cc:892
 msgid "One or more of the selected formats is not compatible with this system!"
 msgstr ""
 "Eines oder mehrere der gewählten Formate sind mit diesem Sytem nicht "
 "kompatibel!"
 
-#: export_profile_manager.cc:892
+#: export_profile_manager.cc:895
 msgid ""
 "%1 supports only %2 channels, but you have %3 channels in your channel "
 "configuration"
@@ -735,7 +867,7 @@ msgstr ""
 "% unterstützt nur %2 Kanäle, in Ihrer Kanalkonfiguration befinden sich "
 "jedoch %3 Kanäle"
 
-#: file_source.cc:201 session_state.cc:2987
+#: file_source.cc:201 session_state.cc:3144
 msgid ""
 "there are already 1000 files with names like %1; versioning discontinued"
 msgstr ""
@@ -809,11 +941,15 @@ msgstr ""
 msgid "ARDOUR_DLL_PATH not set in environment - exiting\n"
 msgstr "Umgebungsvariable ARDOUR_DLL_PATH ist nicht gesetzt - beende\n"
 
-#: filesystem_paths.cc:260
+#: filesystem_paths.cc:232
+msgid "Cannot determine %1 package directory"
+msgstr "kann %1 Paketverzeichnis nicht bestimmen"
+
+#: filesystem_paths.cc:277
 msgid "ARDOUR_CONFIG_PATH not set in environment\n"
 msgstr "Umgebungsvariable ARDOUR_CONFIG_PATH ist nicht gesetzt\n"
 
-#: filesystem_paths.cc:281
+#: filesystem_paths.cc:298
 msgid "ARDOUR_DATA_PATH not set in environment\n"
 msgstr "Umgebungsvariable ARDOUR_DATA_PATH ist nicht gesetzt\n"
 
@@ -825,47 +961,73 @@ msgstr "Filter: Fehler beim Erzeugen des neuen Dateinamens aus %1"
 msgid "filter: error creating new file %1 (%2)"
 msgstr "Filter: Fehler beim Erzeugen der neuen Datei %1 (%2)"
 
-#: find_session.cc:59
+#: find_session.cc:60
 msgid "cannot check session path %1 (%2)"
 msgstr "Kann Projektpfad %1 nicht überprüfen (%2)"
 
-#: find_session.cc:85
+#: find_session.cc:86
 msgid "cannot check statefile %1 (%2)"
 msgstr "Kann die Projektdatei %1 nicht überprüfen (%2)"
 
-#: find_session.cc:124
+#: find_session.cc:125
 msgid "%1 is not a snapshot file"
 msgstr "%1 ist keine Schnappschussdatei"
 
-#: find_session.cc:141
+#: find_session.cc:142
 msgid "cannot determine current working directory (%1)"
 msgstr "kann momentanes Arbeitsverzeichnis nicht bestimmen (%1)"
 
-#: find_session.cc:158
+#: find_session.cc:159
 msgid "unknown file type for session %1"
 msgstr "Unbekannter Dateityp für Projekt %1"
 
-#: globals.cc:262
+#: globals.cc:265
 msgid "Could not set system open files limit to \"unlimited\""
 msgstr ""
 "Konnte die Systemgrenze für offene Dateien nicht auf \"unbeschränkt\" setzen"
 
-#: globals.cc:264
+#: globals.cc:267
 msgid "Could not set system open files limit to %1"
 msgstr "Konnte die Systemgrenze für offene Dateien nicht auf %1 setzen"
 
-#: globals.cc:268
+#: globals.cc:271 globals.cc:288
 msgid "Your system is configured to limit %1 to only %2 open files"
 msgstr "Ihre Systemkonfiguration beschränkt %1 auf nur %2 offene Dateien"
 
-#: globals.cc:272
+#: globals.cc:275
 msgid "Could not get system open files limit (%1)"
 msgstr "Konnte die Grenze für offene Dateien nicht erhalten (%1)"
 
-#: globals.cc:454
+#: globals.cc:290
+msgid "Could not set system open files limit. Current limit is %1 open files"
+msgstr ""
+"Konnte die Systemgrenze für offene Dateien nicht setzen. Momentane Grenze "
+"ist bei %1 Dateien"
+
+#: globals.cc:472
 msgid "Loading configuration"
 msgstr "Lade Konfiguration"
 
+#: globals.cc:536 session.cc:1031
+msgid "Monitor"
+msgstr "Monitor"
+
+#: globals.cc:537 session_state.cc:633
+msgid "Master"
+msgstr "Master"
+
+#: globals.cc:538
+msgid "Control"
+msgstr "Strg"
+
+#: globals.cc:539
+msgid "Click"
+msgstr "Klick"
+
+#: globals.cc:540
+msgid "Mackie"
+msgstr "Mackie"
+
 #: import.cc:146
 msgid "Cannot find new filename for imported file %1"
 msgstr "Kann keinen neuen Dateinamen für importierte Datei %1 finden"
@@ -928,15 +1090,15 @@ msgstr "Preset %1 (Bank %2)"
 msgid "%1 - cannot find any track/bus with the ID %2 to connect to"
 msgstr "%1 - kann Spur/Bus mit der ID %2 zum Verbinden finden"
 
-#: io.cc:210
+#: io.cc:209
 msgid "IO: cannot disconnect port %1 from %2"
 msgstr "IO: kann Port %1 nicht von %2 trennen"
 
-#: io.cc:345 io.cc:432
+#: io.cc:344 io.cc:431
 msgid "IO: cannot register input port %1"
 msgstr "IO: kann Eingangsport %1 nicht registrieren"
 
-#: io.cc:350 io.cc:437
+#: io.cc:349 io.cc:436
 msgid "IO: cannot register output port %1"
 msgstr "IO: kann Ausgangsport %1 nicht registrieren"
 
@@ -1007,15 +1169,15 @@ msgstr "%s in"
 msgid "%s out"
 msgstr "%s out"
 
-#: io.cc:1540 session.cc:823 session.cc:857
+#: io.cc:1540 session.cc:837 session.cc:871
 msgid "mono"
 msgstr "Mono"
 
-#: io.cc:1542 session.cc:836 session.cc:871
+#: io.cc:1542 session.cc:850 session.cc:885
 msgid "L"
 msgstr "L"
 
-#: io.cc:1542 session.cc:838 session.cc:873
+#: io.cc:1542 session.cc:852 session.cc:887
 msgid "R"
 msgstr "R"
 
@@ -1078,49 +1240,49 @@ msgstr "Fehler beim Sichern der Preset-Datei %1."
 msgid "Could not locate HOME.  Preset not saved."
 msgstr "Konnte HOME nicht eruieren. Preset nicht gesichert."
 
-#: location.cc:458
+#: location.cc:459
 msgid "You cannot put a CD marker at this position"
 msgstr "An dieser Stelle können Sie keinen CD-Marker ablegen"
 
-#: location.cc:610
+#: location.cc:611
 msgid "incorrect XML node passed to Location::set_state"
 msgstr "Unkorrekter XML-Knoten an Location::set_state weitergereicht"
 
-#: location.cc:615
+#: location.cc:616
 msgid "XML node for Location has no ID information"
 msgstr "XML-Knoten für Position hat keine ID-Information"
 
-#: location.cc:619
+#: location.cc:620
 msgid "XML node for Location has no name information"
 msgstr "XML-Knoten für Position hat keine Namensinformation"
 
-#: location.cc:626
+#: location.cc:627
 msgid "XML node for Location has no start information"
 msgstr "XML-Knoten für Position hat keine Start-Information"
 
-#: location.cc:637
+#: location.cc:638
 msgid "XML node for Location has no end information"
 msgstr "XML-Knoten für Position hat keine End-Information"
 
-#: location.cc:644
+#: location.cc:645
 msgid "XML node for Location has no flags information"
 msgstr "XML-Knoten für Position hat keine Flags-Information"
 
-#: location.cc:871
+#: location.cc:872
 msgid "Locations: attempt to use unknown location as selected location"
 msgstr ""
 "Locations: Versuch, eine unbekannte Position als ausgewählte Position zu "
 "verwenden"
 
-#: location.cc:1049
+#: location.cc:1050
 msgid "incorrect XML mode passed to Locations::set_state"
 msgstr "unkorrekter XML-Modus an Locations::set_state weitergereicht"
 
-#: location.cc:1062 session.cc:1520 session.cc:5729 session_state.cc:1128
+#: location.cc:1063 session.cc:1537 session.cc:5717 session_state.cc:1169
 msgid "session"
 msgstr "Projekt"
 
-#: location.cc:1129
+#: location.cc:1130
 msgid "could not load location from session file - ignored"
 msgstr "konnte Position nicht aus Projektdatei laden - ignoriert"
 
@@ -1174,6 +1336,22 @@ msgstr ""
 "Es gibt bereits eine Position mit diesem Namen.\n"
 "Sie können die importierte Position umbenennen:"
 
+#: ltc_file_reader.cc:96
+msgid "LTCFileReader: cannot open file \"%1\""
+msgstr "LTCFileReader: kann Datei \"%1\" nicht öffnen"
+
+#: ltc_file_reader.cc:105
+msgid "LTCFileReader: cannot open file \"%1\" (%3)"
+msgstr "LTCFileReader: kann Datei \"%1\" nicht öffnen (%3)"
+
+#: ltc_file_reader.cc:109
+msgid "LTCFileReader: \"%1\" is an empty audio file"
+msgstr "LTCFileReader: \"%1\" ist eine leere Audiodatei"
+
+#: ltc_file_reader.cc:134
+msgid "LTCFileReader:: invalid audio channel selected"
+msgstr "LTCFileReader: ungültiger Audiokanal gewählt"
+
 #: ltc_slave.cc:275
 msgid "Session framerate adjusted from %1 to LTC's %2."
 msgstr "Projekt-Framerate von %1 auf %2 (von LTC) geändert."
@@ -1187,39 +1365,39 @@ msgstr ""
 msgid "flywheel"
 msgstr "Schwungrad"
 
-#: midi_diskstream.cc:173
+#: midi_diskstream.cc:172
 msgid ""
 "%1: I/O configuration change %4 requested to use %2, but channel setup is %3"
 msgstr ""
 "%1: E/A-Konfigurationsänderung %4 will %2 verwenden, aber Kanalzahl ist %3"
 
-#: midi_diskstream.cc:225
+#: midi_diskstream.cc:224
 msgid "MidiDiskstream: Playlist \"%1\" isn't a midi playlist"
 msgstr "MidiDiskstream: Wiedergabeliste \"%1\" ist keine MIDI-Wiedergabeliste"
 
-#: midi_diskstream.cc:276
+#: midi_diskstream.cc:275
 msgid "MidiDiskstream %1: there is no existing playlist to make a copy of!"
 msgstr "MidiDiskstream %1: es gibt keine Wiedergabeliste zum Kopieren!"
 
-#: midi_diskstream.cc:754
+#: midi_diskstream.cc:753
 msgid "MidiDiskstream %1: cannot read %2 from playlist at frame %3"
 msgstr ""
 "MidiDiskstream %1: kann %2 nicht von Wiedergabeliste bei Frame %3 lesen"
 
-#: midi_diskstream.cc:891
+#: midi_diskstream.cc:890
 msgid "MidiDiskstream %1: cannot write to disk"
 msgstr "MidiDiskstream %1: kann nicht auf Disk schreiben"
 
-#: midi_diskstream.cc:925
+#: midi_diskstream.cc:924
 msgid "MidiDiskstream \"%1\": cannot flush captured data to disk!"
 msgstr ""
 "MidiDiskstream \"%1\": kann aufgenommene Daten nicht auf Disk schreiben!"
 
-#: midi_diskstream.cc:1014
+#: midi_diskstream.cc:1013
 msgid "%1: could not create region for complete midi file"
 msgstr "%1: konnte Region für die komplette MIDI-Datei nicht erzeugen"
 
-#: midi_diskstream.cc:1055
+#: midi_diskstream.cc:1054
 msgid "MidiDiskstream: could not create region for captured midi!"
 msgstr "MidiDiskstream: konnte Region für aufgenommenes MIDI nicht erzeugen"
 
@@ -1242,15 +1420,31 @@ msgstr ""
 "Keine SysExID für die Änderung der Eigenschaft \"sys-ex\" gefunden - "
 "ignoriert"
 
-#: midi_model.cc:1999
-msgid "transpose"
-msgstr "transponieren"
+#: midi_patch_manager.cc:78
+msgid "Loading %1 MIDI patch from %2"
+msgid_plural "Loading %1 MIDI patches from %2"
+msgstr[0] "Lade %1 MIDI Patch von %2"
+msgstr[1] "Lade %1 MIDI Patches von %2"
+
+#: midi_patch_manager.cc:109
+msgid "Unloading %1 MIDI patch from %2"
+msgid_plural "Unloading %1 MIDI patches from %2"
+msgstr[0] "Entlade %1 MIDI Patch von %2"
+msgstr[1] "Entlade %1 MIDI Patches von %2"
+
+#: midi_patch_manager.cc:126
+msgid "Error parsing MIDI patch file %1"
+msgstr "Fehler beim Parsen der MIDI-Patch-Datei %1"
 
-#: midi_patch_manager.cc:133
+#: midi_patch_manager.cc:135
 msgid "Duplicate MIDI device `%1' in `%2' ignored"
 msgstr "Doppeltes MIDI-Gerät '%1' in '%2' ignoriert"
 
-#: midi_scene_changer.cc:309
+#: midi_patch_manager.cc:170
+msgid "Removing MIDI patch file %1"
+msgstr "Entferne MIDI-Patch-Datei %1"
+
+#: midi_scene_changer.cc:312
 msgid "Scene "
 msgstr "Szene"
 
@@ -1406,7 +1600,7 @@ msgstr "PannerManager: Modul \"%1\" hat keine Beschreibungsfunktion"
 msgid "no panner discovered for in/out = %1/%2"
 msgstr "keinen Panner für %1/%2 Ein/Ausgänge gefunden"
 
-#: panner_shell.cc:122
+#: panner_shell.cc:121
 msgid ""
 "No panner found: check that panners are being discovered correctly during "
 "startup."
@@ -1414,23 +1608,23 @@ msgstr ""
 "Keinen Panner gefunden: Vergewissern Sie sich, dass die Panner während des "
 "Programmstarts korrekt erkannt werden."
 
-#: panner_shell.cc:126
+#: panner_shell.cc:125
 msgid "select panner: %1\n"
 msgstr "wähle Panner: %1\n"
 
-#: panner_shell.cc:255
+#: panner_shell.cc:254
 msgid "Unknown panner plugin \"%1\" found in pan state - ignored"
 msgstr "Unbekanntes Panner-Plugin \"%1\" in Pan-Status gefunden - ignoriert"
 
-#: panner_shell.cc:261
+#: panner_shell.cc:260
 msgid "panner plugin node has no type information!"
 msgstr "Panner Plugin-Knoten hat keine Typinformation!"
 
-#: playlist.cc:2140
+#: playlist.cc:2179
 msgid "region state node has no ID, ignored"
 msgstr "Status-Knoten der Region hat keine ID, ignoriert"
 
-#: playlist.cc:2158
+#: playlist.cc:2197
 msgid "Playlist: cannot create region from XML"
 msgstr "Wiedergabeliste: kann Region aus XML nicht erzeugen"
 
@@ -1444,7 +1638,7 @@ msgstr ""
 "Konnte die Wiedergabeliste nicht aus den Quelldaten des Projekts "
 "konstruieren!"
 
-#: plugin.cc:328
+#: plugin.cc:329
 msgid ""
 "Plugin presets are not supported in this build of %1. Consider paying for a "
 "full version"
@@ -1452,7 +1646,7 @@ msgstr ""
 "Pluginpresets werden in diesem %1-Binärpaket nicht unterstützt. Erwägen Sie, "
 "für die Vollversion zu bezahlen"
 
-#: plugin.cc:403
+#: plugin.cc:412
 msgid ""
 "Saving plugin settings is not supported in this build of %1. Consider paying "
 "for the full version"
@@ -1460,23 +1654,23 @@ msgstr ""
 "Das Speichern von Pluginpresets werden in diesem %1-Binärpaket nicht "
 "unterstützt. Erwägen Sie, für die Vollversion zu bezahlen"
 
-#: plugin_insert.cc:596
+#: plugin_insert.cc:597
 msgid "programming error: "
 msgstr "Programmierfehler:"
 
-#: plugin_insert.cc:1002
+#: plugin_insert.cc:1010
 msgid "XML node describing plugin is missing the `type' field"
 msgstr "Dem XML-Knoten zur Beschreibung des Plugins fehlt das \"type\"-Feld"
 
-#: plugin_insert.cc:1017
+#: plugin_insert.cc:1025
 msgid "unknown plugin type %1 in plugin insert state"
 msgstr "Unbekannter Plugintyp %1 im Einfüge-Status des Plugins"
 
-#: plugin_insert.cc:1045
+#: plugin_insert.cc:1053
 msgid "Plugin has no unique ID field"
 msgstr "Das Plugin hat kein Feld für die eindeutige ID"
 
-#: plugin_insert.cc:1070
+#: plugin_insert.cc:1078
 msgid ""
 "Found a reference to a plugin (\"%1\") that is unknown.\n"
 "Perhaps it was removed or moved since it was last used."
@@ -1484,105 +1678,153 @@ msgstr ""
 "Referenz auf ein unbekanntes Plugin (\"%1\") gefunden.\n"
 "Vielleicht wurde es seit der letzten Verwendung entfernt oder verschoben."
 
-#: plugin_insert.cc:1193
+#: plugin_insert.cc:1235
 msgid "PluginInsert: Auto: no ladspa port number"
 msgstr "PluginInsert: Auto: keine LADSPA Portnummer"
 
-#: plugin_insert.cc:1200
+#: plugin_insert.cc:1242
 msgid "PluginInsert: Auto: port id out of range"
 msgstr "PluginInsert: Auto: Port-ID Bereichsüberschreitung"
 
-#: plugin_insert.cc:1236
+#: plugin_insert.cc:1278
 msgid "PluginInsert: automatable control %1 not found - ignored"
 msgstr ""
 "PluginInsert: automatisierbares Kontrollelement %1 nicht gefunden - ignoriert"
 
-#: plugin_manager.cc:209
+#: plugin_manager.cc:217
 msgid "Discovering Plugins"
 msgstr "Finde Plugins"
 
-#: plugin_manager.cc:237
+#: plugin_manager.cc:245
 msgid "Scanning LADSPA Plugins"
 msgstr "Scanne LADSPA Plugins"
 
-#: plugin_manager.cc:240
+#: plugin_manager.cc:248
 msgid "Scanning LV2 Plugins"
 msgstr "Scanne LV2 Plugins"
 
-#: plugin_manager.cc:246
+#: plugin_manager.cc:254
 msgid "Scanning Windows VST Plugins"
 msgstr "Scanne Windows VST Plugins"
 
-#: plugin_manager.cc:248
+#: plugin_manager.cc:256
 msgid "Discovering Windows VST Plugins"
 msgstr "Halte Ausschau nach Windows VST Plugins"
 
-#: plugin_manager.cc:257
+#: plugin_manager.cc:265
 msgid "Scanning Linux VST Plugins"
 msgstr "Scanne Linux VST Plugins"
 
-#: plugin_manager.cc:259
+#: plugin_manager.cc:267
 msgid "Discovering Linux VST Plugins"
 msgstr "Halte Ausschau nach Linux VST Plugins"
 
-#: plugin_manager.cc:272
+#: plugin_manager.cc:280
+msgid "VST Blacklist: "
+msgstr "VST Schwarzliste: "
+
+#: plugin_manager.cc:282
 msgid "VST Blacklist:"
 msgstr "VST Schwarzliste:"
 
-#: plugin_manager.cc:279
+#: plugin_manager.cc:292
 msgid "Scanning AU Plugins"
 msgstr "Scanne AU Plugins"
 
-#: plugin_manager.cc:281
+#: plugin_manager.cc:294
 msgid "Discovering AU Plugins"
 msgstr "Halte Ausschau nach AU Plugins"
 
-#: plugin_manager.cc:286
+#: plugin_manager.cc:299
 msgid "Plugin Scan Complete..."
 msgstr "Plugin-Scan abgeschlossen"
 
-#: plugin_manager.cc:470
+#: plugin_manager.cc:483
 msgid "LADSPA"
 msgstr "LADSPA"
 
-#: plugin_manager.cc:522
+#: plugin_manager.cc:535
 msgid "Could not parse rdf file: %1"
 msgstr "Konnte RDF-Datei: %1 nicht parsen"
 
-#: plugin_manager.cc:559
+#: plugin_manager.cc:572
 msgid "LADSPA: cannot load module \"%1\" (%2)"
 msgstr "LADSPA: kann Modul \"%1\" nicht laden (%2)"
 
-#: plugin_manager.cc:566
+#: plugin_manager.cc:579
 msgid "LADSPA: module \"%1\" has no descriptor function."
 msgstr "LADSPA: Modul \"%1\" hat keine Beschreibungsfunktion."
 
-#: plugin_manager.cc:765
+#: plugin_manager.cc:778
 msgid "--- Windows VST plugins Scan: %1"
 msgstr "--- Windows VST plugins Scan: %1"
 
-#: plugin_manager.cc:771
+#: plugin_manager.cc:784
 msgid "VST"
 msgstr "VST"
 
-#: plugin_manager.cc:776
+#: plugin_manager.cc:789
 msgid "--- Windows VST plugins Scan Done"
 msgstr "--- Windows VST plugins Scan Fertig"
 
-#: plugin_manager.cc:788
-msgid " *  %1 %2"
-msgstr " *  %1 %2"
+#: plugin_manager.cc:804
+msgid "cannot open dll"
+msgstr "kann dll  nicht öffnen"
 
-#: plugin_manager.cc:788
-msgid " (cache only)"
-msgstr " (nur Cache)"
+#: plugin_manager.cc:808
+msgid "invalid dll, file too small"
+msgstr "Ungültige dll, Datei zu klein"
 
-#: plugin_manager.cc:801
+#: plugin_manager.cc:812
+msgid "not a dll"
+msgstr "keine dll"
+
+#: plugin_manager.cc:818
+msgid "cannot determine dll type"
+msgstr "kann dll-Typ nicht ermitteln"
+
+#: plugin_manager.cc:822
+msgid "cannot read dll PE header"
+msgstr "kann den dll-PE-Header nicht lesen"
+
+#: plugin_manager.cc:827
+msgid "invalid dll PE header"
+msgstr "ungültiger dll-PE-Header"
+
+#: plugin_manager.cc:834
+msgid "i386 (32-bit)"
+msgstr "i386 (32-bit)"
+
+#: plugin_manager.cc:837
+msgid "Itanium"
+msgstr "Itanium"
+
+#: plugin_manager.cc:840
+msgid "x64 (64-bit)"
+msgstr "x64 (64-bit)"
+
+#: plugin_manager.cc:843
+msgid "Native Architecture"
+msgstr "Native Architektur"
+
+#: plugin_manager.cc:846
+msgid "Unknown Architecture"
+msgstr "Unbekannte Architektur"
+
+#: plugin_manager.cc:862
+msgid " *  %1 (cache only)"
+msgstr " *  %1 (nur Cache)"
+
+#: plugin_manager.cc:864
+msgid " *  %1 - %2"
+msgstr " *  %1 - %2"
+
+#: plugin_manager.cc:878
 msgid " -> Cannot get Windows VST information, plugin ignored."
 msgstr ""
 "Kann Windows VST Informationen nicht erhalten, Plugin \"%1\" wird ignoriert."
 
-#: plugin_manager.cc:812
+#: plugin_manager.cc:889
 msgid ""
 "VST plugin %1 does not support processReplacing, and cannot be used in %2 at "
 "this time"
@@ -1590,19 +1832,19 @@ msgstr ""
 "VST-Plugin %1 unterstützt kein processReplacing und kann zur Zeit nicht mit "
 "%2 benützt werden"
 
-#: plugin_manager.cc:847
+#: plugin_manager.cc:924
 msgid "Ignoring duplicate Windows VST plugin \"%1\""
 msgstr "Ignoriere Duplikat des Windows VST Plugins \"%1\""
 
-#: plugin_manager.cc:859
+#: plugin_manager.cc:936
 msgid " -> OK (VST Plugin \"%1\" was added)."
 msgstr " -> OK (VST Plugin \"%1\" hinzugefügt)."
 
-#: plugin_manager.cc:907
+#: plugin_manager.cc:984
 msgid "LXVST"
 msgstr "LXVST"
 
-#: plugin_manager.cc:934
+#: plugin_manager.cc:1011
 msgid ""
 "linuxVST plugin %1 does not support processReplacing, and so cannot be used "
 "in %2 at this time"
@@ -1610,15 +1852,15 @@ msgstr ""
 "linuxVST-Plugin %1 unterstützt kein processReplacing und kann daher zur Zeit "
 "nicht mit %2 benützt werden"
 
-#: plugin_manager.cc:1103
+#: plugin_manager.cc:1175
 msgid "unknown plugin status type \"%1\" - all entries ignored"
 msgstr "unbekannter Plugin-Statustyp \"%1\" - alle Einträge ignoriert"
 
-#: plugin_manager.cc:1120
+#: plugin_manager.cc:1192
 msgid "unknown plugin type \"%1\" - ignored"
 msgstr "unbekannter Plugintyp \"%1\" - ignoriert"
 
-#: port.cc:455
+#: port.cc:462
 msgid "could not reregister %1"
 msgstr "konnte %1 nicht erneut registrieren"
 
@@ -1635,7 +1877,7 @@ msgstr ""
 msgid "non-port insert XML used for port plugin insert"
 msgstr "Nicht-Port-Insert XML zum Einfügen eines Port-Plugin benutzt"
 
-#: port_manager.cc:290
+#: port_manager.cc:285
 msgid ""
 "a port with the name \"%1\" already exists: check for duplicated track/bus "
 "names"
@@ -1643,7 +1885,7 @@ msgstr ""
 "Ein Port mit Namen \"%1\" existiert bereits: Prüfen Sie auf doppelte Spur/"
 "Busnamen"
 
-#: port_manager.cc:292
+#: port_manager.cc:287
 msgid ""
 "No more ports are available. You will need to stop %1 and restart with more "
 "ports if you need this many tracks."
@@ -1651,19 +1893,19 @@ msgstr ""
 "Keine Ports mehr verfügbar. Wenn Sie so viele Spuren brauchen, müssen Sie %1 "
 "stoppen und mit mehr Ports neu starten."
 
-#: port_manager.cc:295
+#: port_manager.cc:290
 msgid "AudioEngine: cannot register port \"%1\": %2"
 msgstr "AudioEngine: kann Port \"%1\": %2 nicht registrieren"
 
-#: port_manager.cc:334
+#: port_manager.cc:329
 msgid "unable to create port: %1"
 msgstr "kann Port: %1 nicht erzeugen"
 
-#: port_manager.cc:421
+#: port_manager.cc:416
 msgid "AudioEngine: cannot connect %1 (%2) to %3 (%4)"
 msgstr "AudioEngine: kann %1 (%2) nicht mit %3 (%4) verbinden"
 
-#: port_manager.cc:473 port_manager.cc:474
+#: port_manager.cc:468 port_manager.cc:469
 msgid "Re-establising port %1 failed"
 msgstr "Portwiederherstellung fehlgeschlagen"
 
@@ -1719,10 +1961,22 @@ msgstr "Konfigurationsdatei %1 nicht gesichert"
 msgid "cannot open recent session file %1 (%2)"
 msgstr "Kann kürzlich geöffnete Datei %1 nicht öffnen (%2)"
 
-#: recent_sessions.cc:97
-msgid "cannot open recent template file %1 (%2)"
+#: recent_sessions.cc:68 recent_sessions.cc:126
+msgid "Error reading recent session file %1 (%2)"
+msgstr "Kann kürzlich geöffnete Projektdatei %1 nicht lesen (%2)"
+
+#: recent_sessions.cc:113
+msgid "Cannot open recent template file %1 (%2)"
 msgstr "Kann  kürzlich verwendete Vorlagendatei %1 (%2) nicht öffnen"
 
+#: recent_sessions.cc:176
+msgid "Error writing recent sessions file %1 (%2)"
+msgstr "Kann kürzlich geöffnete Projektdatei %1 nicht schreiben (%2)"
+
+#: recent_sessions.cc:211
+msgid "Error writing saved template file %1 (%2)"
+msgstr "Kann gesicherte Vorlagendatei %1 nicht schreiben (%2)"
+
 #: region_factory.cc:78 region_factory.cc:120 region_factory.cc:161
 #: region_factory.cc:203
 msgid ""
@@ -1755,38 +2009,97 @@ msgstr "Import: Fehler in src_new() : %1"
 msgid "return %1"
 msgstr "Rückgabewert: %1"
 
-#: route.cc:1311 route.cc:2888
+#: route.cc:841
+msgid "Cleared Explicit solo: %1\n"
+msgstr "Explizites Solo gelöscht: %1\n"
+
+#: route.cc:844
+msgid "Cleared Implicit solo: %1 up:%2 down:%3\n"
+msgstr "Implizites Solo gelöscht: %1 auf:%2 ab:%3\n"
+
+#: route.cc:1371 route.cc:2983
 msgid "unknown Processor type \"%1\"; ignored"
 msgstr "unbekannter Prozessortyp \"%1\"; ignoriert"
 
-#: route.cc:1333
+#: route.cc:1393
 msgid "processor could not be created. Ignored."
 msgstr "Prozessor konnte nicht erzeugt werden. Ignoriert."
 
-#: route.cc:2314 route.cc:2539
+#: route.cc:2406 route.cc:2631
 msgid "Bad node sent to Route::set_state() [%1]"
 msgstr "Schlechter Knoten an Route::set_state() gesendet [%1]"
 
-#: route.cc:2374
+#: route.cc:2466
 msgid "Pannable state found for route (%1) without a panner!"
 msgstr "Pannerziel-Status für Route (%1) ohne Panner gefunden!"
 
-#: route.cc:2448 route.cc:2452 route.cc:2653 route.cc:2657
+#: route.cc:2540 route.cc:2544 route.cc:2745 route.cc:2749
 msgid "badly formed order key string in state file! [%1] ... ignored."
 msgstr ""
 "schlecht geformte Zeichenkette für den Schlüssel der Sortierreihenfolge in "
 "der Projektdatei! [%1] ... ignoriert"
 
-#: route.cc:2663
+#: route.cc:2755
 msgid "Converting deprecated order key for %1 using Editor order %2"
 msgstr ""
 "Konvertiere veralteten Sortierschlüssel für %1 unter Nutzung der "
 "Editorreihenfolge %2"
 
+#: route.cc:3389
+msgid "Invalid Solo-Isolate propagation: from:%1 new:%2 - old:%3 = delta:%4"
+msgstr "Ungültige Solo-Isolate Propagierung: von:%1 neu:%2 - alt:%3 = delta:%4"
+
+#: route.cc:5308
+msgid "lo"
+msgstr "lo"
+
+#: route.cc:5310
+msgid "mid"
+msgstr "mid"
+
+#: route.cc:5312
+msgid "hi"
+msgstr "hi"
+
+#: route.cc:5419
+msgid "Leveler"
+msgstr "Leveller"
+
+#: route.cc:5421
+msgid "Compressor"
+msgstr "Kompressor"
+
+#: route.cc:5423
+msgid "Limiter"
+msgstr "Limiter"
+
+#: route.cc:5426 route.cc:5428 route.cc:5444 route.cc:5446
+msgid "???"
+msgstr "???"
+
+#: route.cc:5438
+msgid "Attk"
+msgstr "Attk"
+
+#: route.cc:5440
+msgid "Ratio"
+msgstr "Ratio"
+
+#: route.cc:5442
+msgid "Rels"
+msgstr "Rels"
+
 #: route_group.cc:459
 msgid "You cannot subgroup MIDI tracks at this time"
 msgstr "MIDI-Spuren können zur Zeit nicht zu Subgruppen zusammengefasst werden"
 
+#: route_group.cc:466
+msgid ""
+"You cannot subgroup tracks with different number of outputs at this time."
+msgstr ""
+"Spuren mit verschiedener Anzahl an Ausgängen können zur Zeit nicht zu "
+"Subgruppen zusammengefasst werden."
+
 #: rb_effect.cc:229 rb_effect.cc:269
 msgid "tempoize: error reading data from %1 at %2 (wanted %3, got %4)"
 msgstr ""
@@ -1809,97 +2122,119 @@ msgstr "Send %1"
 msgid "programming error: send created using role %1"
 msgstr "Programmierfehler: Send erzeugt mittels Rolle %1"
 
-#: session.cc:391
+#: session.cc:317 session.cc:366
+msgid "Cannot connect to audio/midi engine"
+msgstr "Kann nicht zur Audio/MIDI Engine verbinden"
+
+#: session.cc:322
+msgid "Session initialization failed"
+msgstr "Projektinitialisierung gescheitert"
+
+#: session.cc:338
+msgid "Failed to load template/snapshot state"
+msgstr "Konnte Vorlagen/Schnappschussstatus nicht laden"
+
+#: session.cc:349
+msgid "Failed to load state"
+msgstr "Konnte Status nicht laden"
+
+#: session.cc:372
+msgid "Cannot configure audio/midi engine with session parameters"
+msgstr "Kann Audio/MIDI Engine nicht mit Projektparametern konfigurieren"
+
+#: session.cc:395
 msgid "Connect to engine"
 msgstr "Verbinde zur Engine"
 
-#: session.cc:442
+#: session.cc:446
 msgid "Session loading complete"
 msgstr "Laden des Projektes abgeschlossen"
 
-#: session.cc:513
+#: session.cc:517
 msgid "Set up LTC"
 msgstr "LTC einrichten"
 
-#: session.cc:515
+#: session.cc:519
 msgid "Set up Click"
 msgstr "Klick einrichten"
 
-#: session.cc:517
+#: session.cc:521
 msgid "Set up standard connections"
 msgstr "Richte Standard-Verbindungen ein"
 
-#: session.cc:754
+#: session.cc:768
 msgid "could not setup Click I/O"
 msgstr "konnte Metronom-E/A nicht einrichten"
 
-#: session.cc:817
+#: session.cc:831
 #, c-format
 msgid "out %s"
 msgstr "aus %s"
 
-#: session.cc:819
+#: session.cc:833
 #, c-format
 msgid "out %<PRIu32>"
 msgstr "out %<PRIu32>"
 
-#: session.cc:834
+#: session.cc:848
 #, c-format
 msgid "out %<PRIu32>+%<PRIu32>"
 msgstr "out %<PRIu32>+%<PRIu32>"
 
-#: session.cc:851
+#: session.cc:865
 #, c-format
 msgid "in %s"
 msgstr "in %s"
 
-#: session.cc:853
+#: session.cc:867
 #, c-format
 msgid "in %<PRIu32>"
 msgstr "in %<PRIu32>"
 
-#: session.cc:868
+#: session.cc:882
 #, c-format
 msgid "in %<PRIu32>+%<PRIu32>"
 msgstr "in %<PRIu32>+%<PRIu32>"
 
-#: session.cc:948
+#: session.cc:962
 msgid "cannot connect master output %1 to %2"
 msgstr "kann Master-Ausgang %1 nicht mit %2 verbinden"
 
-#: session.cc:1017
-msgid "Monitor"
-msgstr "Monitor"
+#: session.cc:1045
+msgid "Cannot create monitor section. 'Monitor' Port name is not unique."
+msgstr ""
+"Kann keine Monitorsektion erzeugen. Der Portname 'Monitor' ist schon "
+"vergeben."
 
-#: session.cc:1062 session.cc:1188
+#: session.cc:1079 session.cc:1205
 msgid "cannot connect control input %1 to %2"
 msgstr "kann Kontrolleingang %1 nicht mit %2 verbinden"
 
-#: session.cc:1082 session.cc:1207
+#: session.cc:1099 session.cc:1224
 msgid "The preferred I/O for the monitor bus (%1) cannot be found"
 msgstr "Bevorzugte E/A für den Monitorbus (%1) kann nicht gefunden werden"
 
-#: session.cc:1113 session.cc:1238
+#: session.cc:1130 session.cc:1255
 msgid "cannot connect control output %1 to %2"
 msgstr "kann Kontrollausgang %1 nicht mit %2 verbinden"
 
-#: session.cc:1296
+#: session.cc:1313
 msgid "cannot create Auditioner: no auditioning of regions possible"
 msgstr ""
 "Kann das Vorhör-System nicht einrichten: kein Vorhören von Regionen möglich"
 
-#: session.cc:1497
+#: session.cc:1514
 msgid "Session: you can't use that location for auto punch (start <= end)"
 msgstr ""
 "Session: Sie können diese Position nicht für Auto-Punch verwenden (Start <= "
 "Ende) "
 
-#: session.cc:1524
+#: session.cc:1541
 msgid "Session: you can't use that location for session start/end)"
 msgstr ""
 "Projekt: Sie können diesen Zeitpunkt nicht als Projektanfang/ende benutzen"
 
-#: session.cc:1556
+#: session.cc:1573
 msgid ""
 "You cannot use this location for auto-loop because it has zero or negative "
 "length"
@@ -1907,31 +2242,31 @@ msgstr ""
 "Sie können diese Position nicht für \"automatische Schleife\" verwenden, da "
 "sie keine oder eine negative Länge hat"
 
-#: session.cc:1739
+#: session.cc:1756
 msgid "programming error: session range removed!"
 msgstr "Programmierfehler: Projektbereich entfernt!"
 
-#: session.cc:2004
+#: session.cc:2016
 msgid "feedback loop setup between %1 and %2"
 msgstr "Feedbackschleife zwischen %1 und %2 erkannt"
 
-#: session.cc:2240
+#: session.cc:2276
 msgid "Track "
 msgstr "Spur "
 
-#: session.cc:2242
+#: session.cc:2278
 msgid "Audio "
 msgstr "Audio "
 
-#: session.cc:2247
+#: session.cc:2283
 msgid "MIDI "
 msgstr "MIDI"
 
-#: session.cc:2322
+#: session.cc:2358
 msgid "Session: could not create new midi track."
 msgstr "Session: konnte keine neue MIDI-Spur erzeugen."
 
-#: session.cc:2328
+#: session.cc:2364
 msgid ""
 "No more JACK ports are available. You will need to stop %1 and restart JACK "
 "with more ports if you need this many tracks."
@@ -1939,81 +2274,81 @@ msgstr ""
 "Keine JACK-Ports mehr verfügbar. Wenn Sie so viele Spuren benötigen, müssen "
 "Sie %1 stoppen und JACK mit mehr Ports neu starten."
 
-#: session.cc:2848 session.cc:2856 session.cc:2940 session.cc:2948
+#: session.cc:2884 session.cc:2892 session.cc:2976 session.cc:2984
 msgid "cannot configure %1 in/%2 out configuration for new audio track"
 msgstr "kann %1 ein/%2 aus für neue Audiospur nicht konfigurieren"
 
-#: session.cc:2881
+#: session.cc:2917
 msgid "Session: could not create new audio track."
 msgstr "Session: konnte keine neue Audiospur erzeugen"
 
-#: session.cc:2918 session.cc:2921
+#: session.cc:2954 session.cc:2957
 msgid "Bus"
 msgstr "Bus"
 
-#: session.cc:2973
+#: session.cc:3009
 msgid "Session: could not create new audio route."
 msgstr "Session: konnte keine neueAudio-Route  erzeugen"
 
-#: session.cc:3037 session.cc:3047
+#: session.cc:3082 session.cc:3092
 msgid "Session: UINT_MAX routes? impossible!"
 msgstr "Session: UINT_MAX Routen? unmöglich!"
 
-#: session.cc:3069
+#: session.cc:3125
 msgid "Session: cannot create track/bus from template description"
 msgstr "Session: Kann die Route aus der Vorlagenbeschreibung nicht erzeugen"
 
-#: session.cc:3097
+#: session.cc:3168
 msgid "Session: could not create new route from template"
 msgstr "Session: konnte keine neue Route aus der Vorlage erzeugen."
 
-#: session.cc:3131
+#: session.cc:3202
 msgid "Adding new tracks/busses failed"
 msgstr "Fehler beim Hinzufügen neuer Spuren/Busse"
 
-#: session.cc:4452
+#: session.cc:4440
 msgid "Merging embedded file %1: name collision AND md5 hash collision!"
 msgstr ""
 "Zusammenführen der eingebetteten Datei %1: Namenskollision UND md5 hash "
 "Kollision!"
 
-#: session.cc:4582 session.cc:4655
+#: session.cc:4570 session.cc:4643
 msgid "There are already %1 recordings for %2, which I consider too many."
 msgstr "Es gibt bereits %1 Aufnahmen für %2, was ich als zu viele erachte."
 
-#: session.cc:5097
+#: session.cc:5085
 msgid "send ID %1 appears to be in use already"
 msgstr "Send ID %1 ist offenbar schon in Gebrauch"
 
-#: session.cc:5109
+#: session.cc:5097
 msgid "aux send ID %1 appears to be in use already"
 msgstr "Aux-Send ID %1 ist offenbar schon in Gebrauch"
 
-#: session.cc:5121
+#: session.cc:5109
 msgid "return ID %1 appears to be in use already"
 msgstr "Return ID %1 ist offenbar schon in Gebrauch"
 
-#: session.cc:5133
+#: session.cc:5121
 msgid "insert ID %1 appears to be in use already"
 msgstr "Insert ID %1 ist offenbar schon in Gebrauch"
 
-#: session.cc:5258
+#: session.cc:5246
 msgid "Cannot write a range where end <= start (e.g. %1 <= %2)"
 msgstr "Kann einen Bereich mit Ende <= Start nicht schreiben (z.B. %1 <= %2)"
 
-#: session.cc:5267
+#: session.cc:5255
 msgid "Cannot write a range with no data."
 msgstr "Kann einen Bereich ohne Daten nicht schreiben."
 
-#: session.cc:5309
+#: session.cc:5297
 msgid "cannot create new file \"%1\" for %2"
 msgstr "Kann neue Datei \"%1\" für %2 nicht erzeugen"
 
-#: session_click.cc:161
+#: session_click.cc:163
 msgid "cannot open click soundfile %1 (%2)"
 msgstr "kann Metronom-Audiodatei %1 nicht öffnen (%2)"
 
-#: session_click.cc:174
+#: session_click.cc:176
 msgid "cannot read data from click soundfile"
 msgstr "kann Daten der Metronom-Audiodatei nicht lesen"
 
@@ -2058,14 +2393,33 @@ msgstr "Keine Projektvoreinstellungen in XML-Datei gefunden."
 msgid "Could not save session options"
 msgstr "Konnte Projektoptionen nicht sichern"
 
-#: session_directory.cc:59
+#: session_directory.cc:65
 msgid "Cannot create Session directory at path %1 Error: %2"
 msgstr "Kann Projektverzeichnis im Pfad %1 nicht erzeugen. Fehler: %2"
 
-#: session_directory.cc:76
+#: session_directory.cc:82
 msgid "Session subdirectory does not exist at path %1"
 msgstr "Projektunterverzeichnis im Pfad %1 existiert nicht"
 
+#: session_directory.cc:161
+msgid ""
+"session-dir and session-name mismatch. Please use 'Menu > Session > Rename' "
+"in the future to rename sessions."
+msgstr ""
+"Projektverzeichnis und Projektname sind verschieden. Bitte benutzen Sie "
+"zukünftig 'Menü > Projekt > Umbenennen', um Projekte umzubenennen."
+
+#: session_directory.cc:167
+msgid ""
+"The session's interchange dir is tainted.\n"
+"There is more than one folder in '%1'.\n"
+"Please remove extra subdirs to reduce possible filename ambiguties."
+msgstr ""
+"Das interchange-Verzeichnis dieses Projekts ist unsauber.\n"
+"Es gibt mehr als einen Ordner in '%1'.\n"
+"Bitte entfernen Sie zusätzliche Unterverzeichnisse, um mögliche "
+"Doppeldeutigkeiten bei Dateinamen zu verhindern."
+
 #: session_events.cc:229
 msgid "Session: cannot have two events of type %1 at the same frame (%2)."
 msgstr ""
@@ -2092,7 +2446,7 @@ msgstr ""
 msgid "Session: cannot send quarter-frame MTC message (%1)"
 msgstr "Session: kann quarter-frame MTC-Nachricht nicht senden (%1)"
 
-#: session_playlists.cc:378 session_playlists.cc:397
+#: session_playlists.cc:402 session_playlists.cc:421
 msgid "Session: cannot create Playlist from XML description."
 msgstr "Session: kann Wiedergabeliste nicht aus der XML-Beschreibung erzeugen"
 
@@ -2104,7 +2458,7 @@ msgstr "Session: Fehler in no_roll für %1"
 msgid "Programming error: illegal event type in process_event (%1)"
 msgstr "Programmierfehler: illegaler Ereignistyp in process_event (%1)"
 
-#: session_state.cc:185
+#: session_state.cc:187
 msgid "solo cut control (dB)"
 msgstr "Solo Cut Einstellung (dB)"
 
@@ -2166,35 +2520,39 @@ msgstr ""
 msgid "Session: cannot create session folder \"%1\" (%2)"
 msgstr "Session: kann den Projektordner \"%1\" nicht erzeugen (%2)"
 
-#: session_state.cc:565
+#: session_state.cc:560
+msgid "Error reading session template file %1 (%2)"
+msgstr "Fehler beim Lesen der Projektvorlagendatei %1 (%2)"
+
+#: session_state.cc:575
+msgid "Error writing session template file %1 (%2)"
+msgstr "Fehler beim Schreiben der Projektvorlagendatei %1 (%2)"
+
+#: session_state.cc:592
 msgid "Could not open %1 for writing session template"
 msgstr "Konnte %1 nicht zum Schreiben der Projektvorlage öffnen"
 
-#: session_state.cc:571
+#: session_state.cc:599
 msgid "Could not open session template %1 for reading"
 msgstr "Konnte Projektvorlage %1 nicht zum Lesen öffnen"
 
-#: session_state.cc:589
+#: session_state.cc:617
 msgid "Loop"
 msgstr "Schleife"
 
-#: session_state.cc:605
-msgid "Master"
-msgstr "Master"
-
-#: session_state.cc:670
+#: session_state.cc:698
 msgid "Could not remove pending capture state at path \"%1\" (%2)"
 msgstr "Konnte vorläufigen Aufnahmestatus im Pfad \"%1\" nicht entfernen (%2)"
 
-#: session_state.cc:694
+#: session_state.cc:722
 msgid "could not rename snapshot %1 to %2 (%3)"
 msgstr "Konnte  Schnappschuss %1 nicht auf %2 umbenennen (%3)"
 
-#: session_state.cc:722
+#: session_state.cc:750
 msgid "Could not remove session file at path \"%1\" (%2)"
 msgstr "Konnte Projektdatei im Pfad \"%1\" nicht entfernen (%2)"
 
-#: session_state.cc:749
+#: session_state.cc:777
 msgid ""
 "the %1 audio engine is not connected and state saving would lose all I/O "
 "connections. Session not saved"
@@ -2202,148 +2560,148 @@ msgstr ""
 "die %1 Audio-Engine ist nicht verbunden, beim Sichern würden Sie daher alle "
 "E/A-Verbindungen verlieren. Projekt nicht gesichert"
 
-#: session_state.cc:804
+#: session_state.cc:841
 msgid "state could not be saved to %1"
 msgstr "Status konnte nicht nach %1 gesichert werden"
 
-#: session_state.cc:806 session_state.cc:819
+#: session_state.cc:843 session_state.cc:856
 msgid "Could not remove temporary session file at path \"%1\" (%2)"
 msgstr "Konnte temporäre Projektdatei im Pfad \"%1\" nicht entfernen (%2)"
 
-#: session_state.cc:816
+#: session_state.cc:853
 msgid "could not rename temporary session file %1 to %2 (%3)"
 msgstr "konnte temporäre Projektdatei %1 nicht nach %2 umbenennen(%3)"
 
-#: session_state.cc:884
+#: session_state.cc:923
 msgid "%1: session file \"%2\" doesn't exist!"
 msgstr "%1: Projektdatei \"%2\" existiert nicht!"
 
-#: session_state.cc:896
+#: session_state.cc:935
 msgid "Could not understand session file %1"
 msgstr "Konnte Projektdatei \"%1\" nicht verstehen"
 
-#: session_state.cc:905
+#: session_state.cc:944
 msgid "Session file %1 is not a session"
 msgstr "Projektdatei %1 ist kein Projekt"
 
-#: session_state.cc:1232
+#: session_state.cc:1273
 msgid "programming error: Session: incorrect XML node sent to set_state()"
 msgstr ""
 "Programmierfehler: Session: Inkorrekter XML-Knoten an send_state() gesendet"
 
-#: session_state.cc:1286
+#: session_state.cc:1327
 msgid "Session: XML state has no options section"
 msgstr "Session: XML hat keinen Abschnitt \"options\""
 
-#: session_state.cc:1291
+#: session_state.cc:1332
 msgid "Session: XML state has no metadata section"
 msgstr "Session: XML hat keinen Abschnitt \"metadata\""
 
-#: session_state.cc:1302
+#: session_state.cc:1343
 msgid "Session: XML state has no sources section"
 msgstr "Session: XML hat keinen Abschnitt \"sources\""
 
-#: session_state.cc:1309
+#: session_state.cc:1350
 msgid "Session: XML state has no Tempo Map section"
 msgstr "Session: XML hat keinen Abschnitt \"Tempo Map\""
 
-#: session_state.cc:1316
+#: session_state.cc:1357
 msgid "Session: XML state has no locations section"
 msgstr "Session: XML hat keinen Abschnitt \"locations\""
 
-#: session_state.cc:1329
+#: session_state.cc:1370
 msgid "Session: XML state has no Regions section"
 msgstr "Session: XML hat keinen Abschnitt \"Regions\""
 
-#: session_state.cc:1336
+#: session_state.cc:1377
 msgid "Session: XML state has no playlists section"
 msgstr "Session: XML hat keinen Abschnitt \"playlists\""
 
-#: session_state.cc:1356
+#: session_state.cc:1397
 msgid "Session: XML state has no bundles section"
 msgstr "Session: XML hat keinen Abschnitt \"bundles\""
 
-#: session_state.cc:1368
+#: session_state.cc:1409
 msgid "Session: XML state has no diskstreams section"
 msgstr "Session: XML hat keinen Abschnitt \"diskstreams\""
 
-#: session_state.cc:1376
+#: session_state.cc:1417
 msgid "Session: XML state has no routes section"
 msgstr "Session: XML hat keinen Abschnitt \"routes\""
 
-#: session_state.cc:1388
+#: session_state.cc:1429
 msgid "Session: XML state has no route groups section"
 msgstr "Session: XML hat keinen Abschnitt \"route groups\""
 
-#: session_state.cc:1397
+#: session_state.cc:1438
 msgid "Session: XML state has no edit groups section"
 msgstr "Session: XML hat keinen Abschnitt \"edit groups\""
 
-#: session_state.cc:1404
+#: session_state.cc:1445
 msgid "Session: XML state has no mix groups section"
 msgstr "Session: XML hat keinen Abschnitt \"mix groups\""
 
-#: session_state.cc:1412
+#: session_state.cc:1453
 msgid "Session: XML state has no click section"
 msgstr "Session: XML hat keinen Abschnitt \"click\""
 
-#: session_state.cc:1458
+#: session_state.cc:1500
 msgid "Session: cannot create Route from XML description."
 msgstr "Session: Kann die Route aus der XML-Beschreibung nicht erzeugen"
 
-#: session_state.cc:1462
+#: session_state.cc:1504
 msgid "Loaded track/bus %1"
 msgstr "Spur/Bus %1 wurde geladen"
 
-#: session_state.cc:1467
+#: session_state.cc:1509
 msgid "Tracks/busses loaded;  Adding to Session"
 msgstr "Spuren/Busse geladen; Füge sie dem Projekt hinzu"
 
-#: session_state.cc:1471
+#: session_state.cc:1513
 msgid "Finished adding tracks/busses"
 msgstr "Hinzufügen der Spuren/Busse abgeschlossen"
 
-#: session_state.cc:1570
+#: session_state.cc:1612
 msgid "Could not find diskstream for route"
 msgstr "Konnte Diskstream für Route nicht finden"
 
-#: session_state.cc:1630
+#: session_state.cc:1672
 msgid "Session: cannot create Region from XML description."
 msgstr "Session: kann Region nicht aus XML-Beschreibung erzeugen"
 
-#: session_state.cc:1634
+#: session_state.cc:1676
 msgid "Can not load state for region '%1'"
 msgstr "Kann Status für Region '%1' nicht laden"
 
-#: session_state.cc:1670
+#: session_state.cc:1712
 msgid "Regions in compound description not found (ID's %1 and %2): ignored"
 msgstr ""
 "Regionen der Verbindungsbeschreibung nicht gefunden (IDs %1 and %2): "
 "ignoriert"
 
-#: session_state.cc:1698
+#: session_state.cc:1740
 msgid "Nested source has no ID info in session file! (ignored)"
 msgstr ""
 "Verschachtelte Quelle hat keine ID-Information in Projektdatei! (ignoriert)"
 
-#: session_state.cc:1710
+#: session_state.cc:1752
 msgid "Cannot reconstruct nested source for region %1"
 msgstr "Kann verschachtelte Quelle für Region %1 nicht wiederherstellen"
 
-#: session_state.cc:1772
+#: session_state.cc:1814
 msgid "Session: XMLNode describing a AudioRegion is incomplete (no source)"
 msgstr ""
 "Session: XML-Knoten zur Beschreibung einer Audioregion ist unvollständig "
 "(Quelle fehlt)"
 
-#: session_state.cc:1780 session_state.cc:1801 session_state.cc:1821
+#: session_state.cc:1822 session_state.cc:1843 session_state.cc:1863
 msgid ""
 "Session: XMLNode describing a AudioRegion references an unknown source id =%1"
 msgstr ""
 "Session: XML-Knoten zur Beschreibung einer Audioregion referenziert eine "
 "unbekannte Quell-ID =%1"
 
-#: session_state.cc:1786 session_state.cc:1807 session_state.cc:1827
+#: session_state.cc:1828 session_state.cc:1849 session_state.cc:1869
 msgid ""
 "Session: XMLNode describing a AudioRegion references a non-audio source id ="
 "%1"
@@ -2351,7 +2709,7 @@ msgstr ""
 "Session: XML-Knoten zur Beschreibung einer Audioregion referenziert eine "
 "Nicht-Audio Quell-ID =%1"
 
-#: session_state.cc:1850
+#: session_state.cc:1892
 msgid ""
 "Session: XMLNode describing an AudioRegion is missing some master sources; "
 "ignored"
@@ -2359,31 +2717,31 @@ msgstr ""
 "Session: dem XML-Knoten zur Beschreibung einer Audioregion fehlen einige "
 "Hauptquellen; ignoriert"
 
-#: session_state.cc:1884
+#: session_state.cc:1926
 msgid "Session: XMLNode describing a MidiRegion is incomplete (no source)"
 msgstr ""
 "Session: XML-Knoten zur Beschreibung einer MIDI-Region ist unvollständig "
 "(Quelle fehlt)"
 
-#: session_state.cc:1892
+#: session_state.cc:1934
 msgid ""
 "Session: XMLNode describing a MidiRegion references an unknown source id =%1"
 msgstr ""
 "Session: XML-Knoten zur Beschreibung einer MIDI-Region referenziert eine "
 "unbekannte Quell-ID =%1"
 
-#: session_state.cc:1898
+#: session_state.cc:1940
 msgid ""
 "Session: XMLNode describing a MidiRegion references a non-midi source id =%1"
 msgstr ""
 "Session: XML-Knoten zur Beschreibung einer MIDI-Region referenziert eine "
 "Nicht-MIDI Quell-ID =%1"
 
-#: session_state.cc:1971
+#: session_state.cc:2013
 msgid "Session: cannot create Source from XML description."
 msgstr "Session: Kann Quelle aus der XML-Beschreibung nicht erzeugen"
 
-#: session_state.cc:1979
+#: session_state.cc:2021
 msgid ""
 "A external MIDI file is missing. %1 cannot currently recover from missing "
 "external MIDI files"
@@ -2391,123 +2749,133 @@ msgstr ""
 "Eine externe MIDI-Datei fehlt, %1 kann zur Zeit mit fehlenden externen MIDI-"
 "Dateien nicht umgehen"
 
-#: session_state.cc:2061
+#: session_state.cc:2103
 msgid "Found a sound file that cannot be used by %1. Talk to the programmers."
 msgstr ""
 "Eine nicht mit %1 benutzbare Audiodatei wurde gefunden. Sprechen Sie mit den "
 "Programmierern."
 
-#: session_state.cc:2082
+#: session_state.cc:2124
 msgid "Could not create templates directory \"%1\" (%2)"
 msgstr "Konnte Vorlagenverzeichnis \"%1\" nicht erzeugen (%2)"
 
-#: session_state.cc:2094
+#: session_state.cc:2136
 msgid "Template \"%1\" already exists - new version not created"
 msgstr "Vorlage \"%1\" existiert bereits - neue Version wurde nicht erzeugt"
 
-#: session_state.cc:2100
+#: session_state.cc:2142
 msgid "Could not create directory for Session template\"%1\" (%2)"
 msgstr "Konnte kein Verzeichnis für Projektvorlage \"%1\" erzeugen (%2)"
 
-#: session_state.cc:2125
+#: session_state.cc:2171
 msgid "template not saved"
 msgstr "Vorlage nicht gesichert"
 
-#: session_state.cc:2135
-msgid "Could not create directory for Session template plugin state\"%1\" (%2)"
-msgstr ""
-"Konnte Verzeichnis für Projektvorlagen-Pluginstatus \"%1\" nicht erzeugen "
-"(%2)"
-
-#: session_state.cc:2380
+#: session_state.cc:2413
 msgid "Unknown node \"%1\" found in Bundles list from session file"
 msgstr "Unbekannter Knoten \"%1\" in Bündelliste der Projektdatei gefunden"
 
-#: session_state.cc:2964
+#: session_state.cc:2869
+msgid "Cannot cleanup peak-files for read-only session."
+msgstr "Kann Peakdateien für Nur-Lese Projekt nicht aufräumen"
+
+#: session_state.cc:2873
+msgid "Cannot cleanup peak-files while recording"
+msgstr "Kann Peakdateien während Aufnahme nicht aufräumen"
+
+#: session_state.cc:2896
+msgid ""
+"Timeout waiting for peak-file creation to terminate before cleanup, please "
+"try again later."
+msgstr ""
+"Timeout beim Warten darauf, daß die Peakdatei-Erzeugung vor dem Aufräumen "
+"abgeschlossen wird, bitte versuchen Sie es später noch einmal."
+
+#: session_state.cc:3121
 msgid "Session: cannot create dead file folder \"%1\" (%2)"
 msgstr "Session: kann den Mülleimer \"%1\" nicht erzeugen (%2)"
 
-#: session_state.cc:3003
+#: session_state.cc:3160
 msgid "cannot rename unused file source from %1 to %2 (%3)"
 msgstr "kann unbenutzte Dateiquelle nicht von %1 nach %2 umbenennen (%3)"
 
-#: session_state.cc:3021
+#: session_state.cc:3178
 msgid "cannot remove peakfile %1 for %2 (%3)"
 msgstr "kann Peakdatei %1 für %2 nicht entfernen (%3)"
 
-#: session_state.cc:3338
+#: session_state.cc:3495
 msgid "could not backup old history file, current history not saved"
 msgstr ""
 "konnte kein Backup der alten Aktionsliste erstellen, momentane Aktionsliste "
 "ungesichert"
 
-#: session_state.cc:3347
+#: session_state.cc:3504
 msgid "history could not be saved to %1"
 msgstr "Aktionsliste konnte nicht nach %1 gesichert werden"
 
-#: session_state.cc:3350
+#: session_state.cc:3507
 msgid "Could not remove history file at path \"%1\" (%2)"
 msgstr "Konnte Aktionslistendatei im Pfad \"%1\" nicht entfernen (%2)"
 
-#: session_state.cc:3354
+#: session_state.cc:3511
 msgid "could not restore history file from backup %1 (%2)"
 msgstr "konnte Aktionslistendatei nicht aus dem Backup %1 restaurieren (%2)"
 
-#: session_state.cc:3379
+#: session_state.cc:3536
 msgid "%1: no history file \"%2\" for this session."
 msgstr "%1: keine Aktionslistendatei \"%2\" für dieses Projekt."
 
-#: session_state.cc:3385
+#: session_state.cc:3542
 msgid "Could not understand session history file \"%1\""
 msgstr "Konnte Projekt-Aktionslistendatei \"%1\" nicht verstehen"
 
-#: session_state.cc:3427
+#: session_state.cc:3584
 msgid "Failed to downcast MidiSource for NoteDiffCommand"
 msgstr "MidiSource für NoteDiffCommand nicht auffindbar"
 
-#: session_state.cc:3438
+#: session_state.cc:3595
 msgid "Failed to downcast MidiSource for SysExDiffCommand"
 msgstr "MidiSource für SysExDiffCommand nicht auffindbar"
 
-#: session_state.cc:3449
+#: session_state.cc:3606
 msgid "Failed to downcast MidiSource for PatchChangeDiffCommand"
 msgstr "MidiSource für PatchChangeDiffCommand nicht auffindbar"
 
-#: session_state.cc:3457
+#: session_state.cc:3614
 msgid "Couldn't figure out how to make a Command out of a %1 XMLNode."
 msgstr "Konnte im XML-Knoten \"%1\" keinen Befehl erkennen."
 
-#: session_state.cc:3695
+#: session_state.cc:3852
 msgid "Session: unknown diskstream type in XML"
 msgstr "Session: Unbekannter Diskstream  im XML"
 
-#: session_state.cc:3700
+#: session_state.cc:3857
 msgid "Session: could not load diskstream via XML state"
 msgstr "Session: konnte Diskstream nicht via XML-Status laden"
 
-#: session_state.cc:3763
+#: session_state.cc:3954
 msgid "Cannot rename read-only session."
-msgstr "Kan Nur-Lese Projekt nicht umbenennen"
+msgstr "Kann Nur-Lese Projekt nicht umbenennen"
 
-#: session_state.cc:3767
+#: session_state.cc:3958
 msgid "Cannot rename session while recording"
 msgstr "Kann Projekt während Aufnahme nicht umbenennen"
 
-#: session_state.cc:3852 session_state.cc:3853 session_state.cc:3895
-#: session_state.cc:3899
+#: session_state.cc:4043 session_state.cc:4044 session_state.cc:4086
+#: session_state.cc:4090
 msgid "renaming %s as %2 failed (%3)"
 msgstr "umbenennen von %s in %2 gescheitert (%3)"
 
-#: session_state.cc:3915 session_state.cc:3916 session_state.cc:3930
-#: session_state.cc:3931
+#: session_state.cc:4106 session_state.cc:4107 session_state.cc:4121
+#: session_state.cc:4122
 msgid "renaming %1 as %2 failed (%3)"
 msgstr "umbenennen von %1 in %2 gescheitert (%3)"
 
-#: session_state.cc:4217
+#: session_state.cc:4431
 msgid "Cannot create new session folder %1"
 msgstr "Kann den neuen Projektordner \"%1\" nicht erzeugen"
 
-#: session_state.cc:4279 session_state.cc:4354
+#: session_state.cc:4493 session_state.cc:4568
 msgid ""
 "\n"
 "copying \"%1\" failed !"
@@ -2515,7 +2883,7 @@ msgstr ""
 "\n"
 "kopieren von \"%1\" fehlgeschlagen !"
 
-#: session_state.cc:4552
+#: session_state.cc:4766
 msgid "unknown reason"
 msgstr "unbekannter Grund"
 
@@ -2523,11 +2891,11 @@ msgstr "unbekannter Grund"
 msgid "Unknown transport state %1 in sync callback"
 msgstr "Unbekannter Transportstatus %1 im Sync-Callback"
 
-#: session_transport.cc:171
+#: session_transport.cc:177
 msgid "Cannot loop - no loop range defined"
 msgstr "Kann nicht loopen - kein Schleifenbereich definieert"
 
-#: session_transport.cc:906
+#: session_transport.cc:956
 msgid ""
 "Seamless looping cannot be supported while %1 is using JACK transport.\n"
 "Recommend changing the configured options"
@@ -2536,11 +2904,11 @@ msgstr ""
 "benutzt.\n"
 "Ändern Sie die Konfigurationsoption"
 
-#: session_transport.cc:988
+#: session_transport.cc:1038
 msgid "Locate called for negative sample position - ignored"
 msgstr "Locate für negative Sample-Position aufgerufen - ignoriert"
 
-#: session_transport.cc:1346
+#: session_transport.cc:1392
 msgid ""
 "Global varispeed cannot be supported while %1 is connected to JACK transport "
 "control"
@@ -2560,18 +2928,18 @@ msgstr "time/size gelesen, aber nicht buffer, korrupter MIDI-Ringbuffer"
 msgid "Event time is before MIDI source position"
 msgstr "Event-Zeitpunkt befindet sich vor MIDI Quellposition"
 
-#: smf_source.cc:415
+#: smf_source.cc:417
 msgid ""
 "Skipping event with unordered beat time %1 < %2 (off by %3 beats, %4 ticks)"
 msgstr ""
 "Ãœberspringe Event mit unsortiertem Schlag-Zeitpunkt %1 < %2(Abweichung %3 "
 "Schläge, %4 Ticks)"
 
-#: smf_source.cc:459
+#: smf_source.cc:461
 msgid "Skipping event with unordered frame time %1 < %2"
 msgstr "Ãœberspringe Event mit unsortiertem Frame-Zeitpunkt %1 < %2"
 
-#: smf_source.cc:524
+#: smf_source.cc:526
 msgid "cannot open MIDI file %1 for write"
 msgstr "kann MIDI-Datei %1 nicht zum Schreiben öffnen"
 
@@ -2588,8 +2956,8 @@ msgid "CAF"
 msgstr "CAF"
 
 #: sndfile_helpers.cc:37
-msgid "W64 (64 bit WAV)"
-msgstr "W64 (64 bit WAV)"
+msgid "W64 (64-bit WAV)"
+msgstr "W64 (64-bit WAV)"
 
 #: sndfile_helpers.cc:38
 msgid "FLAC"
@@ -2632,24 +3000,24 @@ msgid ".raw"
 msgstr ".raw"
 
 #: sndfile_helpers.cc:66
-msgid "Signed 16 bit PCM"
-msgstr "Signed 16 bit PCM"
+msgid "Signed 16-bit PCM"
+msgstr "Signed 16-bit PCM"
 
 #: sndfile_helpers.cc:67
-msgid "Signed 24 bit PCM"
-msgstr "Signed 24 bit PCM"
+msgid "Signed 24-bit PCM"
+msgstr "Signed 24-bit PCM"
 
 #: sndfile_helpers.cc:68
-msgid "Signed 32 bit PCM"
-msgstr "Signed 32 bit PCM"
+msgid "Signed 32-bit PCM"
+msgstr "Signed 32-bit PCM"
 
 #: sndfile_helpers.cc:69
-msgid "Signed 8 bit PCM"
-msgstr "Signed 8 bit PCM"
+msgid "Signed 8-bit PCM"
+msgstr "Signed 8-bit PCM"
 
 #: sndfile_helpers.cc:70
-msgid "32 bit float"
-msgstr "32 bit float"
+msgid "32-bit float"
+msgstr "32-bit float"
 
 #: sndfile_helpers.cc:83
 msgid "Little-endian (Intel)"
@@ -2659,22 +3027,28 @@ msgstr "Little-endian (Intel)"
 msgid "Big-endian (PowerPC)"
 msgstr "Big-endian (PowerPC)"
 
-#: sndfilesource.cc:264
+#: sndfilesource.cc:282
 msgid "SndFileSource: cannot open file \"%1\" for %2"
 msgstr "SndFileSource: kann Datei \"%1\" nicht für %2  öffnen"
 
-#: sndfilesource.cc:282
+#: sndfilesource.cc:300
 msgid "SndFileSource: cannot open file \"%1\" for %2 (%3)"
 msgstr "SndFileSource: kann Datei \"%1\" nicht für %2  öffnen (%3)"
 
-#: sndfilesource.cc:290
+#: sndfilesource.cc:308
 msgid ""
 "SndFileSource: file only contains %1 channels; %2 is invalid as a channel "
 "number"
 msgstr ""
 "SndFileSource: Datei enthält nur %1 Kanäle, %2 ist eine ungültige Kanalzahl"
 
-#: sndfilesource.cc:344 sndfilesource.cc:674
+#: sndfilesource.cc:323
+msgid "Cannot mark RF64 audio file for automatic downgrade to WAV: %1"
+msgstr ""
+"Kann RF64 Audiodatei nicht für die automatische Umwandlung in WAV markieren: "
+"%1"
+
+#: sndfilesource.cc:375 sndfilesource.cc:705
 msgid ""
 "cannot set broadcast info for audio file %1 (%2); dropping broadcast info "
 "for this file"
@@ -2682,67 +3056,67 @@ msgstr ""
 "kann Broadcast-Informationen für die Audiodatei %1 nicht setzen (%2); "
 "verwerfe Broadcast-Informationen für diese Datei"
 
-#: sndfilesource.cc:387
+#: sndfilesource.cc:418
 msgid "could not open file %1 for reading."
 msgstr "konnte Datei %1 nicht zum Lesen öffnen"
 
-#: sndfilesource.cc:422
+#: sndfilesource.cc:453
 msgid "SndFileSource: could not seek to frame %1 within %2 (%3)"
 msgstr "SndFileSource: Konnte in %2 Frame %1 nicht aufsuchen (%3)"
 
-#: sndfilesource.cc:431
+#: sndfilesource.cc:462
 msgid ""
 "SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5, ret was %6)"
 msgstr ""
 "SndFileSource: @ %1 konnte %2 innerhalb %3 nicht lesen (%4) (len = %5, ret "
 "war %6)"
 
-#: sndfilesource.cc:473 sndfilesource.cc:502
+#: sndfilesource.cc:504 sndfilesource.cc:533
 msgid "attempt to write a non-writable audio file source (%1)"
 msgstr "Versuch, in eine schreibgeschützte Audio-Dateiquelle zu schreiben (%1)"
 
-#: sndfilesource.cc:478 utils.cc:563 utils.cc:587 utils.cc:601 utils.cc:620
+#: sndfilesource.cc:509 utils.cc:564 utils.cc:588 utils.cc:602 utils.cc:621
 msgid "programming error: %1 %2"
 msgstr "Programmierfehler: %1 %2"
 
-#: sndfilesource.cc:605 sndfilesource.cc:623
+#: sndfilesource.cc:636 sndfilesource.cc:654
 msgid "attempt to flush a non-writable audio file source (%1)"
 msgstr "Versuch, eine schreibgeschützte Audio-Dateiquelle zu leeren (%1)"
 
-#: sndfilesource.cc:610
+#: sndfilesource.cc:641
 msgid "could not allocate file %1 to write header"
 msgstr "konnte Datei %1 nicht allozieren, um den Dateikopf zu schreiben"
 
-#: sndfilesource.cc:628
+#: sndfilesource.cc:659
 msgid "could not allocate file %1 to flush contents"
 msgstr "konnte Datei %1 nicht allozieren, um Inhalte zu löschen"
 
-#: sndfilesource.cc:640
+#: sndfilesource.cc:671
 msgid ""
 "attempt to store broadcast info in a non-writable audio file source (%1)"
 msgstr ""
 "Versuch, Broadcast-Informationen in eine schreibgeschützte Audio-Dateiquelle "
 "zu schreiben (%1)"
 
-#: sndfilesource.cc:645
+#: sndfilesource.cc:676
 msgid "attempt to set BWF info for an un-opened audio file source (%1)"
 msgstr ""
 "Versuch, BWF-Informationen in einer nicht geöffnete Audio-Dateiquelle zu "
 "setzen (%1)"
 
-#: sndfilesource.cc:689
+#: sndfilesource.cc:720
 msgid "%1: cannot seek to %2 (libsndfile error: %3)"
 msgstr "%1: kann %2 nicht aufsuchen (libsndfile Fehler: %3)"
 
-#: sndfilesource.cc:799
+#: sndfilesource.cc:830
 msgid "SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"
 msgstr "SndFileSource: \"%1\" schlechter Lese-Rückgabewert: %2 von %5 (%3: %4)"
 
-#: sndfilesource.cc:812 sndfilesource.cc:862 sndfilesource.cc:869
+#: sndfilesource.cc:843 sndfilesource.cc:893 sndfilesource.cc:900
 msgid "SndFileSource: \"%1\" bad write (%2)"
 msgstr "SndFileSource: \"%1\" schlechter Schreibvorgang (%2)"
 
-#: sndfilesource.cc:892
+#: sndfilesource.cc:923
 msgid ""
 "Filesource: start time is already set for existing file (%1): Cannot change "
 "start time."
@@ -2750,7 +3124,7 @@ msgstr ""
 "Filesource: Startzeit für existierende Datei (%1) ist bereits gesetzt: Kann "
 "Startzeit nicht ändern."
 
-#: sndfilesource.cc:947
+#: sndfilesource.cc:982
 msgid "SndFileSource: cannot open file \"%1\" for reading"
 msgstr "SndFileSource: kann Datei \"%1\" nicht zum Lesen öffnen"
 
@@ -2761,7 +3135,7 @@ msgstr ""
 "Das Hochladen nach Soundcloud ist gescheitert. Vielleicht sind E-mail-"
 "Adresse oder Passwort falsch?"
 
-#: source_factory.cc:374
+#: source_factory.cc:390
 msgid "Recovery attempted on a MIDI file - not implemented"
 msgstr ""
 "Wiederherstellung einer MIDI-Datei wurde versucht - nicht implementiert"
@@ -2922,6 +3296,10 @@ msgstr ""
 "Dies wird die aktuelle Tempo Map ersetzen!\n"
 "Wollen Sie das wirklich tun?"
 
+#: unknown_processor.cc:86
+msgid "Using plugin-stub with unknown i/o configuration for: "
+msgstr "Benutze Plugin-Platzhalter mit unbekannter E/A-Konfiguration für: "
+
 #: user_bundle.cc:47
 msgid "Node for Bundle has no \"name\" property"
 msgstr "Knoten für Bündel hat keine Eigenschaft \"name\""
@@ -2943,58 +3321,59 @@ msgstr "Knoten für Kanal hat keine Eigenschaft \"type\""
 msgid "Node for Port has no \"name\" property"
 msgstr "Knoten für Port hat keine Eigenschaft \"name\""
 
-#: utils.cc:411 utils.cc:440
+#: utils.cc:412 utils.cc:441
 msgid "Splice"
 msgstr "Schneiden"
 
-#: utils.cc:413 utils.cc:430
+#: utils.cc:414 utils.cc:431
 msgid "Slide"
 msgstr "Gleiten"
 
-#: utils.cc:415 utils.cc:436
+#: utils.cc:416 utils.cc:437
 msgid "Ripple"
 msgstr "Schieben"
 
-#: utils.cc:417 utils.cc:433
+#: utils.cc:418 utils.cc:434
 msgid "Lock"
 msgstr "Sperren"
 
-#: utils.cc:420
+#: utils.cc:421
 msgid "programming error: unknown edit mode string \"%1\""
 msgstr "Programmierfehler: unbekannte Zeichenkette für Editiermodus \"%1\""
 
-#: utils.cc:447 utils.cc:483
+#: utils.cc:448 utils.cc:484
 msgid "MIDI Timecode"
 msgstr "MIDI Timecode"
 
-#: utils.cc:447 utils.cc:481
+#: utils.cc:448 utils.cc:482
 msgid "MTC"
 msgstr "MTC"
 
-#: utils.cc:451 utils.cc:490
+#: utils.cc:452 utils.cc:491
 msgid "MIDI Clock"
 msgstr "MIDI Clock"
 
-#: utils.cc:455 utils.cc:477 utils.cc:497
+#: utils.cc:456 utils.cc:478 utils.cc:498
 msgid "JACK"
 msgstr "JACK"
 
-#: utils.cc:459 utils.cc:494
+#: utils.cc:460 utils.cc:495
 msgid "LTC"
 msgstr "LTC"
 
-#: utils.cc:463
+#: utils.cc:464
 msgid "programming error: unknown sync source string \"%1\""
 msgstr "Programmierfehler: unbekannte Zeichenkette für Sync-Quelle \"%1\""
 
-#: utils.cc:488
+#: utils.cc:489
 msgid "M-Clock"
 msgstr "M-Clock"
 
-#: utils.cc:655
+#: utils.cc:658
 msgid "programming error: unknown native header format: %1"
 msgstr "Programmierfehler: unbekanntes natives Dateikopfformat: %1"
 
-#: utils.cc:670
+#: utils.cc:673
 msgid "cannot open directory %1 (%2)"
 msgstr "kann Verzeichnis %1 nicht öffnen (%2)"
+
diff --git a/libs/ardour/po/ru.po b/libs/ardour/po/ru.po
index 56c2a96..dac67d7 100644
--- a/libs/ardour/po/ru.po
+++ b/libs/ardour/po/ru.po
@@ -3,14 +3,14 @@
 # Igor Blinov pitstop at nm.ru, 2004.
 # Александр Прокудин <alexandre.prokoudine at gmail.com>, 2012.
 # Александр Кольцов <ag1455 at mail.ru>, 2015.
-# Alexandre Prokoudine <alexandre.prokoudine at gmail.com>, 2015.
+# Alexandre Prokoudine <alexandre.prokoudine at gmail.com>, 2015, 2016.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: libardour 4\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-04-09 23:26+0300\n"
-"PO-Revision-Date: 2015-04-15 04:43+0300\n"
+"POT-Creation-Date: 2016-01-07 03:46+0300\n"
+"PO-Revision-Date: 2016-01-07 04:14+0300\n"
 "Last-Translator: Alexandre Prokoudine <alexandre.prokoudine at gmail.com>\n"
 "Language-Team: русский <>\n"
 "Language: ru\n"
@@ -19,94 +19,246 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
 "|| n%100>=20) ? 1 : 2);\n"
-"X-Generator: Gtranslator 2.91.6\n"
+"X-Generator: Gtranslator 2.91.7\n"
 
-#: amp.cc:58 automatable.cc:165
+#: amp.cc:57 automatable.cc:173
+msgid "Trim"
+msgstr ""
+
+#: amp.cc:57 automatable.cc:171
 msgid "Fader"
 msgstr "Фейдер"
 
-#: amp.cc:408
+#: amp.cc:448
 #, c-format
 msgid "%3.1f dB"
 msgstr "%3.1f Дб"
 
-#: amp.cc:449
+#: amp.cc:489
 #, c-format
 msgid "%.2fdB"
 msgstr "%.2f Дб"
 
-#: analyser.cc:117 audioregion.cc:1729
+#: analyser.cc:119 audioregion.cc:1762
 msgid "Transient Analysis failed for %1."
 msgstr "Не удалось выполнить анализ транзиентов для %1."
 
-#: analyser.cc:117
+#: analyser.cc:119
 msgid "Audio File Source"
 msgstr "Источник звукового файла"
 
-#: audio_diskstream.cc:249
+#: audio_backend.cc:31
+msgid "No Error occurred"
+msgstr ""
+
+#: audio_backend.cc:33
+msgid "Failed to initialize audio backend"
+msgstr ""
+
+#: audio_backend.cc:35
+msgid "Failed to deinitialize audio backend"
+msgstr ""
+
+#: audio_backend.cc:37
+msgid "Failed to reinitialize audio backend"
+msgstr ""
+
+#: audio_backend.cc:39
+msgid "Failed to open audio device"
+msgstr "Не удалось открыть звуковое устройство"
+
+#: audio_backend.cc:41
+msgid "Failed to close audio device"
+msgstr "Не удалось закрыть звуковое устройство"
+
+#: audio_backend.cc:43
+msgid "Audio device not valid"
+msgstr ""
+
+#: audio_backend.cc:45
+msgid "Audio device unavailable"
+msgstr "Звуковое устройство недоступно"
+
+#: audio_backend.cc:47
+msgid "Audio device not connected"
+msgstr "Звуковое устройство не подключено"
+
+#: audio_backend.cc:49
+msgid "Failed to request and reserve audio device"
+msgstr ""
+
+#: audio_backend.cc:51
+msgid "Audio device Input/Output error"
+msgstr "Ошибка ввода-вывода при работе со звуковым устройством"
+
+#: audio_backend.cc:53
+msgid "Failed to open MIDI device"
+msgstr "Не удалось открыть MIDI-устройство"
+
+#: audio_backend.cc:55
+msgid "Failed to close MIDI device"
+msgstr "Не удалось закрыть MIDI-устройство"
+
+#: audio_backend.cc:57
+msgid "MIDI device unavailable"
+msgstr "MIDI-устройство недоступно"
+
+#: audio_backend.cc:59
+msgid "MIDI device not connected"
+msgstr "MIDI-устройство не подключено"
+
+#: audio_backend.cc:61
+msgid "MIDI device Input/Output error"
+msgstr "Ошибка ввода-вывода при работе с MIDI-устройством"
+
+#: audio_backend.cc:63
+msgid "Sample format is not supported"
+msgstr "Формат сэмпла не поддерживается"
+
+#: audio_backend.cc:65
+msgid "Sample rate is not supported"
+msgstr "Частота сэмплирования не поддерживается"
+
+#: audio_backend.cc:67
+msgid "Requested input latency is not supported"
+msgstr ""
+
+#: audio_backend.cc:69
+msgid "Requested output latency is not supported"
+msgstr ""
+
+#: audio_backend.cc:71
+msgid "Period size is not supported"
+msgstr "Размер периода не поддерживается"
+
+#: audio_backend.cc:73
+msgid "Period count is not supported"
+msgstr "Количество периодов не поддерживается"
+
+#: audio_backend.cc:75
+msgid "Device configuration not supported"
+msgstr "Конфигурация устройства не поддерживается"
+
+#: audio_backend.cc:77
+msgid "Channel count configuration not supported"
+msgstr "Конфигурация числа каналов не поддерживается"
+
+#: audio_backend.cc:79
+msgid "Input channel count configuration not supported"
+msgstr "Конфигурация числа каналов входа не поддерживается"
+
+#: audio_backend.cc:81
+msgid "Output channel count configuration not supported"
+msgstr "Конфигурация числа каналов выхода не поддерживается"
+
+#: audio_backend.cc:83
+msgid "Unable to aquire realtime permissions"
+msgstr ""
+
+#: audio_backend.cc:85
+msgid "Setting audio device thread priorities failed"
+msgstr ""
+
+#: audio_backend.cc:87
+msgid "Setting MIDI device thread priorities failed"
+msgstr ""
+
+#: audio_backend.cc:89
+msgid "Failed to start process thread"
+msgstr "Не удалось запустить поток обработки"
+
+#: audio_backend.cc:91
+msgid "Failed to start freewheel thread"
+msgstr ""
+
+#: audio_backend.cc:93
+msgid "Failed to register audio/midi ports"
+msgstr "Не удалось зарегистрировать звуковые и MIDI-порты"
+
+#: audio_backend.cc:95
+msgid "Failed to re-connect audio/midi ports"
+msgstr ""
+
+#: audio_backend.cc:97
+msgid "Out Of Memory Error"
+msgstr "Ошибка: закончилась свободная память"
+
+#: audio_backend.cc:99
+msgid "Could not reconnect to Audio/MIDI engine"
+msgstr ""
+
+#: audio_backend.cc:107 export_formats.cc:52 session.cc:6238 session.cc:6258
+msgid "None"
+msgstr "Нет"
+
+#: audio_backend.cc:109
+msgid "Default"
+msgstr ""
+
+#: audio_diskstream.cc:257
 msgid "AudioDiskstream: Playlist \"%1\" isn't an audio playlist"
 msgstr "Поток аудиодиска: Плейлист \"%1\" не является аудиоплейлистом"
 
-#: audio_diskstream.cc:301
+#: audio_diskstream.cc:309
 msgid "AudioDiskstream %1: there is no existing playlist to make a copy of!"
 msgstr "Поток аудиодиска  %1: нет существующих плейлистов для копирования!"
 
-#: audio_diskstream.cc:861 audio_diskstream.cc:871
+#: audio_diskstream.cc:880 audio_diskstream.cc:890
 msgid ""
 "AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"
 msgstr ""
 "Поток аудиодиска %1: при наполнении не может прочитать %2 из плейлиста в "
 "кадре %3"
 
-#: audio_diskstream.cc:1028
+#: audio_diskstream.cc:1053
 msgid "AudioDiskstream %1: cannot read %2 from playlist at frame %3"
 msgstr "AudioDiskstream% 1: Невозможно прочитать %2 из плейлиста в кадре %3"
 
-#: audio_diskstream.cc:1397 audio_diskstream.cc:1416
+#: audio_diskstream.cc:1469 audio_diskstream.cc:1488
 msgid "AudioDiskstream %1: cannot write to disk"
 msgstr "AudioDiskstream% 1: Невозможно записать на диск"
 
-#: audio_diskstream.cc:1459
+#: audio_diskstream.cc:1531
 msgid "AudioDiskstream \"%1\": cannot flush captured data to disk!"
 msgstr ""
 "AudioDiskstream \"%1\": Невозможно заподлицо слить захваченные данные на "
 "диск!"
 
-#: audio_diskstream.cc:1553
+#: audio_diskstream.cc:1627
 msgid "%1: could not create region for complete audio file"
 msgstr "%1: Невозможно создать область для полного звукового файла"
 
-#: audio_diskstream.cc:1585
+#: audio_diskstream.cc:1659
 msgid "AudioDiskstream: could not create region for captured audio!"
 msgstr "AudioDiskstream: Не удалось создать область для захваченного аудио!"
 
-#: audio_diskstream.cc:1693
+#: audio_diskstream.cc:1755
 msgid "programmer error: %1"
 msgstr "Ошибка программиста: %1"
 
-#: audio_diskstream.cc:1921
+#: audio_diskstream.cc:2012
 msgid "AudioDiskstream: channel %1 out of range"
 msgstr "AudioDiskstream: Канал %1 вне диапазона"
 
-#: audio_diskstream.cc:1935 midi_diskstream.cc:1274
+#: audio_diskstream.cc:2026 midi_diskstream.cc:1295
 msgid "%1:%2 new capture file not initialized correctly"
 msgstr "%1:%2 Новый захваченный файл не правильно инициализирован"
 
-#: audio_diskstream.cc:2214
+#: audio_diskstream.cc:2305
 msgid "%1: cannot restore pending capture source file %2"
 msgstr "%1: невозможно восстановить до исходного захваченного файла %2"
 
-#: audio_diskstream.cc:2236
+#: audio_diskstream.cc:2327
 msgid "%1: incorrect number of pending sources listed - ignoring them all"
 msgstr ""
 "%1: Неправильное количество ожидающих перечисленных источников - "
 "игнорированы все"
 
-#: audio_diskstream.cc:2270
+#: audio_diskstream.cc:2361
 msgid "%1: cannot create whole-file region from pending capture sources"
 msgstr "%1: невозможно создать цельнофайловую область из источников захвата"
 
-#: audio_library.cc:81
+#: audio_library.cc:82
 msgid "Could not open %1.  Audio Library not saved"
 msgstr "Не удалось открыть %1. Аудио библиотека не сохранена"
 
@@ -151,10 +303,10 @@ msgstr "Плохо сформированный XML в импортирован
 msgid "Audio Playlists (unused)"
 msgstr "Плейлисты аудио (неиспользованные)"
 
-#: audio_playlist_source.cc:171 audiosource.cc:963 midi_playlist_source.cc:147
-#: midi_playlist_source.cc:155 midi_playlist_source.cc:162 midi_source.cc:356
-#: plugin_insert.cc:641 rb_effect.cc:327 session.cc:2848 session.cc:2881
-#: session.cc:4127 session_handle.cc:87 sndfilesource.cc:154
+#: audio_playlist_source.cc:171 audiosource.cc:1046 midi_playlist_source.cc:147
+#: midi_playlist_source.cc:155 midi_playlist_source.cc:162 midi_source.cc:398
+#: plugin_insert.cc:705 rb_effect.cc:327 session.cc:3550 session.cc:3588
+#: session.cc:4898 session_handle.cc:88 sndfilesource.cc:173
 msgid "programming error: %1"
 msgstr "Ошибка в программе: %1"
 
@@ -182,26 +334,30 @@ msgstr ""
 "\n"
 "Каналов: "
 
-#: audio_track.cc:161
+#: audio_track.cc:176
 msgid "Unknown bundle \"%1\" listed for input of %2"
 msgstr "Неизвестная связка \"%1\" в списке для ввода %2"
 
-#: audio_track.cc:163
+#: audio_track.cc:178
 msgid "in 1"
 msgstr "в 1"
 
-#: audio_track.cc:164
+#: audio_track.cc:179
 msgid "No input bundles available as a replacement"
 msgstr "Нет входных связок, доступных в качестве замены"
 
-#: audio_track.cc:168
+#: audio_track.cc:183
 msgid "Bundle %1 was not available - \"in 1\" used instead"
 msgstr "Связка %1 не была доступна - \"в 1\" использована вместо неё"
 
-#: audio_track.cc:177
+#: audio_track.cc:192
 msgid "improper input channel list in XML node (%1)"
 msgstr "Неадекватный сходящий список каналов в XML узле (% 1)"
 
+#: audio_track.cc:215 diskstream.cc:503 source.cc:149
+msgid "%1: this session uses destructive tracks, which are not supported"
+msgstr ""
+
 #: audio_track_importer.cc:68
 msgid "Audio Tracks"
 msgstr "Звуковые дорожки"
@@ -222,19 +378,19 @@ msgstr "Не удалось загрузить модуль VAMP под назв
 msgid "VAMP Plugin \"%1\" could not be loaded"
 msgstr "Не удалось загрузить модуль VAMP под названием \"%1\""
 
-#: audioengine.cc:757
+#: audioengine.cc:753
 msgid "AudioEngine: cannot load module \"%1\" (%2)"
 msgstr "AudioEngine: невозможно загрузить модуль \"%1\" (%2)"
 
-#: audioengine.cc:763
+#: audioengine.cc:759
 msgid "AudioEngine: backend at \"%1\" has no descriptor function."
 msgstr "AudioEngine: бэкэнд на \"%1\" не имеет функции дескрипторов."
 
-#: audioengine.cc:840
+#: audioengine.cc:838
 msgid "Could not create backend for %1: %2"
 msgstr "Не удалось создать движок для %1: %2"
 
-#: audioregion.cc:1685
+#: audioregion.cc:1718
 msgid ""
 "You have requested an operation that requires audio analysis.\n"
 "\n"
@@ -259,7 +415,7 @@ msgstr ""
 "Этот диалог не будет отображаться снова, но Вы можете заметить небольшую "
 "задержку в этой и будущих операциях переходных обнаружений.\n"
 
-#: audioregion.cc:1729
+#: audioregion.cc:1762
 msgid "Audio Region"
 msgstr "Звуковая область"
 
@@ -267,86 +423,98 @@ msgstr "Звуковая область"
 msgid "cannot rename peakfile for %1 from %2 to %3 (%4)"
 msgstr "Не удалось переименовать пик-файл  для %1 от %2 до %3 (%4)"
 
-#: audiosource.cc:257
+#: audiosource.cc:262
 msgid "AudioSource: cannot stat peakfile \"%1\""
 msgstr "AudioSource: не удалось определить состояние пик-файла \"%1\""
 
-#: audiosource.cc:361
+#: audiosource.cc:368
+msgid "Cannot open peakfile @ %1 for size check (%2)"
+msgstr ""
+
+#: audiosource.cc:389
+msgid "peak file %1 is truncated from %2 to %3"
+msgstr ""
+
+#: audiosource.cc:392
+msgid "Cannot open peakfile @ %1 for size check (%2) after rebuild"
+msgstr ""
+
+#: audiosource.cc:404
 msgid "Cannot open peakfile @ %1 for reading (%2)"
 msgstr "Не удается открыть пик-файл @ %1 для чтения (%2)"
 
-#: audiosource.cc:394
+#: audiosource.cc:438
 msgid "cannot read sample data for unscaled peak computation"
 msgstr ""
 "Не удалось прочитать данные образцов для немасштабированного пик-вычисления"
 
-#: audiosource.cc:430 audiosource.cc:525
+#: audiosource.cc:473 audiosource.cc:568
 msgid "map failed - could not create file mapping for peakfile %1."
 msgstr "Не удалось создать файловую привязку для пикового файла %1."
 
-#: audiosource.cc:436 audiosource.cc:531
+#: audiosource.cc:479 audiosource.cc:574
 msgid "map failed - could not map peakfile %1."
 msgstr "Не удалось выполнить привязку к пиковому файлу %1."
 
-#: audiosource.cc:447 audiosource.cc:542
+#: audiosource.cc:490 audiosource.cc:585
 msgid "unmap failed - could not unmap peakfile %1."
 msgstr "Не удалось удалить привязку к пиковому файлу %1."
 
-#: audiosource.cc:453 audiosource.cc:548
+#: audiosource.cc:496 audiosource.cc:591
 msgid "map failed - could not mmap peakfile %1."
 msgstr "Не удалось применить mmap к пиковому файлу %1."
 
-#: audiosource.cc:638
+#: audiosource.cc:681
 msgid ""
 "AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"
 msgstr ""
 "AudioSource[%1]: пик-чтение - не удалось прочитать %2 образцов по "
 "ответвлению %3 of %4 (%5)"
 
-#: audiosource.cc:705
+#: audiosource.cc:748
 msgid "%1: could not write read raw data for peak computation (%2)"
 msgstr ""
 "%1: не удалось записать прочтённые исходные данные для обеспечения пиковых "
 "вычислений (%2)"
 
-#: audiosource.cc:742
-msgid "AudioSource: cannot open peakpath (c) \"%1\" (%2)"
-msgstr "AudioSource: не удалось открыть пик-маршрут (c) \"%1\" (%2)"
+#: audiosource.cc:815
+msgid "AudioSource: cannot open _peakpath (c) \"%1\" (%2)"
+msgstr ""
 
-#: audiosource.cc:811 audiosource.cc:933
+#: audiosource.cc:894 audiosource.cc:1016
 msgid "%1: could not seek in peak file data (%2)"
 msgstr "%1: не удалось обратиться в пиковые данных файлов (%2)"
 
-#: audiosource.cc:816 audiosource.cc:942
+#: audiosource.cc:899 audiosource.cc:1025
 msgid "%1: could not write peak file data (%2)"
 msgstr "%1: не удалось записать пиковые данные файла (%2)"
 
-#: audiosource.cc:975
+#: audiosource.cc:1058
 msgid "could not truncate peakfile %1 to %2 (error: %3)"
 msgstr "Не удалось усечь пик-файл %1 в %2 (ошибка: %3)"
 
-#: auditioner.cc:100
+#: auditioner.cc:101
 msgid "Falling back to Reasonable Synth for Midi Audition"
 msgstr "Возврат к Reasonable Synth для прослушивания MIDI"
 
-#: auditioner.cc:102
+#: auditioner.cc:103
 msgid "No synth for midi-audition found."
 msgstr "Синтезатора для прослушивания MIDI не найдено."
 
-#: auditioner.cc:158
+#: auditioner.cc:159
 msgid "no outputs available for auditioner - manual connection required"
 msgstr ""
 "Нет доступных выходов для движка прослушивания. Требуется ручное подключение"
 
-#: auditioner.cc:399 auditioner.cc:446
+#: auditioner.cc:404 auditioner.cc:451
 msgid "Cannot setup auditioner processing flow for %1 channels"
 msgstr "Не удалось установить процесс обработки потока для %1 каналов"
 
-#: auditioner.cc:434
+#: auditioner.cc:439
 msgid "Failed to load synth for MIDI-Audition."
 msgstr "Не удалось загрузить синтезатор MIDI-прослушивания."
 
-#: auditioner.cc:453
+#: auditioner.cc:458
 msgid "Auditioning of regions other than Audio or Midi is not supported."
 msgstr ""
 "Прослушивание в других областях, чем это аудио или MIDI не поддерживается."
@@ -355,89 +523,97 @@ msgstr ""
 msgid "Automation node has no path property"
 msgstr "Узел автоматизации не имеет путевых свойств"
 
-#: automatable.cc:104
+#: automatable.cc:105
 msgid "cannot open %2 to load automation data (%3)"
 msgstr "Не удалось открыть %2 для загрузки данных автоматизации (%3)"
 
-#: automatable.cc:132
+#: automatable.cc:137
 msgid "cannot load automation data from %2"
 msgstr "Не удалось загрузить данные автоматизации из %2"
 
-#: automatable.cc:167
+#: automatable.cc:175
 msgid "Mute"
 msgstr "Приглушить"
 
-#: automation_list.cc:356
+#: automation_control.cc:170
+msgid "record %1 automation"
+msgstr ""
+
+#: automation_list.cc:396
 msgid "automation list: cannot load coordinates from XML, all points ignored"
 msgstr ""
 "Список автоматизации: не удалось загрузить координаты из XML. Все точки "
 "игнорированы"
 
-#: automation_list.cc:402
+#: automation_list.cc:442
 msgid ""
 "automation list: no x-coordinate stored for control point (point ignored)"
 msgstr ""
 "Список автоматизации: нет x-координаты, сохранённой для контрольной точки.\n"
 "Точка игнорируется"
 
-#: automation_list.cc:408
+#: automation_list.cc:448
 msgid ""
 "automation list: no y-coordinate stored for control point (point ignored)"
 msgstr ""
 "Список автоматизации: нет y-координаты, сохранённой для контрольной точки.\n"
 "Точка игнорируется"
 
-#: automation_list.cc:422
+#: automation_list.cc:462
 msgid ""
 "AutomationList: passed XML node called %1, not \"AutomationList\" - ignored"
 msgstr ""
 "AutomationList: одобренный XML-узел с именем %1, не \"AutomationList\". "
 "Игнорирован"
 
-#: butler.cc:100
+#: butler.cc:126
 msgid "Session: could not create butler thread"
 msgstr "Сессия: не удалось создать производительскую нить"
 
-#: butler.cc:222 butler.cc:223
+#: butler.cc:254 butler.cc:255
 msgid "Butler read ahead failure on dstream %1"
 msgstr "Сбой производителького упреждающего чтения dstream %1"
 
-#: butler.cc:270 butler.cc:271
+#: butler.cc:344 butler.cc:345 butler.cc:393 butler.cc:394
 msgid "Butler write-behind failure on dstream %1"
 msgstr "Сбой производительской последующей записи на dstream %1"
 
-#: control_protocol_manager.cc:164
+#: control_protocol_manager.cc:174
 msgid "control protocol name \"%1\" has no descriptor"
 msgstr "Протокол управления с именем \"%1\" не имеет дескриптора"
 
-#: control_protocol_manager.cc:171
+#: control_protocol_manager.cc:181
 msgid "control protocol name \"%1\" could not be initialized"
 msgstr "Протокол управления с именем \"%1\" не был инициализирован"
 
-#: control_protocol_manager.cc:237
+#: control_protocol_manager.cc:265
 msgid "Instantiating mandatory control protocol %1"
 msgstr "Создание экземпляров обязательного протокола управления %1"
 
-#: control_protocol_manager.cc:281
+#: control_protocol_manager.cc:309
 msgid "looking for control protocols in %1\n"
 msgstr "Обнаружение протокола управления в %1\n"
 
-#: control_protocol_manager.cc:306
+#: control_protocol_manager.cc:334
 msgid "Control protocol %1 not usable"
 msgstr "Протокол управления %1 не может использаться"
 
-#: control_protocol_manager.cc:323
+#: control_protocol_manager.cc:351
 msgid "Control surface protocol discovered: \"%1\"\n"
 msgstr "Протокол поверхностного управления обнаружил: \"%1\"\n"
 
-#: control_protocol_manager.cc:341
+#: control_protocol_manager.cc:367
 msgid "ControlProtocolManager: cannot load module \"%1\" (%2)"
 msgstr "ControlProtocolManager: не удалось загрузить модуль \"%1\" (%2)"
 
-#: control_protocol_manager.cc:347
+#: control_protocol_manager.cc:373
 msgid "ControlProtocolManager: module \"%1\" has no descriptor function."
 msgstr "ControlProtocolManager: модуль \"%1\" не имеет функции дескриптора."
 
+#: control_protocol_manager.cc:514
+msgid "Control protocol \"%1\" has no descriptor"
+msgstr ""
+
 #: cycle_timer.cc:40
 msgid "CycleTimer::get_mhz(): can't open /proc/cpuinfo"
 msgstr "CycleTimer::get_mhz(): не удалось открыть /proc/cpuinfo"
@@ -454,7 +630,7 @@ msgstr "Не удалось найти частоту CPU в /proc/cpuinfo"
 msgid "audio"
 msgstr "аудио"
 
-#: data_type.cc:28 session.cc:1998 session.cc:2001
+#: data_type.cc:28 session.cc:2312
 msgid "MIDI"
 msgstr "MIDI"
 
@@ -470,7 +646,7 @@ msgstr "Главные выходы"
 msgid "listen"
 msgstr "Слушать"
 
-#: diskstream.cc:309
+#: diskstream.cc:311
 msgid "Location \"%1\" not valid for track loop (start >= end)"
 msgstr "Позиция \"%1\" не распространяется на петлю дорожки (начало >= конца)"
 
@@ -536,23 +712,23 @@ msgstr "Сжатие с потерями"
 msgid "Lossless compression"
 msgstr "Сжатие без потерь"
 
-#: export_format_manager.cc:218 export_format_specification.cc:591
+#: export_format_manager.cc:218 export_format_specification.cc:601
 msgid "Session rate"
 msgstr "Частота сессии"
 
-#: export_format_specification.cc:549
+#: export_format_specification.cc:556
 msgid "normalize"
 msgstr "Нормировка"
 
-#: export_format_specification.cc:553
+#: export_format_specification.cc:560
 msgid "trim"
 msgstr "Обрезка"
 
-#: export_format_specification.cc:555
+#: export_format_specification.cc:562
 msgid "trim start"
 msgstr "Обрезка начала"
 
-#: export_format_specification.cc:557
+#: export_format_specification.cc:564
 msgid "trim end"
 msgstr "Обрезка конца"
 
@@ -568,25 +744,21 @@ msgstr "Треугольное"
 msgid "Rectangular"
 msgstr "Прямоугольное"
 
-#: export_formats.cc:52 session.cc:5424 session.cc:5440
-msgid "None"
-msgstr "Нет"
-
 #: export_formats.cc:159
-msgid "8bit"
-msgstr "8bit"
+msgid "8-bit"
+msgstr "8-bit"
 
 #: export_formats.cc:161
-msgid "16bit"
-msgstr "16bit"
+msgid "16-bit"
+msgstr "16-bit"
 
 #: export_formats.cc:163
-msgid "24bit"
-msgstr "24bit"
+msgid "24-bit"
+msgstr "24-bit"
 
 #: export_formats.cc:165
-msgid "32bit"
-msgstr "32bit"
+msgid "32-bit"
+msgstr "32-bit"
 
 #: export_formats.cc:167
 msgid "float"
@@ -597,8 +769,8 @@ msgid "double"
 msgstr "double"
 
 #: export_formats.cc:171
-msgid "8bit unsigned"
-msgstr "8bit unsigned"
+msgid "8-bit unsigned"
+msgstr "8-bit unsigned"
 
 #: export_formats.cc:173
 msgid "Vorbis sample format"
@@ -608,91 +780,86 @@ msgstr "Формат сэмплов Vorbis"
 msgid "No sample format"
 msgstr "Без формата сэмплов"
 
-#: export_handler.cc:360
+#: export_handler.cc:371
 msgid "File %1 uploaded to %2"
 msgstr "Файл %1 загружен в %2"
 
-#: export_handler.cc:366
+#: export_handler.cc:377
 msgid ""
 "upload to Soundcloud failed. Perhaps your email or password are incorrect?\n"
 msgstr ""
 "Загрузка на Soundcloud не удалось. Возможно, ваша электронная почта или "
 "пароль неверны.\n"
 
-#: export_handler.cc:413
-msgid "Editor: cannot open \"%1\" as export file for CD marker file"
-msgstr ""
-"Редактор: не удалось открыть \"%1\", как файл экспорта для CD-маркера файла"
-
-#: export_handler.cc:492 export_handler.cc:495
+#: export_handler.cc:503 export_handler.cc:506
 msgid "an error occured while writing a TOC/CUE file: %1"
 msgstr "Произошла ошибка при записи TOC/CUE файла: %1"
 
-#: export_handler.cc:744 export_handler.cc:802
+#: export_handler.cc:796 export_handler.cc:854
 msgid "Cannot convert %1 to Latin-1 text"
 msgstr "Невозможно преобразовать %1 в Latin-1 текст"
 
-#: export_profile_manager.cc:93
+#: export_profile_manager.cc:94
 msgid "Searching for export formats in %1"
 msgstr "Поиск форматов экспорта в %1"
 
-#: export_profile_manager.cc:99
+#: export_profile_manager.cc:100
 msgid "Unable to create export format directory %1: %2"
 msgstr "Невозможно создать каталог экспортного формата %1: %2"
 
-#: export_profile_manager.cc:262
+#: export_profile_manager.cc:263
 msgid "Unable to remove export preset %1: %2"
 msgstr "Невозможно удалить профиль экспорта %1: %2"
 
-#: export_profile_manager.cc:351
+#: export_profile_manager.cc:352
 msgid "Selection"
 msgstr "Выделение"
 
-#: export_profile_manager.cc:604
+#: export_profile_manager.cc:616
 msgid "Unable to rename export format %1 to %2: %3"
 msgstr "Невозможно переименовать профиль экспорта %1 в %2: %3"
 
-#: export_profile_manager.cc:636
+#: export_profile_manager.cc:648
 msgid "Unable to remove export profile %1: %2"
 msgstr "Невозможно удалить профиль экспорта %1: %2"
 
-#: export_profile_manager.cc:654
+#: export_profile_manager.cc:666
 msgid "empty format"
 msgstr "Неопределённый формат"
 
-#: export_profile_manager.cc:735
+#: export_profile_manager.cc:747
 msgid "Cannot load export format from %1"
 msgstr "Не удалось загрузить формат экспорта из %1"
 
-#: export_profile_manager.cc:741
+#: export_profile_manager.cc:753
 msgid "Cannot export format read from %1"
 msgstr "Не удалось экспортировать формат чтения из %1"
 
-#: export_profile_manager.cc:835
+#: export_profile_manager.cc:847
 msgid "No timespan has been selected!"
 msgstr "Отрезок времени не указан!"
 
-#: export_profile_manager.cc:839
+#: export_profile_manager.cc:851
 msgid "No channels have been selected!"
 msgstr "Нет выбранных каналов!"
 
-#: export_profile_manager.cc:843
+#: export_profile_manager.cc:855
 msgid "Some channels are empty"
 msgstr "Некоторые каналы пусты"
 
-#: export_profile_manager.cc:876
+#: export_profile_manager.cc:888
 msgid "No format selected!"
 msgstr "Формат не выбран!"
 
-#: export_profile_manager.cc:878
+#: export_profile_manager.cc:890
 msgid "All channels are empty!"
 msgstr "Все каналы пусты!"
 
-#: export_profile_manager.cc:880
+#: export_profile_manager.cc:892
 msgid "One or more of the selected formats is not compatible with this system!"
 msgstr "Один или более из выбранных форматов не совместим с этой системой!"
 
-#: export_profile_manager.cc:883
+#: export_profile_manager.cc:895
 msgid ""
 "%1 supports only %2 channels, but you have %3 channels in your channel "
 "configuration"
@@ -700,7 +867,7 @@ msgstr ""
 "%1 поддерживает только %2 каналов, но вы должны иметь %3 каналов в вашей "
 "Конфигурации каналов"
 
-#: file_source.cc:201 session_state.cc:2858
+#: file_source.cc:201 session_state.cc:3144
 msgid ""
 "there are already 1000 files with names like %1; versioning discontinued"
 msgstr ""
@@ -710,11 +877,11 @@ msgstr ""
 msgid "cannot rename file source from %1 to %2 (%3)"
 msgstr "Невозможно переименовать исходный файл %1 в% 2 (%3)"
 
-#: file_source.cc:251 file_source.cc:375
+#: file_source.cc:251 file_source.cc:374
 msgid "FileSource: search path not set"
 msgstr "FileSource: путь поиска не установлен"
 
-#: file_source.cc:435
+#: file_source.cc:434
 msgid ""
 "FileSource: \"%1\" is ambigous when searching\n"
 "\t"
@@ -722,15 +889,15 @@ msgstr ""
 "FileSource: \"%1\" неоднозначно при поиске\n"
 "\t"
 
-#: file_source.cc:442
+#: file_source.cc:441
 msgid "Filesource: cannot find required file (%1)"
 msgstr "Filesource: не удалось найти нужный файл (%1)"
 
-#: file_source.cc:487
+#: file_source.cc:486
 msgid "Filesource: cannot find required file (%1): %2"
 msgstr "Filesource: не удалось найти нужный файл (%1): %2"
 
-#: file_source.cc:495
+#: file_source.cc:494
 msgid "Filesource: cannot check for existing file (%1): %2"
 msgstr "Filesource: не удалось проверить на наличие файла (%1): %2"
 
@@ -747,11 +914,11 @@ msgstr ""
 msgid "cannot rename file %1 to %2 (%3)"
 msgstr "Не удалось переименовать файл %1 в %2 (%3)"
 
-#: filesystem_paths.cc:105
+#: filesystem_paths.cc:120
 msgid "Cannot create Configuration directory %1 - cannot run"
 msgstr "Не удалось создать каталог конфигурации %1. Начать нельзя"
 
-#: filesystem_paths.cc:110
+#: filesystem_paths.cc:125
 msgid ""
 "Configuration directory %1 already exists and is not a directory/folder - "
 "cannot run"
@@ -759,26 +926,30 @@ msgstr ""
 "Каталог конфигурации %1 уже существует и не является каталогом/папкой "
 "Невозможно начать"
 
-#: filesystem_paths.cc:171
+#: filesystem_paths.cc:186
 msgid "Cannot create cache directory %1 - cannot run"
 msgstr "Не удалось создать кэш каталог %1.  Продолжение невозможно."
 
-#: filesystem_paths.cc:176
+#: filesystem_paths.cc:191
 msgid ""
 "Cache directory %1 already exists and is not a directory/folder - cannot run"
 msgstr ""
 "Каталог кэша %1 уже существует, но не является каталогом/папкой. Продолжение "
 "невозможно."
 
-#: filesystem_paths.cc:194
+#: filesystem_paths.cc:209
 msgid "ARDOUR_DLL_PATH not set in environment - exiting\n"
 msgstr "ARDOUR_DLL_PATH не установлен в среде. Выход\n"
 
-#: filesystem_paths.cc:245
+#: filesystem_paths.cc:232
+msgid "Cannot determine %1 package directory"
+msgstr ""
+
+#: filesystem_paths.cc:277
 msgid "ARDOUR_CONFIG_PATH not set in environment\n"
 msgstr "ARDOUR_CONFIG_PATH не установлен в среде\n"
 
-#: filesystem_paths.cc:266
+#: filesystem_paths.cc:298
 msgid "ARDOUR_DATA_PATH not set in environment\n"
 msgstr "ARDOUR_DATA_PATH не установлен в среде\n"
 
@@ -786,51 +957,75 @@ msgstr "ARDOUR_DATA_PATH не установлен в среде\n"
 msgid "filter: error creating name for new file based on %1"
 msgstr "filter: ошибка при создании имени для нового файла на основе %1"
 
-#: filter.cc:79
+#: filter.cc:92
 msgid "filter: error creating new file %1 (%2)"
 msgstr "filter: ошибка при создании нового файла %1 (%2)"
 
-#: find_session.cc:59
+#: find_session.cc:60
 msgid "cannot check session path %1 (%2)"
 msgstr "Не удалось проверить путь сессии %1 (%2)"
 
-#: find_session.cc:85
+#: find_session.cc:86
 msgid "cannot check statefile %1 (%2)"
 msgstr "Не удалось проверить файл состояния %1 (%2)"
 
-#: find_session.cc:121
+#: find_session.cc:125
 msgid "%1 is not a snapshot file"
 msgstr "%1 не является снимком файла"
 
-#: find_session.cc:138
+#: find_session.cc:142
 msgid "cannot determine current working directory (%1)"
 msgstr "Не удалось определить текущий рабочий каталог (%1)"
 
-#: find_session.cc:155
+#: find_session.cc:159
 msgid "unknown file type for session %1"
 msgstr "Неизвестный тип файла для сессии %1"
 
-#: globals.cc:234
+#: globals.cc:266
 msgid "Could not set system open files limit to \"unlimited\""
 msgstr "Не удалось установить системный лимит открытых файлов в \"unlimited\""
 
-#: globals.cc:236
+#: globals.cc:268
 msgid "Could not set system open files limit to %1"
 msgstr "Не удалось установить системный лимит открытых файлов в %1"
 
-#: globals.cc:240
+#: globals.cc:272 globals.cc:289
 msgid "Your system is configured to limit %1 to only %2 open files"
 msgstr ""
 "Ваша система сконфигурирована с ограничением %1 в только %2 открытых файлов"
 
-#: globals.cc:244
+#: globals.cc:276
 msgid "Could not get system open files limit (%1)"
 msgstr "Не удалось получить системный лимит открытых файлов (%1)"
 
-#: globals.cc:426
+#: globals.cc:291
+msgid "Could not set system open files limit. Current limit is %1 open files"
+msgstr ""
+
+#: globals.cc:473
 msgid "Loading configuration"
 msgstr "Загрузка конфигурации"
 
+#: globals.cc:553 session.cc:1036
+msgid "Monitor"
+msgstr "Монитор"
+
+#: globals.cc:554 session_state.cc:633
+msgid "Master"
+msgstr "Мастер"
+
+#: globals.cc:555
+msgid "Control"
+msgstr ""
+
+#: globals.cc:556
+msgid "Click"
+msgstr ""
+
+#: globals.cc:557
+msgid "Mackie"
+msgstr "Mackie"
+
 #: import.cc:146
 msgid "Cannot find new filename for imported file %1"
 msgstr "Не удалось найти новое имя файла для импортированного файла %1"
@@ -856,8 +1051,8 @@ msgid "Track %1 of %2 contained no usable MIDI data"
 msgstr "Дорожка %1 из %2 не содержит полезных MIDI-данных"
 
 #: import.cc:427
-msgid "MIDI file %1 was not readable (no reason available)"
-msgstr "MIDI-файл %1 нечитаем по неизвестной причине"
+msgid "MIDI file could not be written (best guess: %1)"
+msgstr ""
 
 #: import.cc:475
 msgid "Import: cannot open input sound file \"%1\""
@@ -885,7 +1080,7 @@ msgstr ""
 msgid "Unknown"
 msgstr "Неизвестный"
 
-#: instrument_info.cc:231
+#: instrument_info.cc:227
 msgid "preset %1 (bank %2)"
 msgstr "Предустановки %1 (банк %2)"
 
@@ -905,86 +1100,86 @@ msgstr "IO: не удалось зарегистрировать входной
 msgid "IO: cannot register output port %1"
 msgstr "IO: не удалось зарегистрировать выходной порт %1"
 
-#: io.cc:598 io.cc:654
+#: io.cc:599 io.cc:655
 msgid "incorrect XML node \"%1\" passed to IO object"
 msgstr "Неправильный XML узел \"%1\" одобренный для объекта IO"
 
-#: io.cc:713
+#: io.cc:717
 msgid "in"
 msgstr "в"
 
-#: io.cc:713
+#: io.cc:717
 msgid "out"
 msgstr "за"
 
-#: io.cc:714
+#: io.cc:718
 msgid "input"
 msgstr "вход"
 
-#: io.cc:714
+#: io.cc:718
 msgid "output"
 msgstr "выход"
 
-#: io.cc:724
+#: io.cc:728
 msgid "Unknown bundle \"%1\" listed for %2 of %3"
 msgstr "Неизвестный пакет \"%1\" в списке для %2 из %3"
 
-#: io.cc:790
+#: io.cc:794
 msgid "Bundle %1 was not available - \"%2\" used instead"
 msgstr "Пакет %1 не был доступен - \"%2\" использован вместо него"
 
-#: io.cc:793
+#: io.cc:797
 msgid "No %1 bundles available as a replacement"
 msgstr "Нет %1 пакетов, доступных в качестве замены"
 
-#: io.cc:897
+#: io.cc:901
 msgid "%1: cannot create I/O ports"
 msgstr "%1: не удалось создать порты ввода/вывода"
 
-#: io.cc:1025 io.cc:1126
+#: io.cc:1029 io.cc:1130
 msgid "IO: badly formed string in XML node for inputs \"%1\""
 msgstr "IO: плохо сформированная строка в XML узле для входов \"%1\""
 
-#: io.cc:1030 io.cc:1131
+#: io.cc:1034 io.cc:1135
 msgid "bad input string in XML node \"%1\""
 msgstr "Плохая входная строка в XML узле \"%1\""
 
-#: io.cc:1069
+#: io.cc:1073
 msgid "IO: badly formed string in XML node for outputs \"%1\""
 msgstr "IO: плохо сформированная строка в XML узле для выходов \"%1\""
 
-#: io.cc:1074
+#: io.cc:1078
 msgid "IO: bad output string in XML node \"%1\""
 msgstr "IO: плохая выходная строка в XML узле \"%1\""
 
-#: io.cc:1413
+#: io.cc:1416
 #, c-format
 msgid "%s %u"
 msgstr "%s %u"
 
-#: io.cc:1460
+#: io.cc:1463
 #, c-format
 msgid "%s in"
 msgstr "%s вх."
 
-#: io.cc:1462
+#: io.cc:1465
 #, c-format
 msgid "%s out"
 msgstr "%s вых."
 
-#: io.cc:1537 session.cc:736 session.cc:770
+#: io.cc:1540 session.cc:842 session.cc:876
 msgid "mono"
 msgstr "Моно"
 
-#: io.cc:1539 session.cc:749 session.cc:784
+#: io.cc:1542 session.cc:855 session.cc:890
 msgid "L"
 msgstr "L"
 
-#: io.cc:1539 session.cc:751 session.cc:786
+#: io.cc:1542 session.cc:857 session.cc:892
 msgid "R"
 msgstr "R"
 
-#: io.cc:1541 io.cc:1547
+#: io.cc:1544 io.cc:1550
 #, c-format
 msgid "%d"
 msgstr "%d"
@@ -1043,47 +1238,47 @@ msgstr "Ошибка сохранения файла пресетов %1."
 msgid "Could not locate HOME.  Preset not saved."
 msgstr "Невозможно найти HOME. Предустановки не сохранены."
 
-#: location.cc:456
+#: location.cc:459
 msgid "You cannot put a CD marker at this position"
 msgstr "Вы не можете поставить CD-маркер в это положение"
 
-#: location.cc:608
+#: location.cc:611
 msgid "incorrect XML node passed to Location::set_state"
 msgstr "некорректный XML узел одобрен для Location::set_state"
 
-#: location.cc:613
+#: location.cc:616
 msgid "XML node for Location has no ID information"
 msgstr "У XML-узла позиции нет данных ID"
 
-#: location.cc:617
+#: location.cc:620
 msgid "XML node for Location has no name information"
 msgstr "У XML-узла позиции нет данных имени"
 
-#: location.cc:624
+#: location.cc:627
 msgid "XML node for Location has no start information"
 msgstr "У XML-узла позиции нет данных о начале"
 
-#: location.cc:635
+#: location.cc:638
 msgid "XML node for Location has no end information"
 msgstr "У XML-узла позиции нет данных о конце"
 
-#: location.cc:642
+#: location.cc:645
 msgid "XML node for Location has no flags information"
 msgstr "У XML-узла позиции нет данных о флагах"
 
-#: location.cc:856
+#: location.cc:872
 msgid "Locations: attempt to use unknown location as selected location"
 msgstr "Позиции: попытка использовать неизвестную позицию как выбранную"
 
-#: location.cc:1034
+#: location.cc:1050
 msgid "incorrect XML mode passed to Locations::set_state"
 msgstr "Неверный режим XML одобрен для Locations::set_state"
 
-#: location.cc:1047 session.cc:1296 session.cc:4922 session_state.cc:1054
+#: location.cc:1063 session.cc:1542 session.cc:5722 session_state.cc:1169
 msgid "session"
 msgstr "Сесссия"
 
-#: location.cc:1112
+#: location.cc:1130
 msgid "could not load location from session file - ignored"
 msgstr "Не удалось загрузить позицию из файла сессии, проигнорировано"
 
@@ -1136,50 +1331,66 @@ msgstr ""
 "Вы можете переименовать расположение \n"
 "импортируемой позиции:"
 
-#: ltc_slave.cc:272
+#: ltc_file_reader.cc:96
+msgid "LTCFileReader: cannot open file \"%1\""
+msgstr ""
+
+#: ltc_file_reader.cc:105
+msgid "LTCFileReader: cannot open file \"%1\" (%3)"
+msgstr ""
+
+#: ltc_file_reader.cc:109
+msgid "LTCFileReader: \"%1\" is an empty audio file"
+msgstr ""
+
+#: ltc_file_reader.cc:134
+msgid "LTCFileReader:: invalid audio channel selected"
+msgstr ""
+
+#: ltc_slave.cc:275
 msgid "Session framerate adjusted from %1 to LTC's %2."
 msgstr "Частота кадров сессии в диапазоне от %1 до LTC'ов %2."
 
-#: ltc_slave.cc:286
+#: ltc_slave.cc:289
 msgid "Session and LTC framerate mismatch: LTC:%1 Session:%2."
 msgstr "Частота кадров сессии и LTC не соответствует: LTC:%1 Сессия:%2."
 
-#: ltc_slave.cc:603
+#: ltc_slave.cc:609
 msgid "flywheel"
 msgstr "Маховик"
 
-#: midi_diskstream.cc:173
+#: midi_diskstream.cc:172
 msgid ""
 "%1: I/O configuration change %4 requested to use %2, but channel setup is %3"
 msgstr ""
 "%1: конфигурация I/O предлагает %4 использовать для %2, но установка канала "
 "%3"
 
-#: midi_diskstream.cc:225
+#: midi_diskstream.cc:224
 msgid "MidiDiskstream: Playlist \"%1\" isn't a midi playlist"
 msgstr "MidiDiskstream: плейлист \"%1\" не является MIDI-плейлистом"
 
-#: midi_diskstream.cc:276
+#: midi_diskstream.cc:275
 msgid "MidiDiskstream %1: there is no existing playlist to make a copy of!"
 msgstr "MidiDiskstream %1: нет существующих плейлистов, чтобы сделать копию!"
 
-#: midi_diskstream.cc:754
+#: midi_diskstream.cc:753
 msgid "MidiDiskstream %1: cannot read %2 from playlist at frame %3"
 msgstr "MidiDiskstream %1: не удалось прочитать %2 из плейлиста в кадре %3"
 
-#: midi_diskstream.cc:891
+#: midi_diskstream.cc:890
 msgid "MidiDiskstream %1: cannot write to disk"
 msgstr "MidiDiskstream %1: не удалось записать на диск"
 
-#: midi_diskstream.cc:925
+#: midi_diskstream.cc:924
 msgid "MidiDiskstream \"%1\": cannot flush captured data to disk!"
 msgstr "MidiDiskstream \"%1\": не удалось слить захваченные данные на диск!"
 
-#: midi_diskstream.cc:1014
+#: midi_diskstream.cc:1013
 msgid "%1: could not create region for complete midi file"
 msgstr "%1: не удалось создать область для полного MIDI-файла"
 
-#: midi_diskstream.cc:1055
+#: midi_diskstream.cc:1054
 msgid "MidiDiskstream: could not create region for captured midi!"
 msgstr "MidiDiskstream: не удалось создать область для захваченного миди!"
 
@@ -1199,15 +1410,33 @@ msgstr "Не найден NoteID для изменения свойств нот
 msgid "No SysExID found for sys-ex property change - ignored"
 msgstr "Нет найден SysExID для изменения свойств sys-ex. Игнорировано"
 
-#: midi_model.cc:1994
-msgid "transpose"
-msgstr "Транспонировать"
+#: midi_patch_manager.cc:78
+msgid "Loading %1 MIDI patch from %2"
+msgid_plural "Loading %1 MIDI patches from %2"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
 
-#: midi_patch_manager.cc:133
+#: midi_patch_manager.cc:109
+msgid "Unloading %1 MIDI patch from %2"
+msgid_plural "Unloading %1 MIDI patches from %2"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#: midi_patch_manager.cc:126
+msgid "Error parsing MIDI patch file %1"
+msgstr ""
+
+#: midi_patch_manager.cc:135
 msgid "Duplicate MIDI device `%1' in `%2' ignored"
 msgstr "Дубликат MIDI-устройства` %1' в `%2' проигнорирован"
 
-#: midi_scene_changer.cc:295
+#: midi_patch_manager.cc:170
+msgid "Removing MIDI patch file %1"
+msgstr ""
+
+#: midi_scene_changer.cc:312
 msgid "Scene "
 msgstr "Сцена"
 
@@ -1267,11 +1496,11 @@ msgstr "Контроль полярности"
 msgid "solo control"
 msgstr "Контроль соло"
 
-#: mtc_slave.cc:240
+#: mtc_slave.cc:241
 msgid "MTC Slave: atomic read of current time failed, sleeping!"
 msgstr "MTC Slave: чтение атомного текущего времени не удалось. Спящий режим!"
 
-#: mtc_slave.cc:362
+#: mtc_slave.cc:363
 msgid ""
 "Unknown rate/drop value %1 in incoming MTC stream, session values used "
 "instead"
@@ -1279,11 +1508,11 @@ msgstr ""
 "Неизвестное значение величины частоты кадров/выпадения %1 во входящем  MTC-"
 "потоке. Значения сессии использованы вместо него"
 
-#: mtc_slave.cc:382
+#: mtc_slave.cc:383
 msgid "Session framerate adjusted from %1 TO: MTC's %2."
 msgstr "Частота кадров сессии в диапазоне от %1 ДО: MTC'ов %2."
 
-#: mtc_slave.cc:396
+#: mtc_slave.cc:397
 msgid "Session and MTC framerate mismatch: MTC:%1 %2:%3."
 msgstr "Сессия и частота кадров МТС несоответствуют: MTC:%1 %2:%3."
 
@@ -1364,7 +1593,7 @@ msgstr "PannerManager: модуль \"%1\" не имеет функции дес
 msgid "no panner discovered for in/out = %1/%2"
 msgstr "Не обнаружен паннер для входа/выхода  =%1/%2"
 
-#: panner_shell.cc:122
+#: panner_shell.cc:121
 msgid ""
 "No panner found: check that panners are being discovered correctly during "
 "startup."
@@ -1372,25 +1601,25 @@ msgstr ""
 "Паннер не найден:  убедитесь, что паннеры обнаруживаются правильно во время "
 "запуска."
 
-#: panner_shell.cc:126
+#: panner_shell.cc:125
 msgid "select panner: %1\n"
 msgstr "Выбор панорамирования: %1\n"
 
-#: panner_shell.cc:255
+#: panner_shell.cc:254
 msgid "Unknown panner plugin \"%1\" found in pan state - ignored"
 msgstr ""
 "Найден неизвестный паннер-плагин \"%1\" в состоянии панорамирования. "
 "Игнорировано"
 
-#: panner_shell.cc:261
+#: panner_shell.cc:260
 msgid "panner plugin node has no type information!"
 msgstr "Узел паннер-плагина не имеет информации о типе!"
 
-#: playlist.cc:2138
+#: playlist.cc:2179
 msgid "region state node has no ID, ignored"
 msgstr "Состояние узла области не имеет ID, проигнорировано"
 
-#: playlist.cc:2156
+#: playlist.cc:2197
 msgid "Playlist: cannot create region from XML"
 msgstr "Плейлист: не удалось создать область из XML"
 
@@ -1403,7 +1632,7 @@ msgid "Could not construct playlist for PlaylistSource from session data!"
 msgstr ""
 "Не удалось построить список воспр. для PlaylistSource из данных сессии!"
 
-#: plugin.cc:328
+#: plugin.cc:346
 msgid ""
 "Plugin presets are not supported in this build of %1. Consider paying for a "
 "full version"
@@ -1411,7 +1640,7 @@ msgstr ""
 "Настройки плагина не поддерживаются в этой сборке %1. Рассмотрите "
 "возможность оплаты за полную версию"
 
-#: plugin.cc:403
+#: plugin.cc:429
 msgid ""
 "Saving plugin settings is not supported in this build of %1. Consider paying "
 "for the full version"
@@ -1419,23 +1648,23 @@ msgstr ""
 "Сохранение настроек плагина не поддерживаются в этой сборке %1. Рассмотрите "
 "возможность оплаты за полную версию"
 
-#: plugin_insert.cc:596
+#: plugin_insert.cc:597
 msgid "programming error: "
 msgstr "Программная ошибка: "
 
-#: plugin_insert.cc:933
+#: plugin_insert.cc:1022
 msgid "XML node describing plugin is missing the `type' field"
 msgstr "В XML-узле описания плагина отсутствует поле `type'"
 
-#: plugin_insert.cc:948
+#: plugin_insert.cc:1037
 msgid "unknown plugin type %1 in plugin insert state"
 msgstr "Неизвестный тип плагина %1 в статусе вставки плагина"
 
-#: plugin_insert.cc:976
+#: plugin_insert.cc:1065
 msgid "Plugin has no unique ID field"
 msgstr "Плагин не имеет уникального идентификационного поля"
 
-#: plugin_insert.cc:1001
+#: plugin_insert.cc:1090
 msgid ""
 "Found a reference to a plugin (\"%1\") that is unknown.\n"
 "Perhaps it was removed or moved since it was last used."
@@ -1444,81 +1673,171 @@ msgstr ""
 "Возможно, он был удален или перемещен с тех пор, как был в последний раз "
 "использован."
 
-#: plugin_insert.cc:1115
+#: plugin_insert.cc:1247
 msgid "PluginInsert: Auto: no ladspa port number"
 msgstr "PluginInsert: Auto: нет номера порта LADSPA"
 
-#: plugin_insert.cc:1122
+#: plugin_insert.cc:1254
 msgid "PluginInsert: Auto: port id out of range"
 msgstr "PluginInsert: Auto: ID порта вне диапазона"
 
-#: plugin_insert.cc:1158
+#: plugin_insert.cc:1290
 msgid "PluginInsert: automatable control %1 not found - ignored"
 msgstr ""
 "PluginInsert: управление возможностью автоматизизации %1 не найдено. "
 "Игнорировано"
 
-#: plugin_manager.cc:209
+#: plugin_manager.cc:217
 msgid "Discovering Plugins"
 msgstr "Обнаружение модулей"
 
-#: plugin_manager.cc:231
+#: plugin_manager.cc:245
 msgid "Scanning LADSPA Plugins"
 msgstr "Сканирование плагинов LADSPA"
 
-#: plugin_manager.cc:234
+#: plugin_manager.cc:248
 msgid "Scanning LV2 Plugins"
 msgstr "Сканирование плагинов LV2"
 
-#: plugin_manager.cc:239
+#: plugin_manager.cc:254
 msgid "Scanning Windows VST Plugins"
 msgstr "Сканирование плагинов Windows VST"
 
-#: plugin_manager.cc:246
+#: plugin_manager.cc:256
+msgid "Discovering Windows VST Plugins"
+msgstr ""
+
+#: plugin_manager.cc:265
 msgid "Scanning Linux VST Plugins"
 msgstr "Сканирование плагинов Linux VST"
 
-#: plugin_manager.cc:252
+#: plugin_manager.cc:267
+msgid "Discovering Linux VST Plugins"
+msgstr ""
+
+#: plugin_manager.cc:280
+msgid "VST Blacklist: "
+msgstr "Чёрный список VST"
+
+#: plugin_manager.cc:282
+msgid "VST Blacklist:"
+msgstr "Чёрный список VST:"
+
+#: plugin_manager.cc:292
 msgid "Scanning AU Plugins"
 msgstr "Сканирование плагинов AU"
 
-#: plugin_manager.cc:256
+#: plugin_manager.cc:294
+msgid "Discovering AU Plugins"
+msgstr ""
+
+#: plugin_manager.cc:299
 msgid "Plugin Scan Complete..."
 msgstr "Сканирование плагинов завершено"
 
-#: plugin_manager.cc:393
+#: plugin_manager.cc:483
 msgid "LADSPA"
 msgstr "LADSPA"
 
-#: plugin_manager.cc:445
+#: plugin_manager.cc:535
 msgid "Could not parse rdf file: %1"
 msgstr "Не удалось проанализировать RDF-файл: %1"
 
-#: plugin_manager.cc:482
+#: plugin_manager.cc:572
 msgid "LADSPA: cannot load module \"%1\" (%2)"
 msgstr "LADSPA: не удалось загрузить модуль \"%1\" (%2)"
 
-#: plugin_manager.cc:489
+#: plugin_manager.cc:579
 msgid "LADSPA: module \"%1\" has no descriptor function."
 msgstr "LADSPA: модуль \"%1\" не имеет функции дескриптора."
 
-#: plugin_manager.cc:705
+#: plugin_manager.cc:778
+msgid "--- Windows VST plugins Scan: %1"
+msgstr ""
+
+#: plugin_manager.cc:784
 msgid "VST"
 msgstr "VST"
 
-#: plugin_manager.cc:732
+#: plugin_manager.cc:789
+msgid "--- Windows VST plugins Scan Done"
+msgstr ""
+
+#: plugin_manager.cc:804
+msgid "cannot open dll"
+msgstr ""
+
+#: plugin_manager.cc:808
+msgid "invalid dll, file too small"
+msgstr ""
+
+#: plugin_manager.cc:812
+msgid "not a dll"
+msgstr ""
+
+#: plugin_manager.cc:818
+msgid "cannot determine dll type"
+msgstr ""
+
+#: plugin_manager.cc:822
+msgid "cannot read dll PE header"
+msgstr ""
+
+#: plugin_manager.cc:827
+msgid "invalid dll PE header"
+msgstr ""
+
+#: plugin_manager.cc:834
+msgid "i386 (32-bit)"
+msgstr "i386 (32-bit)"
+
+#: plugin_manager.cc:837
+msgid "Itanium"
+msgstr "Itanium"
+
+#: plugin_manager.cc:840
+msgid "x64 (64-bit)"
+msgstr "x64 (64-bit)"
+
+#: plugin_manager.cc:843
+msgid "Native Architecture"
+msgstr ""
+
+#: plugin_manager.cc:846
+msgid "Unknown Architecture"
+msgstr ""
+
+#: plugin_manager.cc:862
+msgid " *  %1 (cache only)"
+msgstr ""
+
+#: plugin_manager.cc:864
+msgid " *  %1 - %2"
+msgstr ""
+
+#: plugin_manager.cc:878
+msgid " -> Cannot get Windows VST information, plugin ignored."
+msgstr ""
+
+#: plugin_manager.cc:889
 msgid ""
-"VST plugin %1 does not support processReplacing, and so cannot be used in %2 "
-"at this time"
+"VST plugin %1 does not support processReplacing, and cannot be used in %2 at "
+"this time"
+msgstr ""
+
+#: plugin_manager.cc:924
+msgid "Ignoring duplicate Windows VST plugin \"%1\""
+msgstr ""
+
+#: plugin_manager.cc:936
+msgid " -> OK (VST Plugin \"%1\" was added)."
 msgstr ""
-"VST плагин %1 не поддерживает processReplacing и поэтому не может быть "
-"использован в %2 в это время"
 
-#: plugin_manager.cc:824
+#: plugin_manager.cc:984
 msgid "LXVST"
 msgstr "LXVST"
 
-#: plugin_manager.cc:851
+#: plugin_manager.cc:1011
 msgid ""
 "linuxVST plugin %1 does not support processReplacing, and so cannot be used "
 "in %2 at this time"
@@ -1526,15 +1845,15 @@ msgstr ""
 "linuxVST плагин %1 не поддерживает processReplacing и поэтому не может быть "
 "использован в %2 в это время"
 
-#: plugin_manager.cc:1020
+#: plugin_manager.cc:1175
 msgid "unknown plugin status type \"%1\" - all entries ignored"
 msgstr "неизвестный статус типа плагина \"%1\". Все данные проигнорированы"
 
-#: plugin_manager.cc:1037
+#: plugin_manager.cc:1192
 msgid "unknown plugin type \"%1\" - ignored"
 msgstr "Неизвестный тип плагина \"%1\" - проигнорирован"
 
-#: port.cc:450
+#: port.cc:462
 msgid "could not reregister %1"
 msgstr "Не удалось перерегистрировать %1"
 
@@ -1542,15 +1861,15 @@ msgstr "Не удалось перерегистрировать %1"
 msgid "insert %1"
 msgstr "Вставить %1"
 
-#: port_insert.cc:197
+#: port_insert.cc:204
 msgid "XML node describing port insert is missing the `type' field"
 msgstr "Во вставке XML-узла описания порта отсутствует строка `type'"
 
-#: port_insert.cc:202
+#: port_insert.cc:209
 msgid "non-port insert XML used for port plugin insert"
 msgstr "Использована беспортовая вставка XML для вставки порта плагина"
 
-#: port_manager.cc:287
+#: port_manager.cc:285
 msgid ""
 "a port with the name \"%1\" already exists: check for duplicated track/bus "
 "names"
@@ -1558,7 +1877,7 @@ msgstr ""
 "Порт с именем \"%1\" уже существует: проверьте дублированные имена дорожек/"
 "шин "
 
-#: port_manager.cc:289
+#: port_manager.cc:287
 msgid ""
 "No more ports are available. You will need to stop %1 and restart with more "
 "ports if you need this many tracks."
@@ -1566,19 +1885,19 @@ msgstr ""
 "Больше портов нет. Вам нужно будет остановить и перезапустить %1 с большим "
 "количеством портов, если вам нужно много дорожек."
 
-#: port_manager.cc:292
+#: port_manager.cc:290
 msgid "AudioEngine: cannot register port \"%1\": %2"
 msgstr "AudioEngine: не удалось зарегистрировать порт \"%1\": %2"
 
-#: port_manager.cc:331
+#: port_manager.cc:329
 msgid "unable to create port: %1"
 msgstr "Не удалось создать порт: %1"
 
-#: port_manager.cc:418
+#: port_manager.cc:416
 msgid "AudioEngine: cannot connect %1 (%2) to %3 (%4)"
 msgstr "AudioEngine: не удалось подключить %1 (%2) к %3 (%4)"
 
-#: port_manager.cc:470 port_manager.cc:471
+#: port_manager.cc:468 port_manager.cc:469
 msgid "Re-establising port %1 failed"
 msgstr "Переустановка порта %1 не удалась"
 
@@ -1590,19 +1909,19 @@ msgstr "Нет %1 флага свойств в элементе %2"
 msgid "No child node with active property"
 msgstr "Нет дочернего  узла с активными свойствами"
 
-#: rc_configuration.cc:91
+#: rc_configuration.cc:92
 msgid "Loading system configuration file %1"
 msgstr "Загрузка файла конфигурации %1"
 
-#: rc_configuration.cc:95
+#: rc_configuration.cc:96
 msgid "%1: cannot read system configuration file \"%2\""
 msgstr "%1: не удалось прочитать файл системной конфигурации \"%2\""
 
-#: rc_configuration.cc:100
+#: rc_configuration.cc:101
 msgid "%1: system configuration file \"%2\" not loaded successfully."
 msgstr "%1: файл системной конфигурации \"%2\" не загружен успешно."
 
-#: rc_configuration.cc:104
+#: rc_configuration.cc:105
 msgid ""
 "Your system %1 configuration file is empty. This probably means that there "
 "was an error installing %1"
@@ -1610,30 +1929,46 @@ msgstr ""
 "Ваша файл системной конфигурации %1 пуст. Вероятно, это значит, что "
 "произошла ошибка установки %1"
 
-#: rc_configuration.cc:119
+#: rc_configuration.cc:120
 msgid "Loading user configuration file %1"
 msgstr "Загрузка файла пользовательской конфигурации %1"
 
-#: rc_configuration.cc:123
+#: rc_configuration.cc:124
 msgid "%1: cannot read configuration file \"%2\""
 msgstr "%1: не удалось прочитать файл конфигурации \"%2\""
 
-#: rc_configuration.cc:128
+#: rc_configuration.cc:129
 msgid "%1: user configuration file \"%2\" not loaded successfully."
 msgstr "%1: файл пользовательской конфигурации \"%2\" не загружен полностью."
 
-#: rc_configuration.cc:132
+#: rc_configuration.cc:133
 msgid "your %1 configuration file is empty. This is not normal."
 msgstr "Ваш %1 файл конфигурации пуст. Это ненормально."
 
-#: rc_configuration.cc:149
+#: rc_configuration.cc:150
 msgid "Config file %1 not saved"
 msgstr "Файл конфигурации %1 не сохранён"
 
-#: recent_sessions.cc:54
+#: recent_sessions.cc:55
 msgid "cannot open recent session file %1 (%2)"
 msgstr "Не удалось открыть последний файл сессии %1 (%2)"
 
+#: recent_sessions.cc:68 recent_sessions.cc:126
+msgid "Error reading recent session file %1 (%2)"
+msgstr ""
+
+#: recent_sessions.cc:113
+msgid "Cannot open recent template file %1 (%2)"
+msgstr ""
+
+#: recent_sessions.cc:176
+msgid "Error writing recent sessions file %1 (%2)"
+msgstr ""
+
+#: recent_sessions.cc:211
+msgid "Error writing saved template file %1 (%2)"
+msgstr ""
+
 #: region_factory.cc:78 region_factory.cc:120 region_factory.cc:161
 #: region_factory.cc:203
 msgid ""
@@ -1654,11 +1989,11 @@ msgstr "%1 соединение-%2.1 (%3)"
 msgid "cannot create new name for region \"%1\""
 msgstr "Невозможно создать новое имя для области \"%1\""
 
-#: resampled_source.cc:102
+#: resampled_source.cc:106
 msgid "Import: %1"
 msgstr "Импорт: %1"
 
-#: resampled_source.cc:132 srcfilesource.cc:75
+#: resampled_source.cc:135 srcfilesource.cc:75
 msgid "Import: src_new() failed : %1"
 msgstr "Импорт: src_new() не удался: %1"
 
@@ -1666,38 +2001,95 @@ msgstr "Импорт: src_new() не удался: %1"
 msgid "return %1"
 msgstr "Возврат %1"
 
-#: route.cc:1218 route.cc:2701
+#: route.cc:840
+msgid "Cleared Explicit solo: %1\n"
+msgstr ""
+
+#: route.cc:843
+msgid "Cleared Implicit solo: %1 up:%2 down:%3\n"
+msgstr ""
+
+#: route.cc:1370 route.cc:2982
 msgid "unknown Processor type \"%1\"; ignored"
 msgstr "Неизвестный тип процессора \"%1\". Игнорирован"
 
-#: route.cc:1240
+#: route.cc:1392
 msgid "processor could not be created. Ignored."
 msgstr "Процессор не может быть создан. Игнорирован"
 
-#: route.cc:2126 route.cc:2355
+#: route.cc:2405 route.cc:2630
 msgid "Bad node sent to Route::set_state() [%1]"
 msgstr "Отправлен плохой узел в Route::set_state() [%1]"
 
-#: route.cc:2186
+#: route.cc:2465
 msgid "Pannable state found for route (%1) without a panner!"
 msgstr "Статус панаромирования найден для маршрута (%1) без паннера!"
 
-#: route.cc:2260 route.cc:2264 route.cc:2469 route.cc:2473
+#: route.cc:2539 route.cc:2543 route.cc:2744 route.cc:2748
 msgid "badly formed order key string in state file! [%1] ... ignored."
 msgstr ""
 "Плохо сформированная строка порядкового ключа в файле состояния! [%1] ... "
 "игнорирован."
 
-#: route.cc:2479
+#: route.cc:2754
 msgid "Converting deprecated order key for %1 using Editor order %2"
 msgstr ""
 "Преобразование устаревшего порядкового ключа для %1 с использованием "
 "редактора порядка %2"
 
+#: route.cc:3388
+msgid "Invalid Solo-Isolate propagation: from:%1 new:%2 - old:%3 = delta:%4"
+msgstr ""
+
+#: route.cc:5333
+msgid "lo"
+msgstr ""
+
+#: route.cc:5335
+msgid "mid"
+msgstr ""
+
+#: route.cc:5337
+msgid "hi"
+msgstr ""
+
+#: route.cc:5444
+msgid "Leveler"
+msgstr "Выравниватель"
+
+#: route.cc:5446
+msgid "Compressor"
+msgstr "Компрессор"
+
+#: route.cc:5448
+msgid "Limiter"
+msgstr "Ограничитель"
+
+#: route.cc:5451 route.cc:5453 route.cc:5469 route.cc:5471
+msgid "???"
+msgstr ""
+
+#: route.cc:5463
+msgid "Attk"
+msgstr ""
+
+#: route.cc:5465
+msgid "Ratio"
+msgstr ""
+
+#: route.cc:5467
+msgid "Rels"
+msgstr ""
+
 #: route_group.cc:459
 msgid "You cannot subgroup MIDI tracks at this time"
 msgstr "Сейчас вы не можете подгруппировать MIDI-дорожки"
 
+#: route_group.cc:466
+msgid ""
+"You cannot subgroup tracks with different number of outputs at this time."
+msgstr ""
+
 #: rb_effect.cc:229 rb_effect.cc:269
 msgid "tempoize: error reading data from %1 at %2 (wanted %3, got %4)"
 msgstr "tempoize: Ошибка чтения данных из %1 на %2 (ожидается %3, получено %4)"
@@ -1718,96 +2110,116 @@ msgstr "Отправить %1"
 msgid "programming error: send created using role %1"
 msgstr "ошибка в программе: отправка создана при помощи ролей %1"
 
-#: session.cc:358
+#: session.cc:317 session.cc:371
+msgid "Cannot connect to audio/midi engine"
+msgstr ""
+
+#: session.cc:327
+msgid "Session initialization failed"
+msgstr ""
+
+#: session.cc:343
+msgid "Failed to load template/snapshot state"
+msgstr ""
+
+#: session.cc:354
+msgid "Failed to load state"
+msgstr ""
+
+#: session.cc:377
+msgid "Cannot configure audio/midi engine with session parameters"
+msgstr ""
+
+#: session.cc:400
 msgid "Connect to engine"
 msgstr "Соединение со звуковым движком"
 
-#: session.cc:363
+#: session.cc:451
 msgid "Session loading complete"
 msgstr "Загрузка сессии завершена"
 
-#: session.cc:435
+#: session.cc:522
 msgid "Set up LTC"
 msgstr "Настройка LTC"
 
-#: session.cc:437
+#: session.cc:524
 msgid "Set up Click"
 msgstr "Настройка Click"
 
-#: session.cc:439
+#: session.cc:526
 msgid "Set up standard connections"
 msgstr "Настройка обычных соединений"
 
-#: session.cc:667
+#: session.cc:773
 msgid "could not setup Click I/O"
 msgstr "не удалость настроить Click I/O"
 
-#: session.cc:730
+#: session.cc:836
 #, c-format
 msgid "out %s"
 msgstr "out %s"
 
-#: session.cc:732
+#: session.cc:838
 #, c-format
 msgid "out %<PRIu32>"
 msgstr "out %<PRIu32>"
 
-#: session.cc:747
+#: session.cc:853
 #, c-format
 msgid "out %<PRIu32>+%<PRIu32>"
 msgstr "out %<PRIu32>+%<PRIu32>"
 
-#: session.cc:764
+#: session.cc:870
 #, c-format
 msgid "in %s"
 msgstr "in %s"
 
-#: session.cc:766
+#: session.cc:872
 #, c-format
 msgid "in %<PRIu32>"
 msgstr "in %<PRIu32>"
 
-#: session.cc:781
+#: session.cc:887
 #, c-format
 msgid "in %<PRIu32>+%<PRIu32>"
 msgstr "in %<PRIu32>+%<PRIu32>"
 
-#: session.cc:855
+#: session.cc:967
 msgid "cannot connect master output %1 to %2"
 msgstr "Не удалось подключить выход master %1 к %2"
 
-#: session.cc:924
-msgid "Monitor"
-msgstr "Монитор"
+#: session.cc:1050
+msgid "Cannot create monitor section. 'Monitor' Port name is not unique."
+msgstr ""
 
-#: session.cc:969
+#: session.cc:1084 session.cc:1210
 msgid "cannot connect control input %1 to %2"
 msgstr "Не удалось подключить управление входа %1 к %2"
 
-#: session.cc:989
+#: session.cc:1104 session.cc:1229
 msgid "The preferred I/O for the monitor bus (%1) cannot be found"
 msgstr "Предпочитаемый I/O для шины монитора (%1) не может быть найден"
 
-#: session.cc:1020
+#: session.cc:1135 session.cc:1260
 msgid "cannot connect control output %1 to %2"
 msgstr "Не удалось подключить управления выходом %1 к %2"
 
-#: session.cc:1088
+#: session.cc:1318
 msgid "cannot create Auditioner: no auditioning of regions possible"
 msgstr "Невозможно создать Auditioner: прослушивание областей невозможно"
 
-#: session.cc:1273
+#: session.cc:1519
 msgid "Session: you can't use that location for auto punch (start <= end)"
 msgstr ""
 "Сессия: вы не можете использовать эту позицию для автоврезки (начало <= "
 "конец)"
 
-#: session.cc:1300
+#: session.cc:1546
 msgid "Session: you can't use that location for session start/end)"
 msgstr ""
 "Сессия: вы не можете использовать эту позицию в качестве начала/конца сессии"
 
-#: session.cc:1332
+#: session.cc:1578
 msgid ""
 "You cannot use this location for auto-loop because it has zero or negative "
 "length"
@@ -1815,19 +2227,31 @@ msgstr ""
 "Вы не можете использовать эту позицию для автоцикла, поскольку у неё нулевая "
 "или отрицательная длительность"
 
-#: session.cc:1500
+#: session.cc:1761
 msgid "programming error: session range removed!"
 msgstr "Ошибка в программе: диапазон сессии удалён!"
 
-#: session.cc:1754
+#: session.cc:2021
 msgid "feedback loop setup between %1 and %2"
 msgstr "Настройка петли обратной связи между %1 и %2"
 
-#: session.cc:2050
+#: session.cc:2281
+msgid "Track "
+msgstr ""
+
+#: session.cc:2283
+msgid "Audio "
+msgstr ""
+
+#: session.cc:2288
+msgid "MIDI "
+msgstr ""
+
+#: session.cc:2363
 msgid "Session: could not create new midi track."
 msgstr "Сессия: не удалось создать новую MIDI-дорожку"
 
-#: session.cc:2056
+#: session.cc:2369
 msgid ""
 "No more JACK ports are available. You will need to stop %1 and restart JACK "
 "with more ports if you need this many tracks."
@@ -1835,84 +2259,80 @@ msgstr ""
 "Доступных портов JACK больше нет. Вам нужно остановить %1 и перезапустить "
 "JACK с большим количеством портов, если вам нужно больше дорожек."
 
-#: session.cc:2242 session.cc:2245
-msgid "Audio"
-msgstr "Аудио"
-
-#: session.cc:2269 session.cc:2277 session.cc:2355 session.cc:2363
+#: session.cc:2889 session.cc:2897 session.cc:2981 session.cc:2989
 msgid "cannot configure %1 in/%2 out configuration for new audio track"
 msgstr ""
 "Не удалось настроить %1 в/%2 из конфигурации для новой звуковой дорожки"
 
-#: session.cc:2300
+#: session.cc:2922
 msgid "Session: could not create new audio track."
 msgstr "Сессия: не удалось создать новую звуковую дорожку."
 
-#: session.cc:2333 session.cc:2336
+#: session.cc:2959 session.cc:2962
 msgid "Bus"
 msgstr "Шина"
 
-#: session.cc:2386
+#: session.cc:3014
 msgid "Session: could not create new audio route."
 msgstr "Сессия: не удалось создать новый маршрут."
 
-#: session.cc:2446 session.cc:2456
+#: session.cc:3087 session.cc:3097
 msgid "Session: UINT_MAX routes? impossible!"
 msgstr "Сессия: UINT_MAX маршруты? Невозможно!"
 
-#: session.cc:2478
+#: session.cc:3130
 msgid "Session: cannot create track/bus from template description"
 msgstr "Сессия: нельзя создать дорожку/шину из  шаблоннного описания"
 
-#: session.cc:2504
+#: session.cc:3173
 msgid "Session: could not create new route from template"
 msgstr "Сессия: не удалось создать новый маршрут из шаблона"
 
-#: session.cc:2534
+#: session.cc:3207
 msgid "Adding new tracks/busses failed"
 msgstr "Не удалось добавить новые дорожки/шины"
 
-#: session.cc:3674
+#: session.cc:4445
 msgid "Merging embedded file %1: name collision AND md5 hash collision!"
 msgstr "Слияние встроенного файла %1: противоречие названия и MD5 хеша!"
 
-#: session.cc:3804 session.cc:3877
+#: session.cc:4575 session.cc:4648
 msgid "There are already %1 recordings for %2, which I consider too many."
 msgstr "Уже есть %1 записей для %2, которых, считается, слишком много."
 
-#: session.cc:4319
+#: session.cc:5090
 msgid "send ID %1 appears to be in use already"
 msgstr "Отправленное ID %1, кажется, уже используется"
 
-#: session.cc:4331
+#: session.cc:5102
 msgid "aux send ID %1 appears to be in use already"
 msgstr "По-видимому, aux посыл ID %1 уже используется"
 
-#: session.cc:4343
+#: session.cc:5114
 msgid "return ID %1 appears to be in use already"
 msgstr "Возврат ID% 1, по-видимому, уже используется"
 
-#: session.cc:4355
+#: session.cc:5126
 msgid "insert ID %1 appears to be in use already"
 msgstr "По-видимому, вставка ID %1 уже используется"
 
-#: session.cc:4480
+#: session.cc:5251
 msgid "Cannot write a range where end <= start (e.g. %1 <= %2)"
 msgstr "Невозможно записать ряд, где конец <= пуска (например, %1 <= %2)"
 
-#: session.cc:4489
+#: session.cc:5260
 msgid "Cannot write a range with no data."
 msgstr "Невозможно записать область без данных."
 
-#: session.cc:4531
+#: session.cc:5302
 msgid "cannot create new file \"%1\" for %2"
 msgstr "невозможно создать новый файл \"%1\" для %2"
 
-#: session_click.cc:161
+#: session_click.cc:163
 msgid "cannot open click soundfile %1 (%2)"
 msgstr "Не удается открыть кликом звуковой файл %1 (%2)"
 
-#: session_click.cc:174
+#: session_click.cc:176
 msgid "cannot read data from click soundfile"
 msgstr "Не удалось считать данные от клика на звуковой файл"
 
@@ -1955,15 +2375,28 @@ msgstr "Не найдено сессии по умолчанию в XML файл
 msgid "Could not save session options"
 msgstr "Не удалось сохранить параметры сессии"
 
-#: session_directory.cc:59
+#: session_directory.cc:65
 msgid "Cannot create Session directory at path %1 Error: %2"
 msgstr "Невозможно создать каталог сессии по пути %1. Ошибка: %2"
 
-#: session_directory.cc:76
+#: session_directory.cc:82
 msgid "Session subdirectory does not exist at path %1"
 msgstr "Подкаталог сессии не существует по пути %1"
 
-#: session_events.cc:234
+#: session_directory.cc:161
+msgid ""
+"session-dir and session-name mismatch. Please use 'Menu > Session > Rename' "
+"in the future to rename sessions."
+msgstr ""
+
+#: session_directory.cc:167
+msgid ""
+"The session's interchange dir is tainted.\n"
+"There is more than one folder in '%1'.\n"
+"Please remove extra subdirs to reduce possible filename ambiguties."
+msgstr ""
+
+#: session_events.cc:229
 msgid "Session: cannot have two events of type %1 at the same frame (%2)."
 msgstr "Сессия: не удалось получить два события типа %1 на том же кадре (%2)."
 
@@ -1983,103 +2416,115 @@ msgstr ""
 "LTC кодер: неверная частота кадров. LTC кодирование отключено для "
 "оставшегося в этой сессии."
 
-#: session_midi.cc:520
+#: session_midi.cc:534
 msgid "Session: cannot send quarter-frame MTC message (%1)"
 msgstr "Сессия: невозможно отправить четверть-кадровое MTC сообщение (%1)"
 
-#: session_playlists.cc:378 session_playlists.cc:397
+#: session_playlists.cc:402 session_playlists.cc:421
 msgid "Session: cannot create Playlist from XML description."
 msgstr "Сессия: невозможно создать список воспроизведения из описания XML."
 
-#: session_process.cc:136
+#: session_process.cc:159
 msgid "Session: error in no roll for %1"
 msgstr "Сессия: ошибка непрокрутки для %1"
 
-#: session_process.cc:1174
+#: session_process.cc:1199
 msgid "Programming error: illegal event type in process_event (%1)"
 msgstr "Ошибка в программе: некорректный тип события в process_event (%1)"
 
-#: session_state.cc:179
+#: session_state.cc:187
 msgid "solo cut control (dB)"
 msgstr "Контроль вырезки соло (дБ)"
 
-#: session_state.cc:203
+#: session_state.cc:209
 msgid "Set block size and sample rate"
 msgstr "Установка размера блока и частоты сэмплирования"
 
-#: session_state.cc:208
+#: session_state.cc:214
 msgid "Using configuration"
 msgstr "Применяется конфигурация"
 
-#: session_state.cc:332
+#: session_state.cc:339
 msgid "Reset Remote Controls"
 msgstr "Сброс удалённого управления"
 
-#: session_state.cc:424
+#: session_state.cc:368 session_state.cc:400
+msgid "Filling playback buffers"
+msgstr ""
+
+#: session_state.cc:466
 msgid "Session: cannot create session peakfile folder \"%1\" (%2)"
 msgstr "Сессия: невозможно создать сессионную папку \"%1\" с пик-файлами (%2)"
 
-#: session_state.cc:431
+#: session_state.cc:473
 msgid "Session: cannot create session sounds dir \"%1\" (%2)"
 msgstr ""
 "Сессия: невозможно создать сессионную папку \"%1\" со звуковыми файлами (%2)"
 
-#: session_state.cc:438
+#: session_state.cc:480
 msgid "Session: cannot create session midi dir \"%1\" (%2)"
 msgstr "Сессия: невозможно создать сессионную папку \"%1\" с файлами MIDI (%2)"
 
-#: session_state.cc:445
+#: session_state.cc:487
 msgid "Session: cannot create session dead sounds folder \"%1\" (%2)"
 msgstr ""
 "Сессия: невозможно создать сессионную папку \"%1\" с утерянными звуками (%2)"
 
-#: session_state.cc:452
+#: session_state.cc:494
 msgid "Session: cannot create session export folder \"%1\" (%2)"
 msgstr "Сессия: невозможно создать сессионную папку \"%1\" для экспорта (%2)"
 
-#: session_state.cc:459
+#: session_state.cc:501
 msgid "Session: cannot create session analysis folder \"%1\" (%2)"
 msgstr ""
 "Сессия: невозможно создать сессионную папку \"%1\" с данными анализа (%2)"
 
-#: session_state.cc:466
+#: session_state.cc:508
 msgid "Session: cannot create session plugins folder \"%1\" (%2)"
 msgstr "Сессия: невозможно создать сессионную папку \"%1\" плагинов (%2)"
 
-#: session_state.cc:473
+#: session_state.cc:515
 msgid "Session: cannot create session externals folder \"%1\" (%2)"
 msgstr ""
 "Сессия: невозможно создать сессионную папку \"%1\" с внешними данными (%2)"
 
-#: session_state.cc:487
+#: session_state.cc:529
 msgid "Session: cannot create session folder \"%1\" (%2)"
 msgstr "Сессия: невозможно создать папку сессии \"%1\" (%2)"
 
-#: session_state.cc:521
+#: session_state.cc:560
+msgid "Error reading session template file %1 (%2)"
+msgstr ""
+
+#: session_state.cc:575
+msgid "Error writing session template file %1 (%2)"
+msgstr ""
+
+#: session_state.cc:592
 msgid "Could not open %1 for writing session template"
 msgstr "Не удалось открыть %1 для записи шаблона сессии"
 
-#: session_state.cc:527
+#: session_state.cc:599
 msgid "Could not open session template %1 for reading"
 msgstr "Не удалось открыть шаблон сессии %1 для чтения"
 
-#: session_state.cc:546
-msgid "Master"
-msgstr "Мастер"
+#: session_state.cc:617
+msgid "Loop"
+msgstr "Петля"
 
-#: session_state.cc:607
+#: session_state.cc:698
 msgid "Could not remove pending capture state at path \"%1\" (%2)"
 msgstr "Не удалось удалить состояние отложенного захвата по пути \"%1\" (%2)"
 
-#: session_state.cc:631
+#: session_state.cc:722
 msgid "could not rename snapshot %1 to %2 (%3)"
 msgstr "Не удалось переименовать снимок %1 в %2 (%3)"
 
-#: session_state.cc:659
+#: session_state.cc:750
 msgid "Could not remove session file at path \"%1\" (%2)"
 msgstr "Не удалось удалить файл сессии по пути \"%1\" (%2)"
 
-#: session_state.cc:686
+#: session_state.cc:777
 msgid ""
 "the %1 audio engine is not connected and state saving would lose all I/O "
 "connections. Session not saved"
@@ -2087,143 +2532,143 @@ msgstr ""
 "Звуковой движок %1 не подключен и статус сохранения ведёт к потере всх "
 "операций ввода/вывода I/O соединений. Сессия не сохранена"
 
-#: session_state.cc:737
+#: session_state.cc:841
 msgid "state could not be saved to %1"
 msgstr "Статус не может быть сохранен в %1"
 
-#: session_state.cc:739 session_state.cc:750
+#: session_state.cc:843 session_state.cc:856
 msgid "Could not remove temporary session file at path \"%1\" (%2)"
 msgstr "Не удалось удалить временный файл сессии в каталоге \"%1\" (%2)"
 
-#: session_state.cc:747
+#: session_state.cc:853
 msgid "could not rename temporary session file %1 to %2 (%3)"
 msgstr "Не удалось переименовать временный файл сессии %1 в %2 (%3)"
 
-#: session_state.cc:815
+#: session_state.cc:923
 msgid "%1: session file \"%2\" doesn't exist!"
 msgstr "%1: файл сессии «%2» не существует!"
 
-#: session_state.cc:827
+#: session_state.cc:935
 msgid "Could not understand session file %1"
 msgstr "Не удалось понять файл сессии %1"
 
-#: session_state.cc:836
+#: session_state.cc:944
 msgid "Session file %1 is not a session"
 msgstr "Файл сессии %1 не является сессией"
 
-#: session_state.cc:1148
+#: session_state.cc:1273
 msgid "programming error: Session: incorrect XML node sent to set_state()"
 msgstr ""
 "Ошибка в программе: Сессия: некорректный узел XML отправил в set_state ()"
 
-#: session_state.cc:1202
+#: session_state.cc:1327
 msgid "Session: XML state has no options section"
 msgstr "Сессия: состояние XML не имеет раздел опций"
 
-#: session_state.cc:1207
+#: session_state.cc:1332
 msgid "Session: XML state has no metadata section"
 msgstr "Сессия: состояние XML не имеет раздел метаданных"
 
-#: session_state.cc:1218
+#: session_state.cc:1343
 msgid "Session: XML state has no sources section"
 msgstr "Сессия: состояние XML не имеет раздел источников"
 
-#: session_state.cc:1225
+#: session_state.cc:1350
 msgid "Session: XML state has no Tempo Map section"
 msgstr "Сессия: состояние XML не имеет раздела тeмpoкарты"
 
-#: session_state.cc:1232
+#: session_state.cc:1357
 msgid "Session: XML state has no locations section"
 msgstr "Сессия: состояние XML не имеет раздел расположения"
 
-#: session_state.cc:1245
+#: session_state.cc:1370
 msgid "Session: XML state has no Regions section"
 msgstr "Сессия: состояние XML не имеет раздел областей"
 
-#: session_state.cc:1252
+#: session_state.cc:1377
 msgid "Session: XML state has no playlists section"
 msgstr "Сессия: состояние XML не имеет раздел плейлистов"
 
-#: session_state.cc:1272
+#: session_state.cc:1397
 msgid "Session: XML state has no bundles section"
 msgstr "Сессия: состояние XML не имеет раздел слоёв"
 
-#: session_state.cc:1284
+#: session_state.cc:1409
 msgid "Session: XML state has no diskstreams section"
 msgstr "Сессия: состояние XML не имеет раздел дисковых потоков"
 
-#: session_state.cc:1292
+#: session_state.cc:1417
 msgid "Session: XML state has no routes section"
 msgstr "Сессия: состояние XML не имеет раздел маршрутов"
 
-#: session_state.cc:1304
+#: session_state.cc:1429
 msgid "Session: XML state has no route groups section"
 msgstr "Сессия: состояние XML не имеет раздел маршрут групп"
 
-#: session_state.cc:1313
+#: session_state.cc:1438
 msgid "Session: XML state has no edit groups section"
 msgstr "Сессия: состояние XML не имеет раздел редактирования групп"
 
-#: session_state.cc:1320
+#: session_state.cc:1445
 msgid "Session: XML state has no mix groups section"
 msgstr "Сессия: состояние XML не имеет раздел микс-групп"
 
-#: session_state.cc:1328
+#: session_state.cc:1453
 msgid "Session: XML state has no click section"
 msgstr "Сессия: состояние XML не имеет click-раздела"
 
-#: session_state.cc:1374
+#: session_state.cc:1500
 msgid "Session: cannot create Route from XML description."
 msgstr "Сессия: невозможно создать маршрут из описания XML."
 
-#: session_state.cc:1378
+#: session_state.cc:1504
 msgid "Loaded track/bus %1"
 msgstr "Загружена дорожка/шина %1"
 
-#: session_state.cc:1383
+#: session_state.cc:1509
 msgid "Tracks/busses loaded;  Adding to Session"
 msgstr "Дорожки и шины загружены, добавляются в сессию"
 
-#: session_state.cc:1387
+#: session_state.cc:1513
 msgid "Finished adding tracks/busses"
 msgstr "Добавление дорожек/шин завершено"
 
-#: session_state.cc:1486
+#: session_state.cc:1612
 msgid "Could not find diskstream for route"
 msgstr "Не удалось найти дисковые потоки по маршруту"
 
-#: session_state.cc:1546
+#: session_state.cc:1672
 msgid "Session: cannot create Region from XML description."
 msgstr "Сессия: невозможно создать область из описания XML."
 
-#: session_state.cc:1550
+#: session_state.cc:1676
 msgid "Can not load state for region '%1'"
 msgstr "Не удается загрузить состояние для области '%1'"
 
-#: session_state.cc:1586
+#: session_state.cc:1712
 msgid "Regions in compound description not found (ID's %1 and %2): ignored"
 msgstr "Областей в описании соединения не найдено (ID's %1 и %2): игнорировано"
 
-#: session_state.cc:1614
+#: session_state.cc:1740
 msgid "Nested source has no ID info in session file! (ignored)"
 msgstr "Вложенный источник не имеет ID-данных в файле сессии! (Игнорировано)"
 
-#: session_state.cc:1626
+#: session_state.cc:1752
 msgid "Cannot reconstruct nested source for region %1"
 msgstr "Невозможно восстановить вложенный источник для области %1"
 
-#: session_state.cc:1688
+#: session_state.cc:1814
 msgid "Session: XMLNode describing a AudioRegion is incomplete (no source)"
 msgstr "Сессия: XMLNode описание AudioRegion является неполным (без источника)"
 
-#: session_state.cc:1696 session_state.cc:1717 session_state.cc:1737
+#: session_state.cc:1822 session_state.cc:1843 session_state.cc:1863
 msgid ""
 "Session: XMLNode describing a AudioRegion references an unknown source id =%1"
 msgstr ""
 "Сессия: XMLNode описание AudioRegion ссылается на неизвестный идентификатор "
 "источника = %1"
 
-#: session_state.cc:1702 session_state.cc:1723 session_state.cc:1743
+#: session_state.cc:1828 session_state.cc:1849 session_state.cc:1869
 msgid ""
 "Session: XMLNode describing a AudioRegion references a non-audio source id ="
 "%1"
@@ -2231,7 +2676,7 @@ msgstr ""
 "Сессия: XMLNode описание AudioRegion ссылается на неисходный "
 "аудиоидентификатор = %1"
 
-#: session_state.cc:1766
+#: session_state.cc:1892
 msgid ""
 "Session: XMLNode describing an AudioRegion is missing some master sources; "
 "ignored"
@@ -2239,29 +2684,29 @@ msgstr ""
 "Сессия: XMLNode в описании AudioRegion отсутствуют некоторые мастер-"
 "источники; Игнорировано"
 
-#: session_state.cc:1800
+#: session_state.cc:1926
 msgid "Session: XMLNode describing a MidiRegion is incomplete (no source)"
 msgstr "Сессия: XMLNode описание MidiRegion является неполным (без источника)"
 
-#: session_state.cc:1808
+#: session_state.cc:1934
 msgid ""
 "Session: XMLNode describing a MidiRegion references an unknown source id =%1"
 msgstr ""
 "Сессия: XMLNode описание MidiRegion ссылается на неизвестный идентификатор "
 "источника id = %1"
 
-#: session_state.cc:1814
+#: session_state.cc:1940
 msgid ""
 "Session: XMLNode describing a MidiRegion references a non-midi source id =%1"
 msgstr ""
 "Сессия: XMLNode описание MidiRegion ссылается на неисходный MIDI-"
 "идентификатор id= %1"
 
-#: session_state.cc:1873
+#: session_state.cc:2013
 msgid "Session: cannot create Source from XML description."
 msgstr "Сессия: невозможно создать источник из описания XML."
 
-#: session_state.cc:1881
+#: session_state.cc:2021
 msgid ""
 "A external MIDI file is missing. %1 cannot currently recover from missing "
 "external MIDI files"
@@ -2269,121 +2714,149 @@ msgstr ""
 "Внешний MIDI файл отсутствует. % 1 в настоящее время не может восстановить "
 "данные из утраченных внешних MIDI файлов"
 
-#: session_state.cc:1963
+#: session_state.cc:2103
 msgid "Found a sound file that cannot be used by %1. Talk to the programmers."
 msgstr ""
 "Найден звуковой файл, который не может быть использован %1. Обратитесь к "
 "программистам."
 
-#: session_state.cc:1980
+#: session_state.cc:2124
 msgid "Could not create templates directory \"%1\" (%2)"
 msgstr "Не удалось создать шаблоны каталогоа \"%1\" (%2)"
 
-#: session_state.cc:1993
+#: session_state.cc:2136
 msgid "Template \"%1\" already exists - new version not created"
 msgstr "Шаблон \"%1\" уже существует. Новая версия не создана"
 
-#: session_state.cc:1999
+#: session_state.cc:2142
 msgid "Could not create directory for Session template\"%1\" (%2)"
 msgstr "Не удалось создать каталог для шаблона сессии \"%1\" (%2)"
 
-#: session_state.cc:2009
+#: session_state.cc:2171
 msgid "template not saved"
 msgstr "Шаблон не сохранён"
 
-#: session_state.cc:2019
-msgid "Could not create directory for Session template plugin state\"%1\" (%2)"
-msgstr ""
-"Не удалось создать каталог для шаблона состояния плагинов сессии \"%1\" (%2)"
-
-#: session_state.cc:2262
+#: session_state.cc:2413
 msgid "Unknown node \"%1\" found in Bundles list from session file"
 msgstr "Неизвестный узел \"%1\" найден в списке пакетов файла сессии"
 
-#: session_state.cc:2835
+#: session_state.cc:2869
+msgid "Cannot cleanup peak-files for read-only session."
+msgstr ""
+
+#: session_state.cc:2873
+msgid "Cannot cleanup peak-files while recording"
+msgstr ""
+
+#: session_state.cc:2896
+msgid ""
+"Timeout waiting for peak-file creation to terminate before cleanup, please "
+"try again later."
+msgstr ""
+
+#: session_state.cc:3121
 msgid "Session: cannot create dead file folder \"%1\" (%2)"
 msgstr "Сессия: невозможно создать папку утерянных файлов \"%1\" (%2)"
 
-#: session_state.cc:2874
+#: session_state.cc:3160
 msgid "cannot rename unused file source from %1 to %2 (%3)"
 msgstr ""
 "Невозможно переименовать неиспользованный файл источника из %1 в %2 (%3)"
 
-#: session_state.cc:2892
+#: session_state.cc:3178
 msgid "cannot remove peakfile %1 for %2 (%3)"
 msgstr "Не удалось удалить пик-файл %1 для %2 (%3)"
 
-#: session_state.cc:3205
+#: session_state.cc:3495
 msgid "could not backup old history file, current history not saved"
 msgstr ""
 "Невозможно сделать копию старого файла истории. Текущая история не сохранена"
 
-#: session_state.cc:3214
+#: session_state.cc:3504
 msgid "history could not be saved to %1"
 msgstr "История не может быть сохраненв в %1"
 
-#: session_state.cc:3217
+#: session_state.cc:3507
 msgid "Could not remove history file at path \"%1\" (%2)"
 msgstr "Не удалось удалить файл истории по пути \"%1\" (%2)"
 
-#: session_state.cc:3221
+#: session_state.cc:3511
 msgid "could not restore history file from backup %1 (%2)"
 msgstr "Не удалось восстановить файл истории из резервной %1 (% 2)"
 
-#: session_state.cc:3246
+#: session_state.cc:3536
 msgid "%1: no history file \"%2\" for this session."
 msgstr "%1: нет файла истории \"%2\" для этой сессии."
 
-#: session_state.cc:3252
+#: session_state.cc:3542
 msgid "Could not understand session history file \"%1\""
 msgstr "Не удалось понять файл истории сессии \"%1\""
 
-#: session_state.cc:3294
+#: session_state.cc:3584
 msgid "Failed to downcast MidiSource for NoteDiffCommand"
 msgstr "Не удалось обратное приведение MidiSource для NoteDiffCommand"
 
-#: session_state.cc:3305
+#: session_state.cc:3595
 msgid "Failed to downcast MidiSource for SysExDiffCommand"
 msgstr "Не удалось обратное приведение MidiSource для SysExDiffCommand"
 
-#: session_state.cc:3316
+#: session_state.cc:3606
 msgid "Failed to downcast MidiSource for PatchChangeDiffCommand"
 msgstr "Не удалось обратное приведение MidiSource для PatchChangeDiffCommand"
 
-#: session_state.cc:3324
+#: session_state.cc:3614
 msgid "Couldn't figure out how to make a Command out of a %1 XMLNode."
 msgstr "Не удалось выяснить, как сделать команду из %1 XMLNode."
 
-#: session_state.cc:3560
+#: session_state.cc:3852
 msgid "Session: unknown diskstream type in XML"
 msgstr "Сессия: неизвестный тип дисковых потоков в XML"
 
-#: session_state.cc:3565
+#: session_state.cc:3857
 msgid "Session: could not load diskstream via XML state"
 msgstr "Сессия: Не удалось загрузить дисковые потоки через XML-статус"
 
-#: session_state.cc:3628
+#: session_state.cc:3954
 msgid "Cannot rename read-only session."
 msgstr "Невозможно переименовать сеанс, доступный только для чтения."
 
-#: session_state.cc:3632
+#: session_state.cc:3958
 msgid "Cannot rename session while recording"
 msgstr "Невозможно переименовать сеанс во время записи."
 
-#: session_state.cc:3707 session_state.cc:3735 session_state.cc:3750
-#: session_state.cc:3765
+#: session_state.cc:4043 session_state.cc:4044 session_state.cc:4086
+#: session_state.cc:4090
+msgid "renaming %s as %2 failed (%3)"
+msgstr "Переименование %s в %2 не удалось (%3)"
+
+#: session_state.cc:4106 session_state.cc:4107 session_state.cc:4121
+#: session_state.cc:4122
 msgid "renaming %1 as %2 failed (%3)"
 msgstr "Не удалось переименовать %1 в %2 (%3)"
 
+#: session_state.cc:4431
+msgid "Cannot create new session folder %1"
+msgstr ""
+
+#: session_state.cc:4493 session_state.cc:4568
+msgid ""
+"\n"
+"copying \"%1\" failed !"
+msgstr ""
+
+#: session_state.cc:4766
+msgid "unknown reason"
+msgstr ""
+
 #: session_time.cc:214
 msgid "Unknown transport state %1 in sync callback"
 msgstr "Неизвестное состояние транспорта %1 в обратном вызове синхронизации"
 
-#: session_transport.cc:171
+#: session_transport.cc:177
 msgid "Cannot loop - no loop range defined"
 msgstr "Не удалось запустить цикл - диапазон цикла не определен"
 
-#: session_transport.cc:833
+#: session_transport.cc:956
 msgid ""
 "Seamless looping cannot be supported while %1 is using JACK transport.\n"
 "Recommend changing the configured options"
@@ -2392,11 +2865,11 @@ msgstr ""
 "транспорт.\n"
 "Рекомендуется измененить настроенные параметры"
 
-#: session_transport.cc:915
+#: session_transport.cc:1038
 msgid "Locate called for negative sample position - ignored"
 msgstr "Размещение, вызываемое для негативной позиции образца,  игнорировано"
 
-#: session_transport.cc:1272
+#: session_transport.cc:1392
 msgid ""
 "Global varispeed cannot be supported while %1 is connected to JACK transport "
 "control"
@@ -2404,30 +2877,30 @@ msgstr ""
 "Глобальная переменная скорость не поддерживается в то время как %1 подключен "
 "к JACK транспортуконтроль"
 
-#: smf_source.cc:344
+#: smf_source.cc:350
 msgid "Unable to read event prefix, corrupt MIDI ring"
 msgstr "Невозможно прочитать префикс событий. MIDI кольцо повреждено"
 
-#: smf_source.cc:357
+#: smf_source.cc:363
 msgid "Event has time and size but no body, corrupt MIDI ring"
 msgstr "Событие имеет время и размер, но не тело. MIDI-кольцо испорченно"
 
-#: smf_source.cc:363
+#: smf_source.cc:369
 msgid "Event time is before MIDI source position"
 msgstr "Временное событие есть перед позицией MIDI-источника"
 
-#: smf_source.cc:409
+#: smf_source.cc:417
 msgid ""
 "Skipping event with unordered beat time %1 < %2 (off by %3 beats, %4 ticks)"
 msgstr ""
 "Пропускается событие с неупорядоченным время удара %1 < %2 (выключено %3 "
 "ударов, %4 тиков)"
 
-#: smf_source.cc:453
+#: smf_source.cc:461
 msgid "Skipping event with unordered frame time %1 < %2"
 msgstr "Пропускается событие с неупорядоченным временем кадра %1 < %2"
 
-#: smf_source.cc:518
+#: smf_source.cc:526
 msgid "cannot open MIDI file %1 for write"
 msgstr "не удалось открыть MIDI-файл %2 для записи"
 
@@ -2444,8 +2917,8 @@ msgid "CAF"
 msgstr "CAF"
 
 #: sndfile_helpers.cc:37
-msgid "W64 (64 bit WAV)"
-msgstr "W64 (64-разрядный WAV)"
+msgid "W64 (64-bit WAV)"
+msgstr "W64 (64-bit WAV)"
 
 #: sndfile_helpers.cc:38
 msgid "FLAC"
@@ -2488,24 +2961,24 @@ msgid ".raw"
 msgstr ".raw"
 
 #: sndfile_helpers.cc:66
-msgid "Signed 16 bit PCM"
-msgstr "Signed 16 bit PCM"
+msgid "Signed 16-bit PCM"
+msgstr "Signed 16-bit PCM"
 
 #: sndfile_helpers.cc:67
-msgid "Signed 24 bit PCM"
-msgstr "Signed 24 bit PCM"
+msgid "Signed 24-bit PCM"
+msgstr "Signed 24-bit PCM"
 
 #: sndfile_helpers.cc:68
-msgid "Signed 32 bit PCM"
-msgstr "Signed 32 bit PCM"
+msgid "Signed 32-bit PCM"
+msgstr "Signed 32-bit PCM"
 
 #: sndfile_helpers.cc:69
-msgid "Signed 8 bit PCM"
-msgstr "Signed 8 bit PCM"
+msgid "Signed 8-bit PCM"
+msgstr "Signed 8-bit PCM"
 
 #: sndfile_helpers.cc:70
-msgid "32 bit float"
-msgstr "32 bit float"
+msgid "32-bit float"
+msgstr "32-bit float"
 
 #: sndfile_helpers.cc:83
 msgid "Little-endian (Intel)"
@@ -2515,11 +2988,15 @@ msgstr "Прямой порядок байтов (Intel)"
 msgid "Big-endian (PowerPC)"
 msgstr "От старшего к младшему (PowerPC)"
 
-#: sndfilesource.cc:260
+#: sndfilesource.cc:282
+msgid "SndFileSource: cannot open file \"%1\" for %2"
+msgstr ""
+
+#: sndfilesource.cc:300
 msgid "SndFileSource: cannot open file \"%1\" for %2 (%3)"
 msgstr "sndFileSource: Не удалось открыть файл  \"%1\" для %2 (% 3)"
 
-#: sndfilesource.cc:268
+#: sndfilesource.cc:308
 msgid ""
 "SndFileSource: file only contains %1 channels; %2 is invalid as a channel "
 "number"
@@ -2527,7 +3004,11 @@ msgstr ""
 "SndFileSource: файл содержит только %1 каналов; %2 недействителен в качестве "
 "каналаномер"
 
-#: sndfilesource.cc:322 sndfilesource.cc:655
+#: sndfilesource.cc:323
+msgid "Cannot mark RF64 audio file for automatic downgrade to WAV: %1"
+msgstr ""
+
+#: sndfilesource.cc:375 sndfilesource.cc:705
 msgid ""
 "cannot set broadcast info for audio file %1 (%2); dropping broadcast info "
 "for this file"
@@ -2535,65 +3016,65 @@ msgstr ""
 "SndFileSource: файл содержит только %1 каналов; %2 недействителен в качестве "
 "номера канала"
 
-#: sndfilesource.cc:368
-msgid "could not allocate file %1 for reading."
-msgstr "Не удалось выделить файл %1 для чтения."
+#: sndfilesource.cc:418
+msgid "could not open file %1 for reading."
+msgstr "не удалось открыть файл %1 для чтения."
 
-#: sndfilesource.cc:403
+#: sndfilesource.cc:453
 msgid "SndFileSource: could not seek to frame %1 within %2 (%3)"
 msgstr "SndFileSource: невозможно обратиться к кадру %1 в %2 (% 3)"
 
-#: sndfilesource.cc:412
+#: sndfilesource.cc:462
 msgid ""
 "SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5, ret was %6)"
 msgstr ""
 "SndFileSource: @ %1 не смог прочитать кадр %2 в пределах (%3) (len = %5, ret "
 "was %6)"
 
-#: sndfilesource.cc:454 sndfilesource.cc:483
+#: sndfilesource.cc:504 sndfilesource.cc:533
 msgid "attempt to write a non-writable audio file source (%1)"
 msgstr "Попытка записать на незаписываемый источник звукового файла (%1)"
 
-#: sndfilesource.cc:459 utils.cc:579 utils.cc:603 utils.cc:617 utils.cc:636
+#: sndfilesource.cc:509 utils.cc:564 utils.cc:588 utils.cc:602 utils.cc:621
 msgid "programming error: %1 %2"
 msgstr "Программная ошибка: %1 %2"
 
-#: sndfilesource.cc:586 sndfilesource.cc:604
+#: sndfilesource.cc:636 sndfilesource.cc:654
 msgid "attempt to flush a non-writable audio file source (%1)"
 msgstr "Попытка смыть незаписываемый источник звука файла (%1)"
 
-#: sndfilesource.cc:591
+#: sndfilesource.cc:641
 msgid "could not allocate file %1 to write header"
 msgstr "Не удалось выделить файл %1 для записи заголовока"
 
-#: sndfilesource.cc:609
+#: sndfilesource.cc:659
 msgid "could not allocate file %1 to flush contents"
 msgstr "Не удалось выделить файл %1, чтобы флешировать содержание."
 
-#: sndfilesource.cc:621
+#: sndfilesource.cc:671
 msgid ""
 "attempt to store broadcast info in a non-writable audio file source (%1)"
 msgstr ""
 "Попытка сохранить данные вещания в незаписываемый файл источника звука (%1)"
 
-#: sndfilesource.cc:626
+#: sndfilesource.cc:676
 msgid "attempt to set BWF info for an un-opened audio file source (%1)"
 msgstr ""
 "Попытка установить BWF данные для неоткрытого источника звукового файла (%1)"
 
-#: sndfilesource.cc:670
+#: sndfilesource.cc:720
 msgid "%1: cannot seek to %2 (libsndfile error: %3)"
 msgstr "%1: невозможно искать в %2 (libsndfile ошибка: %3)"
 
-#: sndfilesource.cc:780
+#: sndfilesource.cc:830
 msgid "SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"
 msgstr "SndFileSource: \"%1\" плохоe RETVAL-чтение: %2 of %5 (%3: %4)"
 
-#: sndfilesource.cc:793 sndfilesource.cc:843 sndfilesource.cc:850
+#: sndfilesource.cc:843 sndfilesource.cc:893 sndfilesource.cc:900
 msgid "SndFileSource: \"%1\" bad write (%2)"
 msgstr "SndFileSource: \"%1\" плохая запись (%2)"
 
-#: sndfilesource.cc:873
+#: sndfilesource.cc:923
 msgid ""
 "Filesource: start time is already set for existing file (%1): Cannot change "
 "start time."
@@ -2601,6 +3082,10 @@ msgstr ""
 "Filesource: время начала уже установлено для существующего файла (%1): Не "
 "удается изменить время начала."
 
+#: sndfilesource.cc:982
+msgid "SndFileSource: cannot open file \"%1\" for reading"
+msgstr ""
+
 #: soundcloud_upload.cc:129
 msgid ""
 "Upload to Soundcloud failed.  Perhaps your email or password are incorrect?\n"
@@ -2608,7 +3093,7 @@ msgstr ""
 "Загрузка на Soundcloud не удалось. Возможно, ваша электронная почта или "
 "пароль неверны.\n"
 
-#: source_factory.cc:374
+#: source_factory.cc:390
 msgid "Recovery attempted on a MIDI file - not implemented"
 msgstr "Попытка восстановления на MIDI файл не реализована"
 
@@ -2624,7 +3109,7 @@ msgstr "В информация спикера отсутствует повыш
 msgid "Speaker information is missing distance - speaker ignored"
 msgstr "В информация спикера отсутствует расстояние. Спикер игнорирован"
 
-#: srcfilesource.cc:134
+#: srcfilesource.cc:142
 msgid "SrcFileSource: %1"
 msgstr "SrcFileSource: %1"
 
@@ -2713,7 +3198,7 @@ msgstr ""
 msgid "programming error: no tempo section in tempo map!"
 msgstr "Ошибка в программе: нет секции темпа в темп-карте!"
 
-#: tempo.cc:882 tempo.cc:1863
+#: tempo.cc:882 tempo.cc:1892
 msgid "programming error: unhandled MetricSection type"
 msgstr "Ошибка в программе: необработанный MetricSection тип"
 
@@ -2725,16 +3210,16 @@ msgstr "Темп-карта запросила для BBT-времени в ка
 msgid "tempo map asked for frame time at bar < 1  (%1)\n"
 msgstr "Темп-карта запросила время кадра в баре < 1 (%1)\n"
 
-#: tempo.cc:1678 tempo.cc:1692
+#: tempo.cc:1705 tempo.cc:1719
 msgid "Tempo map: could not set new state, restoring old one."
 msgstr ""
 "Темп-карта: не удалось установить новое состояние, восстанавливая старое."
 
-#: tempo.cc:1713
+#: tempo.cc:1740 tempo.cc:1741
 msgid "Multiple meter definitions found at %1"
 msgstr "Определения мультиизмерений найдено на %1"
 
-#: tempo.cc:1718
+#: tempo.cc:1746 tempo.cc:1747
 msgid "Multiple tempo definitions found at %1"
 msgstr "Определения мультитемпа найдено найдено на %1"
 
@@ -2766,6 +3251,10 @@ msgstr ""
 "Это приведет к замене текущей карты темпа!\n"
 "Вы уверены, что хотите это сделать?"
 
+#: unknown_processor.cc:86
+msgid "Using plugin-stub with unknown i/o configuration for: "
+msgstr ""
+
 #: user_bundle.cc:47
 msgid "Node for Bundle has no \"name\" property"
 msgstr "Узел для Bundle это не свойства \"name\""
@@ -2787,64 +3276,127 @@ msgstr "Узел для Channel не имеет свойств \"type\""
 msgid "Node for Port has no \"name\" property"
 msgstr "Node for Port has no \"name\" property"
 
-#: utils.cc:422 utils.cc:451
+#: utils.cc:412 utils.cc:441
 msgid "Splice"
 msgstr "Сращивание"
 
-#: utils.cc:424 utils.cc:441
+#: utils.cc:414 utils.cc:431
 msgid "Slide"
 msgstr "Слайд"
 
-#: utils.cc:426 utils.cc:447
+#: utils.cc:416 utils.cc:437
 msgid "Ripple"
 msgstr "Рябь"
 
-#: utils.cc:428 utils.cc:444
+#: utils.cc:418 utils.cc:434
 msgid "Lock"
 msgstr "Блокировка"
 
-#: utils.cc:431
+#: utils.cc:421
 msgid "programming error: unknown edit mode string \"%1\""
 msgstr "Ошибка в программе: неизвестная строка режима редактирования \"%1\""
 
-#: utils.cc:458 utils.cc:490
+#: utils.cc:448 utils.cc:484
 msgid "MIDI Timecode"
 msgstr "Тайм-код MIDI"
 
-#: utils.cc:458 utils.cc:488
+#: utils.cc:448 utils.cc:482
 msgid "MTC"
 msgstr "MTC"
 
-#: utils.cc:462 utils.cc:497
+#: utils.cc:452 utils.cc:491
 msgid "MIDI Clock"
 msgstr "MIDI-время"
 
-#: utils.cc:466 utils.cc:484 utils.cc:504
+#: utils.cc:456 utils.cc:478 utils.cc:498
 msgid "JACK"
 msgstr "JACK"
 
-#: utils.cc:470
+#: utils.cc:460 utils.cc:495
+msgid "LTC"
+msgstr "LTC"
+
+#: utils.cc:464
 msgid "programming error: unknown sync source string \"%1\""
 msgstr "Ошибка в программе: неизвестная строка источника синхронизации \"%1\""
 
-#: utils.cc:495
+#: utils.cc:489
 msgid "M-Clock"
 msgstr "M-Время"
 
-#: utils.cc:501
-msgid "LTC"
-msgstr "LTC"
-
-#: utils.cc:671
+#: utils.cc:658
 msgid "programming error: unknown native header format: %1"
 msgstr "Ошибка в программе: неизвестный родной формат заголовка: %1"
 
-#: utils.cc:686
+#: utils.cc:673
 msgid "cannot open directory %1 (%2)"
 msgstr "Не удалось открыть директорию %1 (%2)"
 
-#~ msgid "renaming %s as %2 failed (%3)"
-#~ msgstr "Переименование %s в %2 не удалось (%3)"
+#~ msgid ""
+#~ "Could not create directory for Session template plugin state\"%1\" (%2)"
+#~ msgstr ""
+#~ "Не удалось создать каталог для шаблона состояния плагинов сессии "
+#~ "\"%1\" (%2)"
+
+#~ msgid "8bit"
+#~ msgstr "8bit"
+
+#~ msgid "16bit"
+#~ msgstr "16bit"
+
+#~ msgid "24bit"
+#~ msgstr "24bit"
+
+#~ msgid "32bit"
+#~ msgstr "32bit"
+
+#~ msgid "8bit unsigned"
+#~ msgstr "8bit unsigned"
+
+#~ msgid "W64 (64 bit WAV)"
+#~ msgstr "W64 (64-разрядный WAV)"
+
+#~ msgid "Signed 16 bit PCM"
+#~ msgstr "Signed 16 bit PCM"
+
+#~ msgid "Signed 24 bit PCM"
+#~ msgstr "Signed 24 bit PCM"
+
+#~ msgid "Signed 32 bit PCM"
+#~ msgstr "Signed 32 bit PCM"
+
+#~ msgid "Signed 8 bit PCM"
+#~ msgstr "Signed 8 bit PCM"
+
+#~ msgid "32 bit float"
+#~ msgstr "32 bit float"
+
+#~ msgid "AudioSource: cannot open peakpath (c) \"%1\" (%2)"
+#~ msgstr "AudioSource: не удалось открыть пик-маршрут (c) \"%1\" (%2)"
+
+#~ msgid "Editor: cannot open \"%1\" as export file for CD marker file"
+#~ msgstr ""
+#~ "Редактор: не удалось открыть \"%1\", как файл экспорта для CD-маркера "
+#~ "файла"
+
+#~ msgid "MIDI file %1 was not readable (no reason available)"
+#~ msgstr "MIDI-файл %1 нечитаем по неизвестной причине"
+
+#~ msgid "transpose"
+#~ msgstr "Транспонировать"
+
+#~ msgid ""
+#~ "VST plugin %1 does not support processReplacing, and so cannot be used in "
+#~ "%2 at this time"
+#~ msgstr ""
+#~ "VST плагин %1 не поддерживает processReplacing и поэтому не может быть "
+#~ "использован в %2 в это время"
+
+#~ msgid "Audio"
+#~ msgstr "Аудио"
+
+#~ msgid "could not allocate file %1 for reading."
+#~ msgstr "Не удалось выделить файл %1 для чтения."
 
 #~ msgid ""
 #~ "AudioSource: could not seek to correct location in peak file \"%1\" (%2)"
diff --git a/libs/ardour/po/zh.po b/libs/ardour/po/zh.po
index f4d08f6..32fb0c3 100644
--- a/libs/ardour/po/zh.po
+++ b/libs/ardour/po/zh.po
@@ -1,2660 +1,13686 @@
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+# 一善鱼 YQ-YSY at 163.com 完成翻译于 2015-12-09 在 Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn> 的基础上
+#
 msgid ""
 msgstr ""
 "Project-Id-Version: Ardour 3\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2015-03-31 20:13-0400\n"
-"PO-Revision-Date: 2012-08-26 13:43+0800\n"
+"PO-Revision-Date: 2016-01-04 23:21+0800\n"
 "Last-Translator: Rui-huai Zhang <zrhzrh>\n"
 "Language-Team: zrhzrh <zrhzrh at mail.ustc.edu.cn>\n"
-"Language: \n"
+"Language: zh_CN\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
-"X-Poedit-Basepath: ../../\n"
-"X-Poedit-Language: Chinese\n"
-"X-Poedit-Country: CHINA\n"
+"X-Poedit-Basepath: ../..\n"
 "X-Poedit-SourceCharset: utf-8\n"
-"X-Poedit-SearchPath-0: ardour\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Poedit 1.8.4\n"
+"X-Poedit-SearchPath-0: gtk2_ardour\n"
 
-#: amp.cc:57 automatable.cc:165
-msgid "Fader"
+#: about.cc:125
+msgid "Brian Ahr"
 msgstr ""
 
-#: analyser.cc:117 audioregion.cc:1729
-msgid "Transient Analysis failed for %1."
+#: about.cc:126
+msgid "John Anderson"
 msgstr ""
 
-#: analyser.cc:117
-msgid "Audio File Source"
+#: about.cc:127
+msgid "Marcus Andersson"
 msgstr ""
 
-#: audio_diskstream.cc:249
-msgid "AudioDiskstream: Playlist \"%1\" isn't an audio playlist"
+#: about.cc:128
+msgid "Nedko Arnaudov"
 msgstr ""
 
-#: audio_diskstream.cc:301
-msgid "AudioDiskstream %1: there is no existing playlist to make a copy of!"
+#: about.cc:129
+msgid "Hans Baier"
 msgstr ""
 
-#: audio_diskstream.cc:861 audio_diskstream.cc:871
-msgid ""
-"AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"
+#: about.cc:130
+msgid "Ben Bell"
 msgstr ""
 
-#: audio_diskstream.cc:1028
-msgid "AudioDiskstream %1: cannot read %2 from playlist at frame %3"
+#: about.cc:131
+msgid "Sakari Bergen"
 msgstr ""
 
-#: audio_diskstream.cc:1397 audio_diskstream.cc:1416
-msgid "AudioDiskstream %1: cannot write to disk"
-msgstr "音频磁盘流 %1: 无法吸入到硬盘"
-
-#: audio_diskstream.cc:1459
-msgid "AudioDiskstream \"%1\": cannot flush captured data to disk!"
+#: about.cc:132
+msgid "Christian Borss"
 msgstr ""
 
-#: audio_diskstream.cc:1553
-msgid "%1: could not create region for complete audio file"
+#: about.cc:133
+msgid "Chris Cannam"
 msgstr ""
 
-#: audio_diskstream.cc:1585
-msgid "AudioDiskstream: could not create region for captured audio!"
+#: about.cc:134
+msgid "Jeremy Carter"
 msgstr ""
 
-#: audio_diskstream.cc:1693
-msgid "programmer error: %1"
-msgstr "程序错误: %1"
+#: about.cc:135
+msgid "Jesse Chappell"
+msgstr ""
 
-#: audio_diskstream.cc:1921
-msgid "AudioDiskstream: channel %1 out of range"
-msgstr "音频磁盘流: 声道 %1 超出范围"
+#: about.cc:136
+msgid "Thomas Charbonnel"
+msgstr ""
 
-#: audio_diskstream.cc:1935 midi_diskstream.cc:1274
-msgid "%1:%2 new capture file not initialized correctly"
+#: about.cc:137
+msgid "Sam Chessman"
 msgstr ""
 
-#: audio_diskstream.cc:2214
-msgid "%1: cannot restore pending capture source file %2"
+#: about.cc:138
+msgid "André Colomb"
 msgstr ""
 
-#: audio_diskstream.cc:2236
-msgid "%1: incorrect number of pending sources listed - ignoring them all"
+#: about.cc:139
+msgid "Paul Davis"
 msgstr ""
 
-#: audio_diskstream.cc:2270
-msgid "%1: cannot create whole-file region from pending capture sources"
+#: about.cc:140
+msgid "Gerard van Dongen"
 msgstr ""
 
-#: audio_library.cc:81
-msgid "Could not open %1.  Audio Library not saved"
-msgstr "无法打开 %1. 音频库未保存"
+#: about.cc:141
+msgid "John Emmas"
+msgstr ""
 
-#: audio_playlist.cc:504
-msgid ""
-"Legacy crossfade involved an incoming region not present in playlist \"%1\" "
-"- crossfade discarded"
+#: about.cc:142
+msgid "Colin Fletcher"
 msgstr ""
 
-#: audio_playlist.cc:520
-msgid ""
-"Legacy crossfade involved an outgoing region not present in playlist \"%1\" "
-"- crossfade discarded"
+#: about.cc:143
+msgid "Dave Flick"
 msgstr ""
 
-#: audio_playlist_importer.cc:68
-msgid "Audio Playlists"
-msgstr "音频播放列表"
+#: about.cc:144
+msgid "Hans Fugal"
+msgstr ""
 
-#: audio_playlist_importer.cc:161
-msgid "region"
+#: about.cc:145
+msgid "Robin Gareus"
 msgstr ""
 
-#: audio_playlist_importer.cc:163
-msgid "regions"
+#: about.cc:146
+msgid "Christopher George"
 msgstr ""
 
-#: audio_playlist_importer.cc:174 audio_track_importer.cc:244
-msgid "A playlist with this name already exists, please rename it."
-msgstr "此名称的播放列表已存在,请重命名"
+#: about.cc:147
+msgid "Chris Goddard"
+msgstr ""
 
-#: audio_playlist_importer.cc:183
-msgid "badly-formed XML in imported playlist"
+#: about.cc:148
+msgid "J. Abelardo Gutierrez"
 msgstr ""
 
-#: audio_playlist_importer.cc:267
-msgid "Audio Playlists (unused)"
-msgstr "音频播放列表(未使用)"
+#: about.cc:149
+msgid "Jeremy Hall"
+msgstr ""
 
-#: audio_playlist_source.cc:171 audiosource.cc:963 midi_playlist_source.cc:147
-#: midi_playlist_source.cc:155 midi_playlist_source.cc:162 midi_source.cc:356
-#: plugin_insert.cc:641 rb_effect.cc:327 session.cc:2845 session.cc:2878
-#: session.cc:4124 session_handle.cc:87 sndfilesource.cc:154
-msgid "programming error: %1"
-msgstr "程序错误: %1"
+#: about.cc:150
+msgid "Audun Halland"
+msgstr ""
 
-#: audio_region_importer.cc:75
-msgid "Audio Regions"
-msgstr "音频区域"
+#: about.cc:151
+msgid "David Halter"
+msgstr ""
 
-#: audio_region_importer.cc:145
-msgid "Length: "
-msgstr "长度:"
+#: about.cc:152
+msgid "Steve Harris"
+msgstr ""
 
-#: audio_region_importer.cc:147
-msgid ""
-"\n"
-"Position: "
+#: about.cc:153
+msgid "Melvin Ray Herr"
 msgstr ""
-"\n"
-"位置:"
 
-#: audio_region_importer.cc:149
-msgid ""
-"\n"
-"Channels: "
+#: about.cc:154
+msgid "Carl Hetherington"
 msgstr ""
-"\n"
-"声道:"
 
-#: audio_track.cc:161
-msgid "Unknown bundle \"%1\" listed for input of %2"
+#: about.cc:155
+msgid "Rob Holland"
 msgstr ""
 
-#: audio_track.cc:163
-msgid "in 1"
+#: about.cc:156
+msgid "Robert Jordens"
 msgstr ""
 
-#: audio_track.cc:164
-msgid "No input bundles available as a replacement"
+#: about.cc:157
+msgid "Stefan Kersten"
 msgstr ""
 
-#: audio_track.cc:168
-msgid "Bundle %1 was not available - \"in 1\" used instead"
+#: about.cc:158
+msgid "Armand Klenk"
 msgstr ""
 
-#: audio_track.cc:177
-msgid "improper input channel list in XML node (%1)"
+#: about.cc:159
+msgid "Julien de Kozak"
 msgstr ""
 
-#: audio_track_importer.cc:68
-msgid "Audio Tracks"
-msgstr "音频音轨"
+#: about.cc:160
+msgid "Matt Krai"
+msgstr ""
 
-#: audio_track_importer.cc:253 audio_track_importer.cc:259
-msgid "badly-formed XML in imported track"
+#: about.cc:161
+msgid "Georg Krause"
 msgstr ""
 
-#: audio_track_importer.cc:287
-msgid "Error Importing Audio track %1"
+#: about.cc:162
+msgid "Nick Lanham"
 msgstr ""
 
-#: audioanalyser.cc:50
-msgid "cannot load VAMP plugin \"%1\""
-msgstr "无法载入VAMP插件 \"%1\""
+#: about.cc:163
+msgid "Colin Law"
+msgstr ""
 
-#: audioanalyser.cc:70
-msgid "VAMP Plugin \"%1\" could not be loaded"
-msgstr "无法载入VAMP插件 \"%1\""
+#: about.cc:164
+msgid "Joshua Leach"
+msgstr ""
 
-#: audioengine.cc:696
-msgid "AudioEngine: cannot load module \"%1\" (%2)"
+#: about.cc:165
+msgid "Ben Loftis"
 msgstr ""
 
-#: audioengine.cc:702
-msgid "AudioEngine: backend at \"%1\" has no descriptor function."
+#: about.cc:166
+msgid "Nick Mainsbridge"
 msgstr ""
 
-#: audioengine.cc:779
-msgid "Could not create backend for %1: %2"
+#: about.cc:167
+msgid "Tim Mayberry"
 msgstr ""
 
-#: audioregion.cc:1685
-msgid ""
-"You have requested an operation that requires audio analysis.\n"
-"\n"
-"You currently have \"auto-analyse-audio\" disabled, which means that "
-"transient data must be generated every time it is required.\n"
-"\n"
-"If you are doing work that will require transient data on a regular basis, "
-"you should probably enable \"auto-analyse-audio\" then quit %1 and restart.\n"
-"\n"
-"This dialog will not display again.  But you may notice a slight delay in "
-"this and future transient-detection operations.\n"
+#: about.cc:168
+msgid "Doug Mclain"
 msgstr ""
 
-#: audioregion.cc:1729
-msgid "Audio Region"
+#: about.cc:169
+msgid "Todd Naugle"
 msgstr ""
 
-#: audiosource.cc:228
-msgid "cannot rename peakfile for %1 from %2 to %3 (%4)"
-msgstr "无法为 %1 重命名峰文件(peakfile), 从 %2 到 %3 (%4)"
+#: about.cc:170
+msgid "Jack O'Quin"
+msgstr ""
 
-#: audiosource.cc:257
-msgid "AudioSource: cannot stat peakfile \"%1\""
+#: about.cc:171
+msgid "Nimal Ratnayake"
 msgstr ""
 
-#: audiosource.cc:361
-msgid "Cannot open peakfile @ %1 for reading (%2)"
+#: about.cc:172
+msgid "David Robillard"
 msgstr ""
 
-#: audiosource.cc:394
-msgid "cannot read sample data for unscaled peak computation"
-msgstr "无法为无标度的峰计算读取采样数据"
+#: about.cc:173
+msgid "Taybin Rutkin"
+msgstr ""
 
-#: audiosource.cc:430 audiosource.cc:525
-msgid "map failed - could not create file mapping for peakfile %1."
+#: about.cc:174
+msgid "Andreas Ruge"
 msgstr ""
 
-#: audiosource.cc:436 audiosource.cc:531
-msgid "map failed - could not map peakfile %1."
+#: about.cc:175
+msgid "Sampo Savolainen"
 msgstr ""
 
-#: audiosource.cc:447 audiosource.cc:542
-msgid "unmap failed - could not unmap peakfile %1."
+#: about.cc:176
+msgid "Rodrigo Severo"
 msgstr ""
 
-#: audiosource.cc:453 audiosource.cc:548
-msgid "map failed - could not mmap peakfile %1."
+#: about.cc:177
+msgid "Per Sigmond"
 msgstr ""
 
-#: audiosource.cc:638
-msgid ""
-"AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"
+#: about.cc:178
+msgid "Lincoln Spiteri"
 msgstr ""
 
-#: audiosource.cc:705
-msgid "%1: could not write read raw data for peak computation (%2)"
+#: about.cc:179
+msgid "Mike Start"
 msgstr ""
 
-#: audiosource.cc:742
-msgid "AudioSource: cannot open peakpath (c) \"%1\" (%2)"
+#: about.cc:180
+msgid "Mark Stewart"
 msgstr ""
 
-#: audiosource.cc:811 audiosource.cc:933
-msgid "%1: could not seek in peak file data (%2)"
+#: about.cc:181
+msgid "Roland Stigge"
 msgstr ""
 
-#: audiosource.cc:816 audiosource.cc:942
-msgid "%1: could not write peak file data (%2)"
+#: about.cc:182
+msgid "Petter Sundlöf"
 msgstr ""
 
-#: audiosource.cc:975
-msgid "could not truncate peakfile %1 to %2 (error: %3)"
+#: about.cc:183
+msgid "Mike Täht"
 msgstr ""
 
-#: auditioner.cc:100
-msgid "Falling back to Reasonable Synth for Midi Audition"
+#: about.cc:184
+msgid "Roy Vegard"
 msgstr ""
 
-#: auditioner.cc:102
-msgid "No synth for midi-audition found."
+#: about.cc:185
+msgid "Thorsten Wilms"
 msgstr ""
 
-#: auditioner.cc:158
-msgid "no outputs available for auditioner - manual connection required"
+#: about.cc:186
+msgid "Grygorii Zharun"
 msgstr ""
 
-#: auditioner.cc:399 auditioner.cc:446
-msgid "Cannot setup auditioner processing flow for %1 channels"
+#: about.cc:191
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel at free.fr>\n"
+"\tChristophe Combelles <ccomb at free.fr>\n"
+"\tMartin Blanchard\n"
+"\tRomain Arnaud <roming22 at gmail.com>\n"
+msgstr ""
+"法语:\n"
+"\tAlain Fréhel <alain.frehel at free.fr>\n"
+"\tChristophe Combelles <ccomb at free.fr>\n"
+"\tMartin Blanchard\n"
+"\tRomain Arnaud <roming22 at gmail.com>\n"
+
+#: about.cc:192
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet at kapet.de>\n"
+"\tSebastian Arnold <mail at sebastian-arnold.net>\n"
+"\tRobert Schwede <schwede at ironshark.com>\n"
+"\tBenjamin Scherrer <realhangman at web.de>\n"
+"\tEdgar Aichinger <edogawa at aon.at>\n"
+"\tRichard Oax <richard at pagliacciempire.de>\n"
+"\tRobin Gloster <robin at loc-com.de>\n"
+msgstr ""
+"德语:\n"
+"\tKarsten Petersen <kapet at kapet.de>\n"
+"\tSebastian Arnold <mail at sebastian-arnold.net>\n"
+"\tRobert Schwede <schwede at ironshark.com>\n"
+"\tBenjamin Scherrer <realhangman at web.de>\n"
+"\tEdgar Aichinger <edogawa at aon.at>\n"
+"\tRichard Oax <richard at pagliacciempire.de>\n"
+"\tRobin Gloster <robin at loc-com.de>\n"
+
+#: about.cc:199
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo at email.it>\n"
+"\tRaffaele Morelli <raffaele.morelli at gmail.com>\n"
 msgstr ""
+"意大利语:\n"
+"\tFilippo Pappalardo <filippo at email.it>\n"
+"\tRaffaele Morelli <raffaele.morelli at gmail.com>\n"
 
-#: auditioner.cc:434
-msgid "Failed to load synth for MIDI-Audition."
+#: about.cc:200
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc at rncbc.org>\n"
 msgstr ""
+"葡萄牙语:\n"
+"\tRui Nuno Capela <rncbc at rncbc.org>\n"
 
-#: auditioner.cc:453
-msgid "Auditioning of regions other than Audio or Midi is not supported."
+#: about.cc:201
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
+"\tChris Ross <chris at tebibyte.org>\n"
 msgstr ""
+"巴西葡萄牙语:\n"
+"\tAlexander da Franca Fernandes <alexander at nautae.eti.br>\n"
+"\tChris Ross <chris at tebibyte.org>\n"
 
-#: automatable.cc:84
-msgid "Automation node has no path property"
+#: about.cc:203
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn at fastmail.fm>\n"
+"\tPablo Fernández <pablo.fbus at gmail.com>\n"
 msgstr ""
+"西班牙语:\n"
+"\t Alex Krohn <alexkrohn at fastmail.fm>\n"
+"\tPablo Fernández <pablo.fbus at gmail.com>\n"
 
-#: automatable.cc:104
-msgid "cannot open %2 to load automation data (%3)"
+#: about.cc:204
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop at nm.ru>\n"
+"\tAlexandre Prokoudine <alexandre.prokoudine at gmail.com>\n"
 msgstr ""
+"俄语:\n"
+"\t Igor Blinov <pitstop at nm.ru>\n"
+"\tAlexandre Prokoudine <alexandre.prokoudine at gmail.com>\n"
 
-#: automatable.cc:132
-msgid "cannot load automation data from %2"
-msgstr "无法从 %2 载入自动数据"
+#: about.cc:206
+msgid ""
+"Greek:\n"
+"\t Klearchos Gourgourinis <muadib at in.gr>\n"
+msgstr ""
+"希腊语:\n"
+"\t Klearchos Gourgourinis <muadib at in.gr>\n"
 
-#: automatable.cc:167
-msgid "Mute"
+#: about.cc:207
+msgid ""
+"Swedish:\n"
+"\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
 msgstr ""
+"瑞典语:\n"
+"\t Petter Sundlöf <petter.sundlof at gmail.com>\n"
 
-#: automation_list.cc:356
-msgid "automation list: cannot load coordinates from XML, all points ignored"
+#: about.cc:208
+msgid ""
+"Polish:\n"
+"\t Piotr Zaryk <pzaryk at gmail.com>\n"
 msgstr ""
+"波兰语:\n"
+"\t Piotr Zaryk <pzaryk at gmail.com>\n"
 
-#: automation_list.cc:402
+#: about.cc:209
 msgid ""
-"automation list: no x-coordinate stored for control point (point ignored)"
+"Czech:\n"
+"\t Pavel Fric <pavelfric at seznam.cz>\n"
 msgstr ""
+"捷克语:\n"
+"\t Pavel Fric <pavelfric at seznam.cz>\n"
 
-#: automation_list.cc:408
+#: about.cc:210
 msgid ""
-"automation list: no y-coordinate stored for control point (point ignored)"
+"Norwegian:\n"
+"\t Eivind Ødegård\n"
 msgstr ""
+"挪威语:\n"
+"\t Eivind Ødegård\n"
 
-#: automation_list.cc:422
+#: about.cc:211
 msgid ""
-"AutomationList: passed XML node called %1, not \"AutomationList\" - ignored"
+"Chinese:\n"
+"\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
 msgstr ""
+"汉语:\n"
+"\t Rui-huai Zhang <zrhzrh at mail.ustc.edu.cn>\n"
 
-#: butler.cc:100
-msgid "Session: could not create butler thread"
-msgstr "会话:无法创建管家线程"
+#: about.cc:591
+msgid "Copyright (C) 1999-2015 Paul Davis\n"
+msgstr "版权所有 (C) 1999-2015 Paul Davis\n"
 
-#: butler.cc:222 butler.cc:223
-msgid "Butler read ahead failure on dstream %1"
+#: about.cc:595
+msgid "http://ardour.org/"
 msgstr ""
 
-#: butler.cc:270 butler.cc:271
-msgid "Butler write-behind failure on dstream %1"
+#: about.cc:596
+msgid ""
+"%1%2\n"
+"(built from revision %3)"
 msgstr ""
+"%1%2\n"
+"(修订自版本 %3)"
 
-#: control_protocol_manager.cc:164
-msgid "control protocol name \"%1\" has no descriptor"
-msgstr "控制协议名称 \"%1\" 没有描述符"
+#: about.cc:600
+msgid "Config"
+msgstr "配置"
 
-#: control_protocol_manager.cc:171
-msgid "control protocol name \"%1\" could not be initialized"
-msgstr "控制协议名称 \"%1\" 无法初始化"
+#: actions.cc:85
+msgid "Loading menus from %1"
+msgstr "正在载入菜单 %1"
 
-#: control_protocol_manager.cc:237
-msgid "Instantiating mandatory control protocol %1"
-msgstr "实例强制性控制协议 %1"
+#: actions.cc:88 actions.cc:89
+msgid "badly formatted menu definition file: %1"
+msgstr "带有错误格式的菜单定义文件: %1"
 
-#: control_protocol_manager.cc:281
-msgid "looking for control protocols in %1\n"
-msgstr ""
+#: actions.cc:91
+msgid "%1 menu definition file not found"
+msgstr "%1 菜单定义文件未找到"
 
-#: control_protocol_manager.cc:306
-msgid "Control protocol %1 not usable"
-msgstr ""
+#: actions.cc:95 actions.cc:96
+msgid "%1 will not work without a valid menu definition file"
+msgstr "缺失有效的菜单定义文件将导致 %1 无法工作。"
 
-#: control_protocol_manager.cc:323
-msgid "Control surface protocol discovered: \"%1\"\n"
-msgstr ""
+#: add_route_dialog.cc:54 route_params_ui.cc:524
+msgid "Add Track or Bus"
+msgstr "添加音轨或总线"
 
-#: control_protocol_manager.cc:341
-msgid "ControlProtocolManager: cannot load module \"%1\" (%2)"
-msgstr ""
+#: add_route_dialog.cc:57
+msgid "Configuration:"
+msgstr "配置:"
 
-#: control_protocol_manager.cc:347
-msgid "ControlProtocolManager: module \"%1\" has no descriptor function."
-msgstr "控制协议管理器: 模块 \"%1\" 没有描述符函数"
+#: add_route_dialog.cc:58
+msgid "Record Mode:"
+msgstr "录制模式:"
 
-#: cycle_timer.cc:40
-msgid "CycleTimer::get_mhz(): can't open /proc/cpuinfo"
-msgstr ""
+#: add_route_dialog.cc:59
+msgid "Instrument:"
+msgstr "乐器:"
 
-#: cycle_timer.cc:52
-msgid "CycleTimer::get_mhz(): cannot locate cpu MHz in /proc/cpuinfo"
-msgstr ""
+#: add_route_dialog.cc:77
+msgid "Audio Tracks"
+msgstr "音频轨道"
 
-#: cycle_timer.cc:75
-msgid "cannot locate cpu MHz in /proc/cpuinfo"
-msgstr ""
+#: add_route_dialog.cc:78 add_route_dialog.cc:209
+msgid "MIDI Tracks"
+msgstr "MIDI 轨道"
 
-#: data_type.cc:27
-msgid "audio"
+#: add_route_dialog.cc:79 add_route_dialog.cc:211
+msgid "Audio+MIDI Tracks"
+msgstr "音频+MIDI 轨道"
+
+#: add_route_dialog.cc:80 add_route_dialog.cc:207
+msgid "Busses"
+msgstr "总线"
+
+#: add_route_dialog.cc:83 add_route_dialog.cc:559
+msgid "First"
+msgstr "起始点"
+
+#: add_route_dialog.cc:84 add_route_dialog.cc:561
+msgid "After Editor Selection"
+msgstr "在编辑器已选择部分之后"
+
+#: add_route_dialog.cc:85 add_route_dialog.cc:563
+msgid "After Mixer Selection"
+msgstr "在混音器已选择部分之后"
+
+#: add_route_dialog.cc:86
+msgid "Last"
+msgstr "结束点"
+
+#: add_route_dialog.cc:103
+msgid "Add:"
+msgstr "添加:"
+
+#: add_route_dialog.cc:116 time_fx_dialog.cc:91 add_video_dialog.cc:135
+#: video_server_dialog.cc:121
+msgid "<b>Options</b>"
+msgstr "<b>选项</b>"
+
+#: add_route_dialog.cc:126 bundle_manager.cc:193 region_editor.cc:50
+#: route_group_dialog.cc:71
+msgid "Name:"
+msgstr "名称:"
+
+#: add_route_dialog.cc:156
+msgid "Group:"
+msgstr "分组:"
+
+#: add_route_dialog.cc:162
+msgid "Insert:"
+msgstr "插入:"
+
+#: add_route_dialog.cc:223 add_route_dialog.cc:232 add_route_dialog.cc:306
+#: ardour_ui_ed.cc:539 engine_dialog.cc:237 rc_option_editor.cc:1805
+#: rc_option_editor.cc:1807 rc_option_editor.cc:1809 rc_option_editor.cc:1827
+#: rc_option_editor.cc:1829 rc_option_editor.cc:1837 rc_option_editor.cc:1839
+#: rc_option_editor.cc:1857 rc_option_editor.cc:1870 rc_option_editor.cc:1872
+#: rc_option_editor.cc:1874 rc_option_editor.cc:1919 rc_option_editor.cc:1921
+#: rc_option_editor.cc:1923 rc_option_editor.cc:1931 rc_option_editor.cc:1939
+#: rc_option_editor.cc:1941 rc_option_editor.cc:1949
+msgid "Audio"
 msgstr "音频"
 
-#: data_type.cc:28 session.cc:1995 session.cc:1998
+#: add_route_dialog.cc:224 add_route_dialog.cc:235 add_route_dialog.cc:307
+#: editor_actions.cc:109 engine_dialog.cc:239 missing_file_dialog.cc:56
+#: rc_option_editor.cc:2084 rc_option_editor.cc:2094 rc_option_editor.cc:2102
+#: rc_option_editor.cc:2110 rc_option_editor.cc:2119 rc_option_editor.cc:2127
+#: rc_option_editor.cc:2135 rc_option_editor.cc:2143 rc_option_editor.cc:2152
+#: rc_option_editor.cc:2161 rc_option_editor.cc:2170 rc_option_editor.cc:2178
+#: rc_option_editor.cc:2186 rc_option_editor.cc:2194 rc_option_editor.cc:2217
 msgid "MIDI"
 msgstr "MIDI"
 
-#: data_type.cc:29
-msgid "unknown"
-msgstr "未知"
+#: add_route_dialog.cc:225 add_route_dialog.cc:238 add_route_dialog.cc:308
+msgid "Audio+MIDI"
+msgstr "Audio+MIDI"
 
-#: delivery.cc:118
-msgid "main outs"
-msgstr ""
-
-#: delivery.cc:121 send.cc:63
-msgid "listen"
-msgstr ""
+#: add_route_dialog.cc:226 add_route_dialog.cc:241 add_route_dialog.cc:309
+msgid "Bus"
+msgstr "总线"
 
-#: diskstream.cc:309
-msgid "Location \"%1\" not valid for track loop (start >= end)"
+#: add_route_dialog.cc:268
+msgid ""
+"Audio+MIDI tracks are intended for use <b>ONLY</b> with plugins that use both "
+"audio and MIDI input data\n"
+"\n"
+"If you do not plan to use such a plugin, then use a normal audio or MIDI track "
+"instead."
 msgstr ""
+"音频+MIDI 轨道已经准备就绪 ,<b>但仅限于</b> 使用音频和MIDI输入数据的插件。\n"
+"\n"
+"如果您不打算使用这样一个插件,那么请使用普通的音频或MIDI轨道作为替代。"
 
-#: export_channel.cc:110
-msgid "Could not get port for export channel \"%1\", dropping the channel"
-msgstr "无法得到输出声道 \"%1\" 的端口, 丢弃此声道"
-
-#: export_failed.cc:32
-msgid "Export failed: %1"
-msgstr "导出失败: %1"
+#: add_route_dialog.cc:327 add_route_dialog.cc:346 editor_actions.cc:422
+#: editor_rulers.cc:251 time_axis_view.cc:1374
+msgid "Normal"
+msgstr "普通"
 
-#: export_filename.cc:126
-msgid "Existing export folder for this session (%1) does not exist - ignored"
-msgstr ""
+#: add_route_dialog.cc:330 add_route_dialog.cc:348
+msgid "Non Layered"
+msgstr "不分层的"
 
-#: export_filename.cc:242
-msgid "No Time"
-msgstr "没时间"
+#: add_route_dialog.cc:331 add_route_dialog.cc:350
+msgid "Tape"
+msgstr "磁带"
 
-#: export_filename.cc:251
-msgid "Invalid time format"
-msgstr "非法时间格式"
+#: add_route_dialog.cc:431 monitor_section.cc:290
+msgid "Mono"
+msgstr "单声道"
 
-#: export_filename.cc:260
-msgid "No Date"
-msgstr "无日期"
+#: add_route_dialog.cc:435
+msgid "Stereo"
+msgstr "双声道立体声"
 
-#: export_filename.cc:275
-msgid "Invalid date format"
-msgstr "非法日期格式"
+#: add_route_dialog.cc:459
+msgid "3 Channel"
+msgstr "三声道"
 
-#: export_format_manager.cc:57
-msgid "CD"
-msgstr "CD"
+#: add_route_dialog.cc:463
+msgid "4 Channel"
+msgstr "四声道"
 
-#: export_format_manager.cc:66
-msgid "DVD-A"
-msgstr "DVD-A"
+#: add_route_dialog.cc:467
+msgid "5 Channel"
+msgstr "五声道"
 
-#: export_format_manager.cc:80
-msgid "iPod"
-msgstr ""
+#: add_route_dialog.cc:471
+msgid "6 Channel"
+msgstr "六声道"
 
-#: export_format_manager.cc:91
-msgid "Something else"
-msgstr "其他的"
+#: add_route_dialog.cc:475
+msgid "8 Channel"
+msgstr "八声道"
 
-#: export_format_manager.cc:110
-msgid "Any"
-msgstr "任何"
+#: add_route_dialog.cc:479
+msgid "12 Channel"
+msgstr "十二声道"
 
-#: export_format_manager.cc:111
-msgid "Lossless (linear PCM)"
-msgstr "无损的 (线性PCM)"
+#: add_route_dialog.cc:483 mixer_strip.cc:1836 mixer_strip.cc:2244
+msgid "Custom"
+msgstr "自定义"
 
-#: export_format_manager.cc:112
-msgid "Lossy compression"
-msgstr "有损压缩"
+#: add_route_dialog.cc:516 add_route_dialog.cc:532 route_group_menu.cc:81
+msgid "New Group..."
+msgstr "新建群组…"
 
-#: export_format_manager.cc:113
-msgid "Lossless compression"
-msgstr "无损压缩"
+#: add_route_dialog.cc:520 route_group_menu.cc:85
+msgid "No Group"
+msgstr "没有群组"
 
-#: export_format_manager.cc:218 export_format_specification.cc:591
-msgid "Session rate"
-msgstr ""
+#: ambiguous_file_dialog.cc:30
+msgid "Ambiguous File"
+msgstr "模糊的文件"
 
-#: export_format_specification.cc:549
-msgid "normalize"
+#: ambiguous_file_dialog.cc:35
+msgid ""
+"%1 has found the file <i>%2</i> in the following places:\n"
+"\n"
 msgstr ""
+"%1 被发现位于文件 <i>%2</i> 的以下位置:\n"
+"\n"
 
-#: export_format_specification.cc:553
-msgid "trim"
+#: ambiguous_file_dialog.cc:44
+msgid ""
+"\n"
+"\n"
+"Please select the path that you want to get the file from."
 msgstr ""
+"\n"
+"\n"
+"请选择您想获取的文件所在的路径。"
 
-#: export_format_specification.cc:555
-msgid "trim start"
-msgstr ""
+#: ambiguous_file_dialog.cc:46 missing_file_dialog.cc:46
+msgid "Done"
+msgstr "完成"
 
-#: export_format_specification.cc:557
-msgid "trim end"
-msgstr ""
+#: analysis_window.cc:46
+msgid "Signal source"
+msgstr "信号源"
 
-#: export_formats.cc:49
-msgid "Shaped Noise"
-msgstr ""
+#: analysis_window.cc:47
+msgid "Selected ranges"
+msgstr "选择范围"
 
-#: export_formats.cc:50
-msgid "Triangular"
-msgstr "三角形"
+#: analysis_window.cc:48
+msgid "Selected regions"
+msgstr "选择区域"
 
-#: export_formats.cc:51
-msgid "Rectangular"
-msgstr "长方形"
+#: analysis_window.cc:50
+msgid "Display model"
+msgstr "显示模式"
 
-#: export_formats.cc:52 session.cc:5421 session.cc:5437
-msgid "None"
-msgstr ""
+#: analysis_window.cc:51
+msgid "Composite graphs for each track"
+msgstr "每个音轨的合成图"
 
-#: export_formats.cc:159
-msgid "8bit"
-msgstr "8位"
+#: analysis_window.cc:52
+msgid "Composite graph of all tracks"
+msgstr "所有音轨的合成图"
 
-#: export_formats.cc:161
-msgid "16bit"
-msgstr ""
+#: analysis_window.cc:54
+msgid "Show frequency power range"
+msgstr "显示频率的功率范围"
 
-#: export_formats.cc:163
-msgid "24bit"
-msgstr ""
+#: analysis_window.cc:55
+msgid "Normalize values"
+msgstr "规范化数值"
 
-#: export_formats.cc:165
-msgid "32bit"
-msgstr ""
+#: analysis_window.cc:59
+msgid "FFT analysis window"
+msgstr "FFT 快速傅立叶变换分析视窗"
 
-#: export_formats.cc:167
-msgid "float"
-msgstr ""
+#: analysis_window.cc:60 editor.cc:1823
+msgid "Spectral Analysis"
+msgstr "频谱分析"
 
-#: export_formats.cc:169
-msgid "double"
-msgstr "(2:1)(_D"
+#: analysis_window.cc:67 editor_actions.cc:142 export_channel_selector.cc:557
+#: session_metadata_dialog.cc:667
+msgid "Track"
+msgstr "音轨"
 
-#: export_formats.cc:171
-msgid "8bit unsigned"
-msgstr "无标号8位"
+#: analysis_window.cc:68 editor_actions.cc:648 mixer_ui.cc:131 mixer_ui.cc:1854
+msgid "Show"
+msgstr "显示"
 
-#: export_formats.cc:173
-msgid "Vorbis sample format"
-msgstr "Vorbis采样格式"
+#: analysis_window.cc:135
+msgid "Re-analyze data"
+msgstr "重新分析数据"
 
-#: export_formats.cc:175
-msgid "No sample format"
-msgstr "无采样格式"
+#: ardour_button.cc:887
+msgid "button cannot watch state of non-existing Controllable\n"
+msgstr "按钮无法显示不存在的操控状态\n"
 
-#: export_handler.cc:360
-msgid "File %1 uploaded to %2"
-msgstr ""
+#: ardour_button.cc:1155
+msgid "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+msgstr "ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
 
-#: export_handler.cc:366
+#: ardour_ui.cc:164
 msgid ""
-"upload to Soundcloud failed. Perhaps your email or password are incorrect?\n"
+"%1 %2.x has discovered configuration files from %1 %3.x.\n"
+"\n"
+"Would you like to copy the relevant files before starting to use the program?\n"
+"\n"
+"(This will require you to restart %1.)"
 msgstr ""
+"%1 %2.x 发现配置文件来源于 %1 %3.x.\n"
+"\n"
+"在启用这个程序前,您打算复制关联文件吗?\n"
+"\n"
+"(这将需要你重新启动 %1.)"
 
-#: export_handler.cc:413
-msgid "Editor: cannot open \"%1\" as export file for CD marker file"
-msgstr ""
+#: ardour_ui.cc:211 editor_actions.cc:642 region_editor.cc:51
+msgid "Audition"
+msgstr "监听"
 
-#: export_handler.cc:492 export_handler.cc:495
-msgid "an error occured while writing a TOC/CUE file: %1"
-msgstr ""
+#: ardour_ui.cc:212 editor_actions.cc:136 mixer_strip.cc:2016
+#: rc_option_editor.cc:1959 route_time_axis.cc:252 route_time_axis.cc:2711
+msgid "Solo"
+msgstr "独奏"
 
-#: export_handler.cc:744 export_handler.cc:802
-msgid "Cannot convert %1 to Latin-1 text"
-msgstr ""
+#: ardour_ui.cc:213 rc_option_editor.cc:741
+msgid "Feedback"
+msgstr "反馈"
 
-#: export_profile_manager.cc:93
-msgid "Searching for export formats in %1"
-msgstr ""
+#: ardour_ui.cc:219 speaker_dialog.cc:36
+msgid "Speaker Configuration"
+msgstr "扬声器配置"
 
-#: export_profile_manager.cc:99
-msgid "Unable to create export format directory %1: %2"
-msgstr ""
+#: ardour_ui.cc:220 keyeditor.cc:53
+msgid "Key Bindings"
+msgstr "按键绑定"
 
-#: export_profile_manager.cc:262
-msgid "Unable to remove export preset %1: %2"
-msgstr ""
+#: ardour_ui.cc:221
+msgid "Preferences"
+msgstr "首选项"
 
-#: export_profile_manager.cc:351
-msgid "Selection"
-msgstr "选取"
+#: ardour_ui.cc:222 ardour_ui.cc:229
+msgid "Add Tracks/Busses"
+msgstr "添加音轨/总线"
 
-#: export_profile_manager.cc:604
-msgid "Unable to rename export format %1 to %2: %3"
-msgstr ""
+#: ardour_ui.cc:223
+msgid "About"
+msgstr "关于"
 
-#: export_profile_manager.cc:636
-msgid "Unable to remove export profile %1: %2"
-msgstr ""
+#: ardour_ui.cc:224 location_ui.cc:1141 session_option_editor.cc:189
+#: session_option_editor.cc:195 session_option_editor.cc:202
+msgid "Locations"
+msgstr "位置"
 
-#: export_profile_manager.cc:654
-msgid "empty format"
-msgstr ""
+#: ardour_ui.cc:225 route_params_ui.cc:59 route_params_ui.cc:630
+msgid "Tracks and Busses"
+msgstr "音轨和总线"
 
-#: export_profile_manager.cc:735
-msgid "Cannot load export format from %1"
-msgstr ""
+#: ardour_ui.cc:226 engine_dialog.cc:70
+msgid "Audio/MIDI Setup"
+msgstr "音频/MIDI设置"
 
-#: export_profile_manager.cc:741
-msgid "Cannot export format read from %1"
-msgstr ""
+#: ardour_ui.cc:227
+msgid "Video Export Dialog"
+msgstr "视频导出对话框"
 
-#: export_profile_manager.cc:835
-msgid "No timespan has been selected!"
-msgstr ""
+#: ardour_ui.cc:228
+msgid "Properties"
+msgstr "属性"
 
-#: export_profile_manager.cc:839
-msgid "No channels have been selected!"
-msgstr "没有选中任何声道"
+#: ardour_ui.cc:230 bundle_manager.cc:264
+msgid "Bundle Manager"
+msgstr "包裹管理器"
 
-#: export_profile_manager.cc:843
-msgid "Some channels are empty"
-msgstr "一些声道是空的"
+#: ardour_ui.cc:231 big_clock_window.cc:37
+msgid "Big Clock"
+msgstr "Big Clock 大计时器"
 
-#: export_profile_manager.cc:876
-msgid "No format selected!"
-msgstr "没有选中格式!"
+#: ardour_ui.cc:232
+msgid "Audio Connections"
+msgstr "音频连接"
 
-#: export_profile_manager.cc:878
-msgid "All channels are empty!"
-msgstr "所有声道都是空的!"
+#: ardour_ui.cc:233
+msgid "MIDI Connections"
+msgstr "MIDI 连接"
 
-#: export_profile_manager.cc:880
-msgid "One or more of the selected formats is not compatible with this system!"
-msgstr ""
+#: ardour_ui.cc:242
+msgid "Your configuration files were copied. You can now restart %1."
+msgstr "您的配置文件已经备份完成。现在可以重新启动 %1 。"
 
-#: export_profile_manager.cc:883
+#: ardour_ui.cc:481
 msgid ""
-"%1 supports only %2 channels, but you have %3 channels in your channel "
-"configuration"
+"The audio backend was shutdown because:\n"
+"\n"
+"%1"
 msgstr ""
+"音频后端已关闭,因为:\n"
+"\n"
+"%1"
 
-#: file_source.cc:201 session_state.cc:2857
+#: ardour_ui.cc:483
 msgid ""
-"there are already 1000 files with names like %1; versioning discontinued"
+"The audio backend has either been shutdown or it\n"
+"disconnected %1 because %1\n"
+"was not fast enough. Try to restart\n"
+"the audio backend and save the session."
 msgstr ""
+"音频后端要么已经关闭,\n"
+"要么它与 %1 失去了连接,\n"
+"因为 %1不够快。\n"
+"请尝试重新启动音频后端并保存会话。"
 
-#: file_source.cc:210
-msgid "cannot rename file source from %1 to %2 (%3)"
-msgstr ""
+#: ardour_ui.cc:507
+msgid ""
+"Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see "
+"the log window for further details."
+msgstr "音频单元插件扫描失败。自动 AU 扫描已被禁用。详情请参阅日志窗口。"
+
+#: ardour_ui.cc:508
+msgid "Audio Unit Plugin Scan Failed:"
+msgstr "音频单元插件扫描失败:"
+
+# NSM (network service manager)
+#: ardour_ui.cc:827
+msgid "NSM server did not announce itself"
+msgstr "NSM服务器没有表明身份"
 
-#: file_source.cc:251 file_source.cc:375
-msgid "FileSource: search path not set"
-msgstr "文件源: 没设置搜索路径"
+#: ardour_ui.cc:840
+msgid "NSM: no client ID provided"
+msgstr "NSM:没有提供客户机识别号"
 
-#: file_source.cc:435
+#: ardour_ui.cc:847
+msgid "NSM: no session created"
+msgstr "NSM:没有已创建的会话"
+
+#: ardour_ui.cc:870
+msgid "NSM: initialization failed"
+msgstr "NSM:初始化失败"
+
+#: ardour_ui.cc:900
+msgid "Free/Demo Version Warning"
+msgstr "免费/演示版本的警告"
+
+#: ardour_ui.cc:902
+msgid "Subscribe and support development of %1"
+msgstr "订阅和支持发展 %1"
+
+#: ardour_ui.cc:903
+msgid "Don't warn me about this again"
+msgstr "不再提醒我这个"
+
+#: ardour_ui.cc:905
 msgid ""
-"FileSource: \"%1\" is ambigous when searching\n"
-"\t"
+"<span weight=\"bold\" size=\"large\">%1</span>\n"
+"\n"
+"<b>%2</b>\n"
+"\n"
+"<i>%3</i>\n"
+"\n"
+"%4"
 msgstr ""
+"<span weight=\"bold\" size=\"large\">%1</span>\n"
+"\n"
+"<b>%2</b>\n"
+"\n"
+"<i>%3</i>\n"
+"\n"
+"%4"
 
-#: file_source.cc:442
-msgid "Filesource: cannot find required file (%1)"
-msgstr ""
+#: ardour_ui.cc:906
+msgid "This is a free/demo version of %1"
+msgstr "这是一个免费/演示版本 %1"
 
-#: file_source.cc:487
-msgid "Filesource: cannot find required file (%1): %2"
-msgstr "文件源: 无法找到要求的文件 (%1): %2"
+#: ardour_ui.cc:907
+msgid "It will not restore OR save any plugin settings"
+msgstr "它不会恢复或保存任何插件设置"
 
-#: file_source.cc:495
-msgid "Filesource: cannot check for existing file (%1): %2"
+#: ardour_ui.cc:908
+msgid ""
+"If you load an existing session with plugin settings\n"
+"they will not be used and will be lost."
 msgstr ""
+"如果您载入一个带有插件设置的已存在的会话\n"
+"它们将不会被采用并将会被丢失。"
 
-#: file_source.cc:589
+#: ardour_ui.cc:910 plugin_ui.cc:569
 msgid ""
-"Programming error! %1 tried to rename a file over another file! It's safe to "
-"continue working, but please report this to the developers."
+"To get full access to updates without this limitation\n"
+"consider becoming a subscriber for a low cost every month."
 msgstr ""
+"为了不受这个限制地升级而得到完整使用权,\n"
+"请考虑以每月极低的成本而成为一个用户。"
 
-#: file_source.cc:596
-msgid "cannot rename file %1 to %2 (%3)"
-msgstr "无法重命名文件 %1 到 %2 (%3)"
+#: ardour_ui.cc:920
+msgid "Quit now"
+msgstr "立即退出"
 
-#: filesystem_paths.cc:105
-msgid "Cannot create Configuration directory %1 - cannot run"
-msgstr ""
+#: ardour_ui.cc:921
+msgid "Continue using %1"
+msgstr "继续使用 %1"
 
-#: filesystem_paths.cc:110
+#: ardour_ui.cc:954 startup.cc:345
+msgid "%1 is ready for use"
+msgstr "%1 准备就绪"
+
+#: ardour_ui.cc:996
 msgid ""
-"Configuration directory %1 already exists and is not a directory/folder - "
-"cannot run"
+"WARNING: Your system has a limit for maximum amount of locked memory. This might "
+"cause %1 to run out of memory before your system runs out of memory. \n"
+"\n"
+"You can view the memory limit with 'ulimit -l', and it is normally controlled by %2"
 msgstr ""
+"警告:您的系统有对于锁定内存的最大数量限制。这可能会在您的系统耗尽内存之前,首先导"
+"致 %1 无内存可用。\n"
+"\n"
+"您可以使用“ulimit -l”命令来查看内存限制,通常它由 %2 来控制。"
 
-#: filesystem_paths.cc:171
-msgid "Cannot create cache directory %1 - cannot run"
-msgstr ""
+#: ardour_ui.cc:1013
+msgid "Do not show this window again"
+msgstr "不再显示此窗口"
+
+#: ardour_ui.cc:1057
+msgid "Don't quit"
+msgstr "不退出"
+
+#: ardour_ui.cc:1058
+msgid "Just quit"
+msgstr "不保存而退出"
 
-#: filesystem_paths.cc:176
+#: ardour_ui.cc:1059
+msgid "Save and quit"
+msgstr "保存并退出"
+
+#: ardour_ui.cc:1069
 msgid ""
-"Cache directory %1 already exists and is not a directory/folder - cannot run"
+"%1 was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
 msgstr ""
+"%1 无法保存您的会话。\n"
+"\n"
+"如果您仍打算退出,\n"
+"\n"
+"请启用“不保存而退出”选项。"
 
-#: filesystem_paths.cc:194
-msgid "ARDOUR_DLL_PATH not set in environment - exiting\n"
-msgstr ""
+#: ardour_ui.cc:1119
+msgid "Unsaved Session"
+msgstr " 尚未保存的会话"
 
-#: filesystem_paths.cc:245
-msgid "ARDOUR_CONFIG_PATH not set in environment\n"
+#: ardour_ui.cc:1140
+msgid ""
+"The session \"%1\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
 msgstr ""
+"此会话 \"%1\" 尚未保存.\n"
+"\n"
+"刚才所作的修改将会丢失\n"
+"除非您保存它。\n"
+"\n"
+"您打算如何做?"
 
-#: filesystem_paths.cc:266
-msgid "ARDOUR_DATA_PATH not set in environment\n"
+#: ardour_ui.cc:1143
+msgid ""
+"The snapshot \"%1\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
 msgstr ""
+"此快照 \"%1\" 尚未保存。\n"
+"\n"
+"刚才所作的修改将会丢失\n"
+"除非您保存它。\n"
+"\n"
+"您打算如何做?"
 
-#: filter.cc:67
-msgid "filter: error creating name for new file based on %1"
-msgstr ""
+#: ardour_ui.cc:1157
+msgid "Prompter"
+msgstr "提词机"
 
-#: filter.cc:79
-msgid "filter: error creating new file %1 (%2)"
-msgstr ""
+#: ardour_ui.cc:1269 ardour_ui.cc:1277
+msgid "Audio: <span foreground=\"red\">none</span>"
+msgstr "音频:<span foreground=\"red\">无</span>"
 
-#: find_session.cc:59
-msgid "cannot check session path %1 (%2)"
-msgstr "无法检查会话路径 %1 (%2)"
+#: ardour_ui.cc:1281
+#, c-format
+msgid "Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"
+msgstr "音频: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"
 
-#: find_session.cc:85
-msgid "cannot check statefile %1 (%2)"
-msgstr ""
+#: ardour_ui.cc:1285
+#, c-format
+msgid "Audio: <span foreground=\"green\">%<PRId64> kHz / %4.1f ms</span>"
+msgstr "音频:<span foreground=\"green\">%<PRId64> kHz / %4.1f ms</span>"
 
-#: find_session.cc:121
-msgid "%1 is not a snapshot file"
-msgstr "%1 不是一个快照文件"
+#: ardour_ui.cc:1303 export_video_dialog.cc:80
+msgid "File:"
+msgstr "文件:"
 
-#: find_session.cc:138
-msgid "cannot determine current working directory (%1)"
+#: ardour_ui.cc:1307
+msgid "BWF"
 msgstr ""
 
-#: find_session.cc:155
-msgid "unknown file type for session %1"
+#: ardour_ui.cc:1310
+msgid "WAV"
 msgstr ""
 
-#: globals.cc:234
-msgid "Could not set system open files limit to \"unlimited\""
+#: ardour_ui.cc:1313
+msgid "WAV64"
 msgstr ""
 
-#: globals.cc:236
-msgid "Could not set system open files limit to %1"
+#: ardour_ui.cc:1316 session_option_editor.cc:185
+msgid "CAF"
 msgstr ""
 
-#: globals.cc:240
-msgid "Your system is configured to limit %1 to only %2 open files"
+#: ardour_ui.cc:1319
+msgid "AIFF"
 msgstr ""
 
-#: globals.cc:244
-msgid "Could not get system open files limit (%1)"
+#: ardour_ui.cc:1322
+msgid "iXML"
 msgstr ""
 
-#: globals.cc:415
-msgid "Loading configuration"
-msgstr "载入配置"
-
-#: import.cc:146
-msgid "Cannot find new filename for imported file %1"
+#: ardour_ui.cc:1325
+msgid "RF64"
 msgstr ""
 
-#: import.cc:166
-msgid "Could not find a source for %1 even though we are updating this file!"
+#: ardour_ui.cc:1333
+msgid "32-float"
 msgstr ""
 
-#: import.cc:195
-msgid "Unable to create file %1 during import"
-msgstr "在导入期间无法创建文件 %1"
+#: ardour_ui.cc:1336
+msgid "24-int"
+msgstr ""
 
-#: import.cc:221
-msgid "Resampling %1 from %2kHz to %3kHz"
+#: ardour_ui.cc:1339
+msgid "16-int"
 msgstr ""
 
-#: import.cc:227
-msgid "Copying %1"
-msgstr "复制 %1 中"
+# DSP 数字信号处理器(Digital Signal Processor)
+#: ardour_ui.cc:1358
+#, c-format
+msgid "DSP: <span foreground=\"%s\">%5.1f%%</span>"
+msgstr "数字信号处理器: <span foreground=\"%s\">%5.1f%%</span>"
 
-#: import.cc:420
-msgid "Track %1 of %2 contained no usable MIDI data"
+#: ardour_ui.cc:1377
+#, c-format
+msgid ""
+"Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span> <span foreground=\"green\">c:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span>"
 msgstr ""
+"缓冲区: <span foreground=\"green\">p:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span> <span foreground=\"green\">c:</span><span foreground=\"%s\">%<PRIu32>%%</"
+"span>"
 
-#: import.cc:427
-msgid "MIDI file %1 was not readable (no reason available)"
-msgstr ""
+#: ardour_ui.cc:1418
+msgid "Disk: <span foreground=\"green\">Unknown</span>"
+msgstr "硬盘: <span foreground=\"green\">Unknown</span>"
 
-#: import.cc:475
-msgid "Import: cannot open input sound file \"%1\""
-msgstr ""
+#: ardour_ui.cc:1420
+msgid "Disk: <span foreground=\"green\">24hrs+</span>"
+msgstr "硬盘:<span foreground=\"green\">24hrs+</span>"
 
-#: import.cc:486
-msgid "Import: error opening MIDI file"
-msgstr "导入: 错误打开MIDI文件"
+#: ardour_ui.cc:1438
+msgid "Disk: <span foreground=\"green\">>24 hrs</span>"
+msgstr "硬盘:<span foreground=\"green\">>24 hrs</span>"
 
-#: import.cc:493
-msgid "Import: file contains no channels."
-msgstr ""
+#: ardour_ui.cc:1449
+#, c-format
+msgid "Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"
+msgstr "硬盘:<span foreground=\"%s\">%02dh:%02dm:%02ds</span>"
 
-#: import.cc:527
-msgid "Loading MIDI file %1"
-msgstr "载入MIDI文件 %1"
+#: ardour_ui.cc:1475
+#, c-format
+msgid "Timecode|TC: <span foreground=\"%s\">%s</span>"
+msgstr "时间码|TC:<span foreground=\"%s\">%s</span>"
 
-#: import.cc:592
-msgid "Failed to remove some files after failed/cancelled import operation"
-msgstr ""
+#: ardour_ui.cc:1596 ardour_ui.cc:1605 session_dialog.cc:318 session_dialog.cc:323
+msgid "Recent Sessions"
+msgstr "最近的会话"
 
-#: instrument_info.cc:41 instrument_info.cc:62
-msgid "Unknown"
+#: ardour_ui.cc:1684
+msgid ""
+"%1 is not connected to any audio backend.\n"
+"You cannot open or close sessions in this condition"
 msgstr ""
+"%1 没有连接到任何音频后端。\n"
+"在这种情况下您不能打开或关闭会话"
 
-#: instrument_info.cc:231
-msgid "preset %1 (bank %2)"
-msgstr ""
+#: ardour_ui.cc:1708
+msgid "Open Session"
+msgstr "打开会话"
+
+#: ardour_ui.cc:1733 session_dialog.cc:349 session_import_dialog.cc:170
+#: session_metadata_dialog.cc:858
+msgid "%1 sessions"
+msgstr "%1 会话"
+
+#: ardour_ui.cc:1770
+msgid "You cannot add a track without a session already loaded."
+msgstr "在没有任何一个会话被载入之前,您不能添加音轨。"
+
+#: ardour_ui.cc:1778
+msgid "could not create %1 new mixed track"
+msgid_plural "could not create %1 new mixed tracks"
+msgstr[0] "无法创建 %1 新的混音轨道"
 
-#: internal_send.cc:316 internal_send.cc:317
-msgid "%1 - cannot find any track/bus with the ID %2 to connect to"
+#: ardour_ui.cc:1784 ardour_ui.cc:1845
+msgid ""
+"There are insufficient ports available\n"
+"to create a new track or bus.\n"
+"You should save %1, exit and\n"
+"restart with more ports."
+msgstr ""
+"没有足够可用的端口\n"
+"去创建一个新的音轨或总线。\n"
+"您应当保存 %1,\n"
+"退出并且带着更多的端口重新启动。"
+
+#: ardour_ui.cc:1819
+msgid "You cannot add a track or bus without a session already loaded."
+msgstr "在没有任何一个会话被载入之前,您不能添加音轨或总线。"
+
+#: ardour_ui.cc:1828
+msgid "could not create %1 new audio track"
+msgid_plural "could not create %1 new audio tracks"
+msgstr[0] "无法创建 %1 新的音频轨道"
+
+#: ardour_ui.cc:1837
+msgid "could not create %1 new audio bus"
+msgid_plural "could not create %1 new audio busses"
+msgstr[0] "无法创建 %1 新的音频总线"
+
+#: ardour_ui.cc:1990
+msgid ""
+"Please create one or more tracks before trying to record.\n"
+"You can do this with the \"Add Track or Bus\" option in the Session menu."
 msgstr ""
+"在录制之前请先创建一条或多条音轨。\n"
+"您可以使用会话菜单中的“添加音轨或总线”选项来实现。"
 
-#: io.cc:209
-msgid "IO: cannot disconnect port %1 from %2"
-msgstr "IO: 无法失去从 %2 的连接端口 %1"
+#: ardour_ui.cc:2376
+msgid "Save as..."
+msgstr "另存为…"
 
-#: io.cc:344 io.cc:431
-msgid "IO: cannot register input port %1"
-msgstr "IO: 无法注册输入端口 %1"
+#: ardour_ui.cc:2377 ardour_ui.cc:2456
+msgid "New session name"
+msgstr "新建快照的名称"
 
-#: io.cc:349 io.cc:436
-msgid "IO: cannot register output port %1"
-msgstr "无法注册输出端口 %1"
+#: ardour_ui.cc:2379
+msgid "Take Snapshot"
+msgstr "生成快照"
 
-#: io.cc:598 io.cc:654
-msgid "incorrect XML node \"%1\" passed to IO object"
-msgstr "不正确的XML符号  \"%1\" 通过IO对象"
+#: ardour_ui.cc:2380
+msgid "Name of new snapshot"
+msgstr "新建快照的名称"
 
-#: io.cc:713
-msgid "in"
+#: ardour_ui.cc:2405
+msgid ""
+"To ensure compatibility with various systems\n"
+"snapshot names may not contain a '%1' character"
 msgstr ""
+"为了确保在不同系统间的兼容性\n"
+"快照名称不能包含' % 1 '字符"
 
-#: io.cc:713
-msgid "out"
-msgstr ""
+#: ardour_ui.cc:2417
+msgid "Confirm Snapshot Overwrite"
+msgstr "确定覆盖快照"
 
-#: io.cc:714
-msgid "input"
-msgstr "输入"
+#: ardour_ui.cc:2418
+msgid "A snapshot already exists with that name.  Do you want to overwrite it?"
+msgstr "已存在相同名称的快照。您打算覆盖它?"
 
-#: io.cc:714
-msgid "output"
-msgstr "输出"
+#: ardour_ui.cc:2421 utils_videotl.cc:74
+msgid "Overwrite"
+msgstr "覆盖"
 
-#: io.cc:724
-msgid "Unknown bundle \"%1\" listed for %2 of %3"
-msgstr ""
+#: ardour_ui.cc:2455
+msgid "Rename Session"
+msgstr "重命名会话"
 
-#: io.cc:790
-msgid "Bundle %1 was not available - \"%2\" used instead"
+#: ardour_ui.cc:2470 ardour_ui.cc:2886 ardour_ui.cc:2924
+msgid ""
+"To ensure compatibility with various systems\n"
+"session names may not contain a '%1' character"
 msgstr ""
+"为了确保在不同系统间的兼容性\n"
+"会话名称不能包含' % 1 '字符"
 
-#: io.cc:793
-msgid "No %1 bundles available as a replacement"
+#: ardour_ui.cc:2478
+msgid "That name is already in use by another directory/folder. Please try again."
+msgstr "此名称已被另一个目录/文件夹使用。 请再尝试另一个。"
+
+#: ardour_ui.cc:2487
+msgid ""
+"Renaming this session failed.\n"
+"Things could be seriously messed up at this point"
 msgstr ""
+"重命名会话失败.\n"
+"从现在开始事情真的将会变得很麻烦。"
 
-#: io.cc:897
-msgid "%1: cannot create I/O ports"
-msgstr "%1: 无法创建I/O端口"
+#: ardour_ui.cc:2602
+msgid "Save Template"
+msgstr "保存模板..."
 
-#: io.cc:1025 io.cc:1126
-msgid "IO: badly formed string in XML node for inputs \"%1\""
-msgstr ""
+#: ardour_ui.cc:2603
+msgid "Name for template:"
+msgstr "模板名:"
 
-#: io.cc:1030 io.cc:1131
-msgid "bad input string in XML node \"%1\""
-msgstr ""
+#: ardour_ui.cc:2604
+msgid "-template"
+msgstr "-模板"
 
-#: io.cc:1069
-msgid "IO: badly formed string in XML node for outputs \"%1\""
+#: ardour_ui.cc:2643
+msgid ""
+"This session\n"
+"%1\n"
+"already exists. Do you want to open it?"
 msgstr ""
+"会话\n"
+"%1\n"
+"已存在。是否 打开它?"
 
-#: io.cc:1074
-msgid "IO: bad output string in XML node \"%1\""
-msgstr ""
+#: ardour_ui.cc:2653
+msgid "Open Existing Session"
+msgstr "打开已存在的会话"
 
-#: io.cc:1413
-#, c-format
-msgid "%s %u"
-msgstr ""
+#: ardour_ui.cc:2914
+msgid "There is no existing session at \"%1\""
+msgstr "在 \"%1\" 没有会话文件"
 
-#: io.cc:1460
-#, c-format
-msgid "%s in"
-msgstr ""
+#: ardour_ui.cc:3006
+msgid "Please wait while %1 loads your session"
+msgstr "请等待 %1 载入您的会话"
 
-#: io.cc:1462
-#, c-format
-msgid "%s out"
-msgstr ""
+#: ardour_ui.cc:3021
+msgid "Port Registration Error"
+msgstr "端口注册错误"
 
-#: io.cc:1537 session.cc:733 session.cc:767
-msgid "mono"
-msgstr "单声道"
+#: ardour_ui.cc:3022
+msgid "Click the Close button to try again."
+msgstr "请单击关闭按钮,再尝试一遍"
 
-#: io.cc:1539 session.cc:746 session.cc:781
-msgid "L"
-msgstr ""
+#: ardour_ui.cc:3043
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "会话  \"%1 (快照 %2)\" 载入失败"
 
-#: io.cc:1539 session.cc:748 session.cc:783
-msgid "R"
-msgstr ""
+#: ardour_ui.cc:3049
+msgid "Loading Error"
+msgstr "载入错误"
 
-#: io.cc:1541 io.cc:1547
-#, c-format
-msgid "%d"
+#: ardour_ui.cc:3068
+msgid ""
+"This session has been opened in read-only mode.\n"
+"\n"
+"You will not be able to record or save."
 msgstr ""
+"本次会话已经以只读模式打开。\n"
+"\n"
+"您不能录制或者保存。"
 
-#: ladspa_plugin.cc:93
-msgid "LADSPA: Unable to open module: "
-msgstr ""
+#: ardour_ui.cc:3073
+msgid "Read-only Session"
+msgstr "只读会话"
 
-#: ladspa_plugin.cc:99
-msgid "LADSPA: module has no descriptor function."
-msgstr "LADSPA: 模块没有描述符函数."
+#: ardour_ui.cc:3139
+msgid "Could not create session in \"%1\""
+msgstr "在 \"%1\" 无法创建会话"
 
-#: ladspa_plugin.cc:106
-msgid "LADSPA: plugin has gone away since discovery!"
-msgstr "LADSPA: 当发现插件时, 插件已经不见了."
+#: ardour_ui.cc:3288
+msgid "No files were ready for clean-up"
+msgstr "没有可以清空的文件"
 
-#: ladspa_plugin.cc:113
-msgid "LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"
-msgstr ""
+#: ardour_ui.cc:3292 ardour_ui.cc:3302 ardour_ui.cc:3435 ardour_ui.cc:3442
+#: ardour_ui_ed.cc:103
+msgid "Clean-up"
+msgstr "清空"
 
-#: ladspa_plugin.cc:311
+#: ardour_ui.cc:3293
 msgid ""
-"illegal parameter number used with plugin \"%1\". This may indicate a change "
-"in the plugin design, and presets may be invalid"
+"If this seems suprising, \n"
+"check for any existing snapshots.\n"
+"These may still include regions that\n"
+"require some unused files to continue to exist."
 msgstr ""
+"如果这情况看起来有点异常,\n"
+"请检查任何已存在的快照。\n"
+"它们也许仍包括有某些范围\n"
+" 需要继续保留某些未使用的文件。"
 
-#: ladspa_plugin.cc:390 ladspa_plugin.cc:440
-msgid "Bad node sent to LadspaPlugin::set_state"
-msgstr "坏的符号发送至 LadspaPlugin::set_state"
+#: ardour_ui.cc:3352
+msgid "kilo"
+msgstr "千"
 
-#: ladspa_plugin.cc:405 ladspa_plugin.cc:454
-msgid "LADSPA: no ladspa port number"
-msgstr "LADSPA: 没有 ladspa 端口数量"
+#: ardour_ui.cc:3355
+msgid "mega"
+msgstr "兆(百万)"
 
-#: ladspa_plugin.cc:411 ladspa_plugin.cc:460
-msgid "LADSPA: no ladspa port data"
-msgstr "LADSPA: 没有LADSPA端口数据"
+#: ardour_ui.cc:3358
+msgid "giga"
+msgstr "十亿(千兆)"
 
-#: ladspa_plugin.cc:842
-msgid "Could not locate HOME.  Preset not removed."
-msgstr "无法定位HOME. 预设没被移除."
+#: ardour_ui.cc:3363
+msgid ""
+"The following file was deleted from %2,\n"
+"releasing %3 %4bytes of disk space"
+msgid_plural ""
+"The following %1 files were deleted from %2,\n"
+"releasing %3 %4bytes of disk space"
+msgstr[0] ""
+"以下 %1 文件被从 %2 删除,\n"
+"释放 %3 %4 字节的磁盘空间"
+
+#: ardour_ui.cc:3370
+msgid ""
+"The following file was not in use and \n"
+"has been moved to: %2\n"
+"\n"
+"After a restart of %5\n"
+"\n"
+"<span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n"
+"\n"
+"will release an additional %3 %4bytes of disk space.\n"
+msgid_plural ""
+"The following %1 files were not in use and \n"
+"have been moved to: %2\n"
+"\n"
+"After a restart of %5\n"
+"\n"
+"<span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n"
+"\n"
+"will release an additional %3 %4bytes of disk space.\n"
+msgstr[0] ""
+"以下 %1 文件未被使用\n"
+"并且被移动到: %2  \n"
+"\n"
 
-#: ladspa_plugin.cc:881 ladspa_plugin.cc:887
-msgid "Could not create %1.  Preset not saved. (%2)"
-msgstr "不能创建 %1. 预设没保存. (%2)"
+#: ardour_ui.cc:3430
+msgid "Are you sure you want to clean-up?"
+msgstr "您确认要清空?"
 
-#: ladspa_plugin.cc:894
-msgid "Error saving presets file %1."
+#: ardour_ui.cc:3437
+msgid ""
+"Clean-up is a destructive operation.\n"
+"ALL undo/redo information will be lost if you clean-up.\n"
+"Clean-up will move all unused files to a \"dead\" location."
 msgstr ""
+"清空是毁灭性的操作。\n"
+"如果你清空了, 所有的撤销/重做信息将会丢失。\n"
+"清空将会把所有未使用过的文件移动到 \"死亡\" 位置。"
 
-#: ladspa_plugin.cc:936
-msgid "Could not locate HOME.  Preset not saved."
-msgstr "无法定位HOME. 预设没保存."
+#: ardour_ui.cc:3445
+msgid "CleanupDialog"
+msgstr "清空对话框"
 
-#: location.cc:456
-msgid "You cannot put a CD marker at this position"
-msgstr "你不可以把CD标签放在这个位置"
+#: ardour_ui.cc:3475
+msgid "Cleaned Files"
+msgstr "清除文件"
 
-#: location.cc:608
-msgid "incorrect XML node passed to Location::set_state"
-msgstr ""
+#: ardour_ui.cc:3492
+msgid "deleted file"
+msgstr "删除文件"
 
-#: location.cc:613
-msgid "XML node for Location has no ID information"
-msgstr ""
+#: ardour_ui.cc:3637
+msgid "Video-Server was not launched by %1. The request to stop it is ignored."
+msgstr "视频服务器未被 %1 触发。请求停止视频服务器的要求被忽略。"
 
-#: location.cc:617
-msgid "XML node for Location has no name information"
-msgstr ""
+#: ardour_ui.cc:3641
+msgid "Stop Video-Server"
+msgstr "停止视频服务器"
 
-#: location.cc:624
-msgid "XML node for Location has no start information"
-msgstr ""
+#: ardour_ui.cc:3642
+msgid "Do you really want to stop the Video Server?"
+msgstr "您真的打算停止视频服务器?"
 
-#: location.cc:635
-msgid "XML node for Location has no end information"
-msgstr ""
+#: ardour_ui.cc:3645
+msgid "Yes, Stop It"
+msgstr "是的,停止它"
 
-#: location.cc:642
-msgid "XML node for Location has no flags information"
-msgstr ""
+#: ardour_ui.cc:3671
+msgid "The Video Server is already started."
+msgstr "视频服务器已经启动。"
 
-#: location.cc:856
-msgid "Locations: attempt to use unknown location as selected location"
-msgstr ""
+#: ardour_ui.cc:3673
+msgid ""
+"An external Video Server is configured and can be reached. Not starting a new "
+"instance."
+msgstr "一个外部视频服务器已经配置且可以实现。尚未启动一个新的实例。"
 
-#: location.cc:1034
-msgid "incorrect XML mode passed to Locations::set_state"
-msgstr ""
+#: ardour_ui.cc:3681 ardour_ui.cc:3786
+msgid ""
+"Could not connect to the Video Server. Start it or configure its access URL in "
+"Preferences."
+msgstr "无法连接到视频服务器。请启动或者配置视频服务器的访问URL网址首选项。"
 
-#: location.cc:1047 session.cc:1293 session.cc:4919 session_state.cc:1053
-msgid "session"
-msgstr "会话"
+#: ardour_ui.cc:3711
+msgid "Specified docroot is not an existing directory."
+msgstr "指定的文档根目录不存在。"
 
-#: location.cc:1112
-msgid "could not load location from session file - ignored"
-msgstr ""
+#: ardour_ui.cc:3717 ardour_ui.cc:3723
+msgid "Given Video Server is not an executable file."
+msgstr "给定的视频服务器不是一个可执行文件。"
 
-#: location_importer.cc:61
-msgid "Locations"
-msgstr ""
+#: ardour_ui.cc:3757
+msgid "Cannot launch the video-server"
+msgstr "无法启动视频服务器"
 
-#: location_importer.cc:123
-msgid "Location: "
-msgstr ""
+#: ardour_ui.cc:3767
+msgid "Video-server was started but does not respond to requests..."
+msgstr "视频服务器已经启动但没有响应请求……"
 
-#: location_importer.cc:125
-msgid ""
-"Range\n"
-"start: "
-msgstr ""
+#: ardour_ui.cc:3812 editor_audio_import.cc:641
+msgid "could not open %1"
+msgstr "无法打开%1"
+
+#: ardour_ui.cc:3816
+msgid "no video-file selected"
+msgstr "尚未选择视频文件"
+
+#: ardour_ui.cc:4014
+msgid "Recording was stopped because your system could not keep up."
+msgstr "由于您的系统无法继续工作导致录制停止。"
 
-#: location_importer.cc:126
+#: ardour_ui.cc:4043
 msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with %1.\n"
 "\n"
-"end: "
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
 msgstr ""
+"您电脑的硬盘系统\n"
+"无法持续跟进 %1 。\n"
+"\n"
+"确切地说,失败的原因是硬盘的写入速度\n"
+"不足以持续跟上录制的速度。\n"
 
-#: location_importer.cc:146
-msgid ""
-"The location is the Punch range. It will be imported as a normal range.\n"
-"You may rename the imported location:"
-msgstr ""
+#: ardour_ui.cc:4113
+msgid "Scanning for plugins"
+msgstr "正在扫描插件"
+
+#: ardour_ui.cc:4115
+msgid "Cancel plugin scan"
+msgstr "取消插件扫描"
 
-#: location_importer.cc:157
+#: ardour_ui.cc:4124
+msgid "Stop Timeout"
+msgstr "停止超时"
+
+#: ardour_ui.cc:4131
+msgid "Scan Timeout"
+msgstr "扫描超时"
+
+#: ardour_ui.cc:4174
 msgid ""
-"The location is a Loop range. It will be imported as a normal range.\n"
-"You may rename the imported location:"
+"The disk system on your computer\n"
+"was not able to keep up with %1.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
 msgstr ""
+"您电脑的硬盘系统\n"
+"无法持续跟进 %1 。\n"
+"\n"
+"确切地说,失败的原因是硬盘的读取速度\n"
+"不足以持续跟上回放的速度。\n"
 
-#: location_importer.cc:168
+#: ardour_ui.cc:4214
+msgid "Crash Recovery"
+msgstr "崩溃恢复"
+
+#: ardour_ui.cc:4215
 msgid ""
-"A location with that name already exists.\n"
-"You may rename the imported location:"
+"This session appears to have been in the\n"
+"middle of recording when %1 or\n"
+"the computer was shutdown.\n"
+"\n"
+"%1 can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
 msgstr ""
+"本会话似乎是一直处在\n"
+"录制的中段,当 %1 时\n"
+"或者在计算机关闭时。\n"
+"\n"
+" %1 可以为您恢复任何已捕获的音频,\n"
+"或者忽略它。\n"
+"请确认您的决定。\n"
 
-#: ltc_slave.cc:272
-msgid "Session framerate adjusted from %1 to LTC's %2."
-msgstr ""
+#: ardour_ui.cc:4227
+msgid "Ignore crash data"
+msgstr "忽略崩溃的数据"
 
-#: ltc_slave.cc:286
-msgid "Session and LTC framerate mismatch: LTC:%1 Session:%2."
-msgstr ""
+#: ardour_ui.cc:4228
+msgid "Recover from crash"
+msgstr "恢复到崩溃前"
 
-#: ltc_slave.cc:603
-msgid "flywheel"
-msgstr ""
+#: ardour_ui.cc:4248
+msgid "Sample Rate Mismatch"
+msgstr "采样率不匹配"
 
-#: midi_diskstream.cc:173
+#: ardour_ui.cc:4249
 msgid ""
-"%1: I/O configuration change %4 requested to use %2, but channel setup is %3"
+"This session was created with a sample rate of %1 Hz, but\n"
+"%2 is currently running at %3 Hz.  If you load this session,\n"
+"audio may be played at the wrong sample rate.\n"
 msgstr ""
+"本会话已经创建 %1 Hz 的采样率,\n"
+"但是 %2 目前运行在 %3 Hz。如果您加载这个会话,\n"
+"音频可能会处在错误的采样率上播放。\n"
 
-#: midi_diskstream.cc:225
-msgid "MidiDiskstream: Playlist \"%1\" isn't a midi playlist"
-msgstr ""
+#: ardour_ui.cc:4258
+msgid "Do not load session"
+msgstr "不要载入会话"
 
-#: midi_diskstream.cc:276
-msgid "MidiDiskstream %1: there is no existing playlist to make a copy of!"
-msgstr ""
+#: ardour_ui.cc:4259
+msgid "Load session anyway"
+msgstr "只管载入会话"
 
-#: midi_diskstream.cc:754
-msgid "MidiDiskstream %1: cannot read %2 from playlist at frame %3"
-msgstr ""
+#: ardour_ui.cc:4286
+msgid "Could not disconnect from Audio/MIDI engine"
+msgstr "无法从音频/MIDI引擎上取消连接"
 
-#: midi_diskstream.cc:891
-msgid "MidiDiskstream %1: cannot write to disk"
-msgstr "MIDI磁盘流 %1: 无法写入硬盘"
+#: ardour_ui.cc:4303 ardour_ui.cc:4306
+msgid "Could not reconnect to the Audio/MIDI engine"
+msgstr "无法重新连接到音频/MIDI引擎"
 
-#: midi_diskstream.cc:925
-msgid "MidiDiskstream \"%1\": cannot flush captured data to disk!"
+#: ardour_ui.cc:4590
+msgid ""
+"%4This is a session from an older version of %3%5\n"
+"\n"
+"%3 has copied the old session file\n"
+"\n"
+"%6%1%7\n"
+"\n"
+"to\n"
+"\n"
+"%6%2%7\n"
+"\n"
+"From now on, use the -2000 version with older versions of %3"
 msgstr ""
+"%4 这是一个来源于 %3%5 旧版本的会话\n"
+"\n"
+"%3 已经被复制到旧的会话文件\n"
+"\n"
+"%6%1%7\n"
+"\n"
+"to\n"
+"\n"
+"%6%2%7\n"
+"\n"
+"从现在开始,使用连带旧版 %3 的 -2000 版本"
 
-#: midi_diskstream.cc:1014
-msgid "%1: could not create region for complete midi file"
-msgstr ""
+#: ardour_ui2.cc:73
+msgid "UI: cannot setup editor"
+msgstr "用户界面:无法设置编辑器"
 
-#: midi_diskstream.cc:1055
-msgid "MidiDiskstream: could not create region for captured midi!"
-msgstr ""
+#: ardour_ui2.cc:78
+msgid "UI: cannot setup mixer"
+msgstr "用户界面:无法设置混音器"
 
-#: midi_model.cc:589
-msgid "Change has no note, using note ID"
-msgstr ""
+#: ardour_ui2.cc:83
+msgid "UI: cannot setup meterbridge"
+msgstr "用户界面:无法设置节拍桥接"
 
-#: midi_model.cc:593
-msgid "Change has no note or note ID"
-msgstr ""
+#: ardour_ui2.cc:128
+msgid "Play from playhead"
+msgstr "从指针开始播放"
 
-#: midi_model.cc:614
-msgid "No NoteID found for note property change - ignored"
-msgstr ""
+#: ardour_ui2.cc:129
+msgid "Stop playback"
+msgstr "停止回放"
 
-#: midi_model.cc:890
-msgid "No SysExID found for sys-ex property change - ignored"
-msgstr ""
+#: ardour_ui2.cc:130
+msgid "Toggle record"
+msgstr "切换录制"
 
-#: midi_model.cc:1994
-msgid "transpose"
-msgstr ""
+#: ardour_ui2.cc:131
+msgid "Play range/selection"
+msgstr "播放范围/已选择部分"
 
-#: midi_patch_manager.cc:133
-msgid "Duplicate MIDI device `%1' in `%2' ignored"
-msgstr ""
+#: ardour_ui2.cc:132
+msgid "Go to start of session"
+msgstr "转至会话起点"
 
-#: midi_scene_changer.cc:295
-msgid "Scene "
-msgstr ""
+#: ardour_ui2.cc:133
+msgid "Go to end of session"
+msgstr "转至会话终点"
 
-#: midi_source.cc:125
-msgid "Missing parameter property on InterpolationStyle"
-msgstr ""
+#: ardour_ui2.cc:134
+msgid "Play loop range"
+msgstr "播放循环范围"
 
-#: midi_source.cc:131
-msgid "Missing style property on InterpolationStyle"
+#: ardour_ui2.cc:135
+msgid ""
+"MIDI Panic\n"
+"Send note off and reset controller messages on all MIDI channels"
 msgstr ""
+"MIDI 终止\n"
+"发送音符关闭和复位控制器信息到所有 MIDI 通道"
 
-#: midi_source.cc:140
-msgid "Missing parameter property on AutomationState"
-msgstr ""
+#: ardour_ui2.cc:136
+msgid "Return to last playback start when stopped"
+msgstr "当停止时返回至最后一次回放的起点"
 
-#: midi_source.cc:146
-msgid "Missing state property on AutomationState"
-msgstr ""
+#: ardour_ui2.cc:137
+msgid "Playhead follows Range Selections and Edits"
+msgstr "指针跟随范围已选择部分并编辑"
 
-#: midi_stretch.cc:88
-msgid "MIDI stretch created non-MIDI source"
-msgstr ""
+#: ardour_ui2.cc:138
+msgid "Be sensible about input monitoring"
+msgstr "确保清晰的输入监控"
 
-#: monitor_processor.cc:53
-msgid "monitor dim"
-msgstr ""
+#: ardour_ui2.cc:139
+msgid "Enable/Disable audio click"
+msgstr "启用/禁用音频识别声(节拍器) "
 
-#: monitor_processor.cc:54
-msgid "monitor cut"
+#: ardour_ui2.cc:140 monitor_section.cc:111
+msgid ""
+"When active, something is soloed.\n"
+"Click to de-solo everything"
 msgstr ""
+"启用时,仅独奏某部分。\n"
+"Click to de-solo everything 点击全部不独奏"
 
-#: monitor_processor.cc:55
-msgid "monitor mono"
+#: ardour_ui2.cc:141
+msgid ""
+"When active, auditioning is taking place\n"
+"Click to stop the audition"
 msgstr ""
+"当启用时监听开始.\n"
+"点击停止监听."
 
-#: monitor_processor.cc:58
-msgid "monitor dim level"
-msgstr ""
+#: ardour_ui2.cc:142
+msgid "When active, there is a feedback loop."
+msgstr "启用时,有一个反馈回路。"
 
-#: monitor_processor.cc:62
-msgid "monitor solo boost level"
+#: ardour_ui2.cc:143
+msgid ""
+"<b>Primary Clock</b> right-click to set display mode. Click to edit, click+drag a "
+"digit or mouse-over+scroll wheel to modify.\n"
+"Text edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: confirm; "
+"postfix the edit with '+' or '-' to enter delta times.\n"
 msgstr ""
+"<b>主计时器</b>右键点击设置显示模式。点击即可编辑,点击+拖动数字或者鼠标放在数字上"
+"面滚动滚轮即可修改数字。\n"
+"文本编辑:从右到左覆盖 <tt>Esc 键</tt>:取消; <tt>回车键</tt>:确认;编辑后加"
+"上“+”号或者“-”号即可进入下一级时间\n"
 
-#: monitor_processor.cc:512
-msgid "cut control %1"
-msgstr ""
+#: ardour_ui2.cc:144
+msgid ""
+"<b>Secondary Clock</b> right-click to set display mode. Click to edit, click+drag "
+"a digit or mouse-over+scroll wheel to modify.\n"
+"Text edits: right-to-left overwrite <tt>Esc</tt>: cancel; <tt>Enter</tt>: confirm; "
+"postfix the edit with '+' or '-' to enter delta times.\n"
+msgstr ""
+"<b>第二计时器</b>右键点击设置显示模式。点击即可编辑,点击+拖动数字或者鼠标放在数字"
+"上面滚动滚轮即可修改数字。\n"
+"文本编辑:从右到左覆盖 <tt>Esc 键</tt>:取消; <tt>回车键</tt>:确认;编辑后加"
+"上“+”号或者“-”号即可进入下一级时间\n"
+
+#: ardour_ui2.cc:145
+msgid "Reset All Peak Indicators"
+msgstr "重置所有峰值指标"
+
+#: ardour_ui2.cc:146
+msgid "Show Error Log and acknowledge warnings"
+msgstr "显示错误日志并确认警报"
+
+#: ardour_ui2.cc:179
+msgid "[ERROR]: "
+msgstr "【错误】:"
+
+#: ardour_ui2.cc:182
+msgid "[WARNING]: "
+msgstr "【警告】:"
+
+#: ardour_ui2.cc:185
+msgid "[INFO]: "
+msgstr "【信息】:"
+
+#: ardour_ui2.cc:253 ardour_ui_ed.cc:403
+msgid "Auto Return"
+msgstr "自动返回"
+
+#: ardour_ui2.cc:255 ardour_ui_ed.cc:406
+msgid "Follow Edits"
+msgstr "跟随编辑"
+
+# GUI - Graphical User Interface
+#: ardour_ui2.cc:716 rc_option_editor.cc:2300
+msgid "GUI"
+msgstr "图形用户界面"
+
+#: ardour_ui2.cc:733 rc_option_editor.cc:1309 rc_option_editor.cc:1327
+#: rc_option_editor.cc:1330 rc_option_editor.cc:1332 rc_option_editor.cc:1334
+#: rc_option_editor.cc:1342 rc_option_editor.cc:1350 rc_option_editor.cc:1352
+#: rc_option_editor.cc:1360 rc_option_editor.cc:1367 rc_option_editor.cc:1376
+#: rc_option_editor.cc:1378 rc_option_editor.cc:1380 rc_option_editor.cc:1388
+#: rc_option_editor.cc:1390 rc_option_editor.cc:1399 session_option_editor.cc:321
+#: session_option_editor.cc:323 session_option_editor.cc:344
+#: session_option_editor.cc:346 session_option_editor.cc:348
+#: session_option_editor.cc:355 session_option_editor.cc:362
+#: session_option_editor.cc:366
+msgid "Misc"
+msgstr "杂项"
+
+#: ardour_ui_dependents.cc:76
+msgid "Setup Editor"
+msgstr "设置编辑器"
+
+#: ardour_ui_dependents.cc:78
+msgid "Setup Mixer"
+msgstr "设置混音器"
+
+#: ardour_ui_dependents.cc:84
+msgid "Reload Session History"
+msgstr "重新装摘会话历史"
+
+#: ardour_ui_dialogs.cc:250
+msgid "Don't close"
+msgstr "请勿关闭"
+
+#: ardour_ui_dialogs.cc:251
+msgid "Just close"
+msgstr "只管关闭"
+
+#: ardour_ui_dialogs.cc:252
+msgid "Save and close"
+msgstr "保存并关闭"
+
+#: ardour_ui_dialogs.cc:362
+msgid "This screen is not tall enough to display the mixer window"
+msgstr "这个屏幕的高度不足以显示混音器窗口"
+
+#: ardour_ui_ed.cc:102
+msgid "Session"
+msgstr "会话"
 
-#: monitor_processor.cc:513
-msgid "dim control"
-msgstr ""
+#: ardour_ui_ed.cc:105 editor_actions.cc:138 editor_regions.cc:116 port_group.cc:458
+#: session_option_editor.cc:82 session_option_editor.cc:89
+msgid "Sync"
+msgstr "同步"
 
-#: monitor_processor.cc:514
-msgid "polarity control"
-msgstr ""
+#: ardour_ui_ed.cc:106
+msgid "Options"
+msgstr "选项"
 
-#: monitor_processor.cc:515
-msgid "solo control"
-msgstr ""
+#: ardour_ui_ed.cc:107
+msgid "Window"
+msgstr "窗口"
 
-#: mtc_slave.cc:240
-msgid "MTC Slave: atomic read of current time failed, sleeping!"
-msgstr ""
+#: ardour_ui_ed.cc:108
+msgid "Help"
+msgstr "帮助"
 
-#: mtc_slave.cc:362
-msgid ""
-"Unknown rate/drop value %1 in incoming MTC stream, session values used "
-"instead"
-msgstr ""
+#: ardour_ui_ed.cc:109
+msgid "Misc. Shortcuts"
+msgstr "杂项、 快捷键"
 
-#: mtc_slave.cc:382
-msgid "Session framerate adjusted from %1 TO: MTC's %2."
-msgstr ""
+#: ardour_ui_ed.cc:110
+msgid "Audio File Format"
+msgstr "音频文件格式"
 
-#: mtc_slave.cc:396
-msgid "Session and MTC framerate mismatch: MTC:%1 %2:%3."
-msgstr ""
+#: ardour_ui_ed.cc:111
+msgid "File Type"
+msgstr "文件类型"
 
-#: operations.cc:41
-msgid "capture"
-msgstr "录音"
+#: ardour_ui_ed.cc:112 export_format_dialog.cc:67
+msgid "Sample Format"
+msgstr "采样格式"
 
-#: operations.cc:42
-msgid "paste"
-msgstr "粘贴"
+#: ardour_ui_ed.cc:113 rc_option_editor.cc:2245 rc_option_editor.cc:2257
+msgid "Control Surfaces"
+msgstr "控制面"
 
-#: operations.cc:43
-msgid "duplicate region"
-msgstr "复制区域"
+#: ardour_ui_ed.cc:114 rc_option_editor.cc:1921 rc_option_editor.cc:2264
+msgid "Plugins"
+msgstr "插件"
 
-#: operations.cc:44
-msgid "insert file"
-msgstr "插入文件"
+#: ardour_ui_ed.cc:115 rc_option_editor.cc:2351
+msgid "Metering"
+msgstr "节拍"
 
-#: operations.cc:45
-msgid "insert region"
-msgstr "插入选取"
+#: ardour_ui_ed.cc:116
+msgid "Fall Off Rate"
+msgstr "衰减率"
 
-#: operations.cc:46
-msgid "drag region brush"
-msgstr ""
+#: ardour_ui_ed.cc:117
+msgid "Hold Time"
+msgstr "持续时间"
 
-#: operations.cc:47
-msgid "region drag"
-msgstr ""
+#: ardour_ui_ed.cc:118
+msgid "Denormal Handling"
+msgstr "非常规处理"
 
-#: operations.cc:48
-msgid "selection grab"
-msgstr ""
+#: ardour_ui_ed.cc:122 route_time_axis.cc:1677
+msgid "New..."
+msgstr "新建…"
 
-#: operations.cc:49
-msgid "region fill"
-msgstr ""
+#: ardour_ui_ed.cc:124
+msgid "Open..."
+msgstr "打开…"
 
-#: operations.cc:50
-msgid "fill selection"
-msgstr "填充选区"
+#: ardour_ui_ed.cc:125
+msgid "Recent..."
+msgstr "最近的…"
 
-#: operations.cc:51
-msgid "create region"
-msgstr "创建选区"
+#: ardour_ui_ed.cc:126 panner_editor.cc:29 playlist_selector.cc:64
+msgid "Close"
+msgstr "关闭"
 
-#: operations.cc:52
-msgid "region copy"
-msgstr ""
+#: ardour_ui_ed.cc:129
+msgid "Add Track or Bus..."
+msgstr "添加音轨或总线…"
 
-#: operations.cc:53
-msgid "fixed time region copy"
-msgstr ""
+#: ardour_ui_ed.cc:134
+msgid "Open Video"
+msgstr "打开视频"
 
-#: pannable.cc:207
-msgid "Pannable given XML data for %1 - ignored"
-msgstr ""
+#: ardour_ui_ed.cc:137
+msgid "Remove Video"
+msgstr "移除视频"
 
-#: panner_manager.cc:95
-msgid "looking for panners in %1\n"
-msgstr ""
+#: ardour_ui_ed.cc:140
+msgid "Export To Video File"
+msgstr "导出为视频文件"
 
-#: panner_manager.cc:121
-msgid "Panner discovered: \"%1\" in %2\n"
-msgstr ""
+#: ardour_ui_ed.cc:144
+msgid "Snapshot..."
+msgstr "快照…"
 
-#: panner_manager.cc:140
-msgid "PannerManager: cannot load module \"%1\" (%2)"
-msgstr ""
+#: ardour_ui_ed.cc:148
+msgid "Save As..."
+msgstr "另存为…"
 
-#: panner_manager.cc:147
-msgid "PannerManager: module \"%1\" has no descriptor function."
-msgstr ""
+#: ardour_ui_ed.cc:152 editor_actions.cc:1771 editor_markers.cc:903
+#: editor_snapshots.cc:124 mixer_strip.cc:1518 route_time_axis.cc:1673
+msgid "Rename..."
+msgstr "重命名…"
+
+#: ardour_ui_ed.cc:156
+msgid "Save Template..."
+msgstr "保存模板…"
+
+#: ardour_ui_ed.cc:159
+msgid "Metadata"
+msgstr "元数据"
+
+#: ardour_ui_ed.cc:162
+msgid "Edit Metadata..."
+msgstr "编辑元数据…"
+
+#: ardour_ui_ed.cc:165
+msgid "Import Metadata..."
+msgstr "导入元数据…"
+
+#: ardour_ui_ed.cc:168
+msgid "Export To Audio File(s)..."
+msgstr "导出为音频文件…"
+
+#: ardour_ui_ed.cc:171
+msgid "Stem export..."
+msgstr "主体导出…"
+
+#: ardour_ui_ed.cc:174 editor_export_audio.cc:65 export_dialog.cc:129
+#: export_video_dialog.cc:84
+msgid "Export"
+msgstr "导出"
+
+#: ardour_ui_ed.cc:177
+msgid "Clean-up Unused Sources..."
+msgstr "清空未使用的源…"
+
+#: ardour_ui_ed.cc:181
+msgid "Flush Wastebasket"
+msgstr "清空回收站"
+
+#: ardour_ui_ed.cc:188
+msgid "Quit"
+msgstr "退出"
+
+#: ardour_ui_ed.cc:192
+msgid "Maximise Editor Space"
+msgstr "最大化编辑器空间"
+
+#: ardour_ui_ed.cc:193
+msgid "Maximise Mixer Space"
+msgstr "最大化混音器空间"
+
+#: ardour_ui_ed.cc:194
+msgid "Show Toolbars"
+msgstr "显示工具栏"
+
+#: ardour_ui_ed.cc:198
+msgid "Show more UI preferences"
+msgstr "显示更多用户界面首选项"
+
+#: ardour_ui_ed.cc:200 mixer_ui.cc:1924 mixer_ui.cc:1930
+msgid "Window|Mixer"
+msgstr "窗口|混音器"
+
+#: ardour_ui_ed.cc:201
+msgid "Toggle Editor+Mixer"
+msgstr "切换编辑器+混音器"
+
+#: ardour_ui_ed.cc:202 meterbridge.cc:218 meterbridge.cc:224
+msgid "Window|Meterbridge"
+msgstr "窗口|节拍桥接"
+
+#: ardour_ui_ed.cc:204
+msgid "Reattach All Tearoffs"
+msgstr "重新附加所有的片段"
+
+#: ardour_ui_ed.cc:206 midi_tracer.cc:45
+msgid "MIDI Tracer"
+msgstr "MIDI 音轨"
+
+#: ardour_ui_ed.cc:208
+msgid "Chat"
+msgstr "聊天"
+
+#: ardour_ui_ed.cc:210
+msgid "Help|Manual"
+msgstr "帮助|手册"
+
+#: ardour_ui_ed.cc:211
+msgid "Reference"
+msgstr "参考"
+
+#: ardour_ui_ed.cc:212
+msgid "Report A Bug"
+msgstr "报告故障"
+
+#: ardour_ui_ed.cc:213
+msgid "Cheat Sheet"
+msgstr "备忘录"
+
+#: ardour_ui_ed.cc:214
+msgid "Ardour Website"
+msgstr "Ardour 官网"
+
+#: ardour_ui_ed.cc:215
+msgid "Ardour Development"
+msgstr "Ardour 开发 "
+
+#: ardour_ui_ed.cc:216
+msgid "User Forums"
+msgstr "用户论坛"
+
+#: ardour_ui_ed.cc:217
+msgid "How to report a bug"
+msgstr "如何报告故障"
+
+#: ardour_ui_ed.cc:219 plugin_ui.cc:419
+msgid "Save"
+msgstr "保存"
+
+#: ardour_ui_ed.cc:227 rc_option_editor.cc:1419 rc_option_editor.cc:1430
+#: rc_option_editor.cc:1441 rc_option_editor.cc:1450 rc_option_editor.cc:1463
+#: rc_option_editor.cc:1476 rc_option_editor.cc:1485 rc_option_editor.cc:1495
+#: rc_option_editor.cc:1497 rc_option_editor.cc:1506 rc_option_editor.cc:1522
+#: rc_option_editor.cc:1543 rc_option_editor.cc:1561 rc_option_editor.cc:1563
+#: rc_option_editor.cc:1579 rc_option_editor.cc:1582 rc_option_editor.cc:1584
+#: rc_option_editor.cc:1601 rc_option_editor.cc:1612
+msgid "Transport"
+msgstr "播送"
+
+#: ardour_ui_ed.cc:233
+msgid "Stop"
+msgstr "停止"
+
+#: ardour_ui_ed.cc:236
+msgid "Roll"
+msgstr "滚动"
+
+#: ardour_ui_ed.cc:240 ardour_ui_ed.cc:243
+msgid "Start/Stop"
+msgstr "开始/停止"
+
+#: ardour_ui_ed.cc:246
+msgid "Start/Continue/Stop"
+msgstr "开始/继续/停止"
+
+#: ardour_ui_ed.cc:249
+msgid "Stop and Forget Capture"
+msgstr "暂停并且废弃已捕获内容"
+
+#: ardour_ui_ed.cc:259
+msgid "Transition To Roll"
+msgstr "过渡到滚动"
+
+#: ardour_ui_ed.cc:263
+msgid "Transition To Reverse"
+msgstr "过渡到反向"
+
+#: ardour_ui_ed.cc:267
+msgid "Play Loop Range"
+msgstr "循环播放范围"
+
+#: ardour_ui_ed.cc:270
+msgid "Play Selection"
+msgstr "播放已选择部分"
+
+#: ardour_ui_ed.cc:273
+msgid "Play Selection w/Preroll"
+msgstr "播放已选择部分预滚"
+
+#: ardour_ui_ed.cc:277
+msgid "Enable Record"
+msgstr "启用录制"
+
+#: ardour_ui_ed.cc:280 ardour_ui_ed.cc:284
+msgid "Start Recording"
+msgstr "开始录制"
+
+#: ardour_ui_ed.cc:288
+msgid "Rewind"
+msgstr "倒带"
+
+#: ardour_ui_ed.cc:291
+msgid "Rewind (Slow)"
+msgstr "倒带(慢速)"
+
+#: ardour_ui_ed.cc:294
+msgid "Rewind (Fast)"
+msgstr "倒带(快速)"
+
+#: ardour_ui_ed.cc:297
+msgid "Forward"
+msgstr "å¿«è¿›"
+
+#: ardour_ui_ed.cc:300
+msgid "Forward (Slow)"
+msgstr "快进(慢速)"
+
+#: ardour_ui_ed.cc:303
+msgid "Forward (Fast)"
+msgstr "快进(快速)"
+
+#: ardour_ui_ed.cc:306
+msgid "Go to Zero"
+msgstr "转到零点"
+
+#: ardour_ui_ed.cc:309 ardour_ui_ed.cc:312
+msgid "Go to Start"
+msgstr "转到起始位置"
+
+#: ardour_ui_ed.cc:315
+msgid "Go to End"
+msgstr "转到末尾位置"
+
+#: ardour_ui_ed.cc:318
+msgid "Go to Wall Clock"
+msgstr "转到计时点"
+
+#: ardour_ui_ed.cc:323 ardour_ui_ed.cc:326
+msgid "Numpad Decimal"
+msgstr "数字键盘十进制"
+
+#: ardour_ui_ed.cc:329
+msgid "Numpad 0"
+msgstr "数字键盘 0"
+
+#: ardour_ui_ed.cc:332
+msgid "Numpad 1"
+msgstr "数字键盘 1"
+
+#: ardour_ui_ed.cc:335
+msgid "Numpad 2"
+msgstr "数字键盘 2"
+
+#: ardour_ui_ed.cc:338
+msgid "Numpad 3"
+msgstr "数字键盘 3"
+
+#: ardour_ui_ed.cc:341
+msgid "Numpad 4"
+msgstr "数字键盘 4"
+
+#: ardour_ui_ed.cc:344
+msgid "Numpad 5"
+msgstr "数字键盘 5"
+
+#: ardour_ui_ed.cc:347
+msgid "Numpad 6"
+msgstr "数字键盘 6"
+
+#: ardour_ui_ed.cc:350
+msgid "Numpad 7"
+msgstr "数字键盘 7"
+
+#: ardour_ui_ed.cc:353
+msgid "Numpad 8"
+msgstr "数字键盘 8"
+
+#: ardour_ui_ed.cc:356
+msgid "Numpad 9"
+msgstr "数字键盘 9"
+
+#: ardour_ui_ed.cc:360
+msgid "Focus On Clock"
+msgstr "聚焦于计时器"
+
+#: ardour_ui_ed.cc:364 ardour_ui_ed.cc:373 audio_clock.cc:2091 editor.cc:258
+#: editor_actions.cc:569 editor_actions.cc:578 export_timespan_selector.cc:88
+#: session_option_editor.cc:41 session_option_editor.cc:61
+#: session_option_editor.cc:80 session_option_editor.cc:96
+#: session_option_editor.cc:109 session_option_editor.cc:122
+#: session_option_editor.cc:124 session_option_editor.cc:126
+msgid "Timecode"
+msgstr "时间码"
+
+#: ardour_ui_ed.cc:366 ardour_ui_ed.cc:375 editor_actions.cc:567
+msgid "Bars & Beats"
+msgstr "小节 & 拍子"
+
+#: ardour_ui_ed.cc:368 ardour_ui_ed.cc:377
+msgid "Minutes & Seconds"
+msgstr "分&秒"
+
+#: ardour_ui_ed.cc:370 ardour_ui_ed.cc:379 audio_clock.cc:2095 editor.cc:259
+#: editor_actions.cc:568
+msgid "Samples"
+msgstr "采样"
+
+#: ardour_ui_ed.cc:382
+msgid "Punch In"
+msgstr "切入"
+
+#: ardour_ui_ed.cc:383 mixer_strip.cc:1819 mixer_strip.cc:1843 mixer_strip.cc:2007
+#: route_ui.cc:162 time_info_box.cc:116
+msgid "In"
+msgstr "å…¥"
+
+#: ardour_ui_ed.cc:386
+msgid "Punch Out"
+msgstr "切出"
+
+#: ardour_ui_ed.cc:387 mixer_strip.cc:1831 time_info_box.cc:117
+msgid "Out"
+msgstr "出"
+
+#: ardour_ui_ed.cc:390
+msgid "Punch In/Out"
+msgstr "切入/切出"
+
+#: ardour_ui_ed.cc:391
+msgid "In/Out"
+msgstr "入/出"
+
+#: ardour_ui_ed.cc:394 rc_option_editor.cc:1376
+msgid "Click"
+msgstr "点击"
+
+#: ardour_ui_ed.cc:397
+msgid "Auto Input"
+msgstr "自动输入"
+
+#: ardour_ui_ed.cc:400
+msgid "Auto Play"
+msgstr "自动播放"
+
+#: ardour_ui_ed.cc:411
+msgid "Sync Startup to Video"
+msgstr "同步启动到视频"
+
+#: ardour_ui_ed.cc:413
+msgid "Time Master"
+msgstr "计时器主控"
+
+#: ardour_ui_ed.cc:420
+msgid "Toggle Record Enable Track %1"
+msgstr "切换录制可用音轨 %1"
+
+#: ardour_ui_ed.cc:427
+msgid "Percentage"
+msgstr "百分比"
+
+#: ardour_ui_ed.cc:428 shuttle_control.cc:178
+msgid "Semitones"
+msgstr "半音"
+
+#: ardour_ui_ed.cc:432
+msgid "Send MTC"
+msgstr "发送MTC"
+
+#: ardour_ui_ed.cc:434
+msgid "Send MMC"
+msgstr "发送MMC"
+
+#: ardour_ui_ed.cc:436
+msgid "Use MMC"
+msgstr "使用MMC"
+
+#: ardour_ui_ed.cc:438 rc_option_editor.cc:2097
+msgid "Send MIDI Clock"
+msgstr "发送MIDI计时器"
+
+#: ardour_ui_ed.cc:440
+msgid "Send MIDI Feedback"
+msgstr "发送MIDI反馈"
+
+#: ardour_ui_ed.cc:446
+msgid "Panic"
+msgstr "终止"
+
+#: ardour_ui_ed.cc:534
+msgid "Wall Clock"
+msgstr "计时点"
 
-#: panner_manager.cc:234
-msgid "no panner discovered for in/out = %1/%2"
-msgstr ""
+#: ardour_ui_ed.cc:536
+msgid "Disk Space"
+msgstr "硬盘空间"
 
-#: panner_shell.cc:122
-msgid ""
-"No panner found: check that panners are being discovered correctly during "
-"startup."
-msgstr ""
+#: ardour_ui_ed.cc:537
+msgid "DSP"
+msgstr "数字信号处理"
 
-#: panner_shell.cc:126
-msgid "select panner: %1\n"
-msgstr ""
+#: ardour_ui_ed.cc:538
+msgid "Buffers"
+msgstr "缓冲"
 
-#: panner_shell.cc:255
-msgid "Unknown panner plugin \"%1\" found in pan state - ignored"
-msgstr ""
+#: ardour_ui_ed.cc:540
+msgid "Timecode Format"
+msgstr " 时间码格式"
 
-#: panner_shell.cc:261
-msgid "panner plugin node has no type information!"
-msgstr ""
+#: ardour_ui_ed.cc:541
+msgid "File Format"
+msgstr "文件格式"
 
-#: playlist.cc:2138
-msgid "region state node has no ID, ignored"
+#: ardour_ui_options.cc:63
+msgid ""
+"It is not possible to use JACK as the the sync source\n"
+"when the pull up/down setting is non-zero."
 msgstr ""
+"当拖动上/下的设置为非零时,\n"
+"不可能使用JACK作为同步源。"
 
-#: playlist.cc:2156
-msgid "Playlist: cannot create region from XML"
-msgstr ""
+#: ardour_ui_options.cc:317
+msgid "Internal"
+msgstr "内部的"
 
-#: playlist_source.cc:99
-msgid "No playlist ID in PlaylistSource XML!"
-msgstr ""
+#: ardour_ui_options.cc:498
+msgid "Enable/Disable external positional sync"
+msgstr "启用/禁用外部位置同步"
 
-#: playlist_source.cc:118
-msgid "Could not construct playlist for PlaylistSource from session data!"
-msgstr ""
+#: ardour_ui_options.cc:500
+msgid "Sync to JACK is not possible: video pull up/down is set"
+msgstr "不可能同步JACK:视频拖动上/下当前设置"
 
-#: plugin.cc:328
-msgid ""
-"Plugin presets are not supported in this build of %1. Consider paying for a "
-"full version"
-msgstr ""
+#: audio_clock.cc:1047 audio_clock.cc:1066
+msgid "--pending--"
+msgstr "—搁置—"
 
-#: plugin.cc:403
-msgid ""
-"Saving plugin settings is not supported in this build of %1. Consider paying "
-"for the full version"
+#: audio_clock.cc:1118
+msgid "SR"
 msgstr ""
 
-#: plugin_insert.cc:596
-msgid "programming error: "
-msgstr "程序错误:"
+#: audio_clock.cc:1124 audio_clock.cc:1128
+msgid "Pull"
+msgstr "拖动"
 
-#: plugin_insert.cc:933
-msgid "XML node describing plugin is missing the `type' field"
-msgstr ""
+#: audio_clock.cc:1126
+#, c-format
+msgid "%+.4f%%"
+msgstr "%+.4f%%"
 
-#: plugin_insert.cc:948
-msgid "unknown plugin type %1 in plugin insert state"
-msgstr ""
+#: audio_clock.cc:1282 editor.cc:260 editor_actions.cc:139 editor_actions.cc:561
+msgid "Tempo"
+msgstr "节奏"
 
-#: plugin_insert.cc:976
-msgid "Plugin has no unique ID field"
-msgstr ""
+#: audio_clock.cc:1286 editor.cc:261 editor_actions.cc:562
+msgid "Meter"
+msgstr "节拍"
 
-#: plugin_insert.cc:1001
-msgid ""
-"Found a reference to a plugin (\"%1\") that is unknown.\n"
-"Perhaps it was removed or moved since it was last used."
-msgstr ""
+#: audio_clock.cc:1864 audio_streamview.cc:115 editor_actions.cc:1089
+#: session_metadata_dialog.cc:452 session_metadata_dialog.cc:500
+#: session_metadata_dialog.cc:556 session_metadata_dialog.cc:845 streamview.cc:470
+msgid "programming error: %1"
+msgstr "程序错误: %1"
 
-#: plugin_insert.cc:1115
-msgid "PluginInsert: Auto: no ladspa port number"
-msgstr ""
+#: audio_clock.cc:1997 audio_clock.cc:2025
+msgid "programming error: %1 %2"
+msgstr "程序错误:%1 %2"
 
-#: plugin_insert.cc:1122
-msgid "PluginInsert: Auto: port id out of range"
-msgstr ""
+#: audio_clock.cc:2093 editor.cc:257 export_timespan_selector.cc:98
+msgid "Bars:Beats"
+msgstr "小节:拍子"
 
-#: plugin_insert.cc:1158
-msgid "PluginInsert: automatable control %1 not found - ignored"
-msgstr ""
+#: audio_clock.cc:2094 export_timespan_selector.cc:93
+msgid "Minutes:Seconds"
+msgstr "分:秒"
 
-#: plugin_manager.cc:209
-msgid "Discovering Plugins"
-msgstr "发现插件"
+#: audio_clock.cc:2099
+msgid "Set From Playhead"
+msgstr "从指针设置"
 
-#: plugin_manager.cc:231
-msgid "Scanning LADSPA Plugins"
-msgstr ""
+#: audio_clock.cc:2100
+msgid "Locate to This Time"
+msgstr "放置此时间"
 
-#: plugin_manager.cc:234
-msgid "Scanning LV2 Plugins"
+#: audio_region_editor.cc:64 control_point_dialog.cc:49 rhythm_ferret.cc:124
+#: rhythm_ferret.cc:129 rhythm_ferret.cc:134
+msgid "dB"
 msgstr ""
 
-#: plugin_manager.cc:239
-msgid "Scanning Windows VST Plugins"
-msgstr ""
+#: audio_region_editor.cc:67
+msgid "Region gain:"
+msgstr "区域增益:"
 
-#: plugin_manager.cc:246
-msgid "Scanning Linux VST Plugins"
+#: audio_region_editor.cc:77 export_format_dialog.cc:43
+msgid "dBFS"
 msgstr ""
 
-#: plugin_manager.cc:252
-msgid "Scanning AU Plugins"
-msgstr ""
+#: audio_region_editor.cc:80
+msgid "Peak amplitude:"
+msgstr "峰值幅度:"
 
-#: plugin_manager.cc:256
-msgid "Plugin Scan Complete..."
-msgstr ""
+#: audio_region_editor.cc:91
+msgid "Calculating..."
+msgstr "计算中…"
 
-#: plugin_manager.cc:393
-msgid "LADSPA"
-msgstr ""
+#: audio_region_view.cc:1243
+msgid "add gain control point"
+msgstr "添加增益控制点"
 
-#: plugin_manager.cc:445
-msgid "Could not parse rdf file: %1"
-msgstr "无法传递 rdf文件: %1"
+#: automation_controller.cc:286 automation_controller.cc:302
+msgid "Select Note..."
+msgstr "选择音符…"
 
-#: plugin_manager.cc:482
-msgid "LADSPA: cannot load module \"%1\" (%2)"
-msgstr "LADSPA: 无法载入模块 \"%1\" (%2)"
+#: automation_controller.cc:293
+msgid "Halve"
+msgstr "减半"
 
-#: plugin_manager.cc:489
-msgid "LADSPA: module \"%1\" has no descriptor function."
-msgstr ""
+#: automation_controller.cc:296
+msgid "Double"
+msgstr "加倍"
 
-#: plugin_manager.cc:705
-msgid "VST"
-msgstr ""
+#: automation_controller.cc:307
+msgid "Set to %1 beat(s)"
+msgstr "设为 %1 拍"
 
-#: plugin_manager.cc:732
-msgid ""
-"VST plugin %1 does not support processReplacing, and so cannot be used in %2 "
-"at this time"
-msgstr ""
+#: automation_line.cc:286 automation_line.cc:462
+msgid "automation event move"
+msgstr "自动化事件移动"
 
-#: plugin_manager.cc:824
-msgid "LXVST"
-msgstr ""
+#: automation_line.cc:488 automation_line.cc:508
+msgid "automation range move"
+msgstr "自动化范围移动"
+
+#: automation_line.cc:880 region_gain_line.cc:72
+msgid "remove control point"
+msgstr "移除控制点"
+
+#: automation_line.cc:1003
+msgid "Ignoring illegal points on AutomationLine \"%1\""
+msgstr "忽略自动化线路上的非法点:“ %1 ”"
+
+#: automation_region_view.cc:190 automation_time_axis.cc:644
+msgid "add automation event"
+msgstr "添加自动化事件"
+
+#: automation_streamview.cc:95
+msgid "unable to display automation region for control without list"
+msgstr "无法显示没有列表的自动化区域控制"
+
+#: automation_time_axis.cc:163
+msgid "automation state"
+msgstr "自动化状态"
+
+#: automation_time_axis.cc:164
+msgid "hide track"
+msgstr "隐藏音轨"
+
+#: automation_time_axis.cc:308 automation_time_axis.cc:360
+#: automation_time_axis.cc:554 gain_meter.cc:220 generic_pluginui.cc:523
+#: generic_pluginui.cc:817 panner_ui.cc:151
+msgid "Automation|Manual"
+msgstr "自动化 | 手册"
+
+#: automation_time_axis.cc:310 automation_time_axis.cc:371
+#: automation_time_axis.cc:559 editor.cc:1904 editor.cc:1981 editor_actions.cc:122
+#: editor_actions.cc:1920 gain_meter.cc:223 generic_pluginui.cc:99
+#: generic_pluginui.cc:526 generic_pluginui.cc:819 midi_time_axis.cc:1606
+#: midi_time_axis.cc:1609 midi_time_axis.cc:1612 panner_ui.cc:154
+msgid "Play"
+msgstr "播放"
+
+#: automation_time_axis.cc:312 automation_time_axis.cc:382
+#: automation_time_axis.cc:564 gain_meter.cc:226 generic_pluginui.cc:101
+#: generic_pluginui.cc:529 generic_pluginui.cc:821 panner_ui.cc:157
+msgid "Write"
+msgstr "写入"
+
+#: automation_time_axis.cc:314 automation_time_axis.cc:393
+#: automation_time_axis.cc:569 gain_meter.cc:229 generic_pluginui.cc:103
+#: generic_pluginui.cc:532 generic_pluginui.cc:823 panner_ui.cc:160
+msgid "Touch"
+msgstr "触碰"
+
+#: automation_time_axis.cc:404 generic_pluginui.cc:535 meter_patterns.cc:112
+msgid "???"
+msgstr "???"
+
+#: automation_time_axis.cc:445
+msgid "clear automation"
+msgstr "清除自动化"
+
+#: automation_time_axis.cc:543 editor_actions.cc:645 editor_markers.cc:902
+#: location_ui.cc:57 plugin_selector.cc:86 route_time_axis.cc:854
+msgid "Hide"
+msgstr "隐藏"
+
+#: automation_time_axis.cc:545
+msgid "Clear"
+msgstr "清除"
+
+#: automation_time_axis.cc:576
+msgid "State"
+msgstr "状态"
+
+#: automation_time_axis.cc:592
+msgid "Discrete"
+msgstr "离散"
+
+#: automation_time_axis.cc:598 export_format_dialog.cc:485
+msgid "Linear"
+msgstr "线性"
+
+#: automation_time_axis.cc:604 rhythm_ferret.cc:109 shuttle_control.cc:197
+msgid "Mode"
+msgstr "模式"
+
+#: bundle_manager.cc:182
+msgid "Disassociate"
+msgstr "分隔"
+
+#: bundle_manager.cc:186
+msgid "Edit Bundle"
+msgstr "编辑包裹"
+
+#: bundle_manager.cc:201
+msgid "Direction:"
+msgstr "方向:"
+
+#: bundle_manager.cc:206 bundle_manager.cc:210 engine_dialog.cc:662
+#: mixer_strip.cc:162 mixer_strip.cc:367 mixer_strip.cc:2240
+#: rc_option_editor.cc:2326
+msgid "Input"
+msgstr "输入"
 
-#: plugin_manager.cc:851
-msgid ""
-"linuxVST plugin %1 does not support processReplacing, and so cannot be used "
-"in %2 at this time"
-msgstr ""
+#: bundle_manager.cc:207 bundle_manager.cc:212 bundle_manager.cc:246
+#: engine_dialog.cc:664 mixer_strip.cc:166 mixer_strip.cc:371 mixer_strip.cc:2243
+#: rc_option_editor.cc:2330
+msgid "Output"
+msgstr "输出"
 
-#: plugin_manager.cc:1020
-msgid "unknown plugin status type \"%1\" - all entries ignored"
-msgstr ""
+#: bundle_manager.cc:265 editor.cc:1945 editor_actions.cc:94 editor_actions.cc:104
+#: rc_option_editor.cc:1087 rc_option_editor.cc:1094
+msgid "Edit"
+msgstr "编辑"
+
+#: bundle_manager.cc:266 editor.cc:5902 editor.cc:5930 editor_actions.cc:338
+#: editor_actions.cc:339 editor_actions.cc:405 plugin_ui.cc:420
+#: processor_box.cc:2458 route_time_axis.cc:859
+msgid "Delete"
+msgstr "删除"
+
+#: bundle_manager.cc:272 bundle_manager.cc:439 editor_route_groups.cc:97
+#: editor_routes.cc:206 midi_list_editor.cc:107 session_metadata_dialog.cc:646
+msgid "Name"
+msgstr "名称"
+
+#: bundle_manager.cc:283
+msgid "New"
+msgstr "新建"
+
+#: bundle_manager.cc:333
+msgid "Bundle"
+msgstr "包裹"
+
+#: bundle_manager.cc:418
+msgid "Add Channel"
+msgstr "添加声道"
+
+#: bundle_manager.cc:425
+msgid "Rename Channel"
+msgstr "重命名声道"
+
+#: configinfo.cc:28
+msgid "Build Configuration"
+msgstr "创建配置"
+
+#: control_point_dialog.cc:33
+msgid "Control point"
+msgstr "控制点"
+
+#: control_point_dialog.cc:45
+msgid "Value"
+msgstr "值"
+
+#: edit_note_dialog.cc:42
+msgid "Note"
+msgstr "音符"
+
+#: edit_note_dialog.cc:45
+msgid "Set selected notes to this channel"
+msgstr "设置已选中的音符为本声道"
+
+#: edit_note_dialog.cc:46
+msgid "Set selected notes to this pitch"
+msgstr "设置已选中的音符为本音高"
+
+#: edit_note_dialog.cc:47
+msgid "Set selected notes to this velocity"
+msgstr "设置已选中的音符为本力度"
+
+#: edit_note_dialog.cc:49
+msgid "Set selected notes to this time"
+msgstr "设置已选中的音符为本时间"
+
+#: edit_note_dialog.cc:51
+msgid "Set selected notes to this length"
+msgstr "设置已选中的音符为本长度"
+
+#: edit_note_dialog.cc:58 midi_list_editor.cc:105 patch_change_dialog.cc:90
+#: step_entry.cc:394
+msgid "Channel"
+msgstr "音轨"
+
+#: edit_note_dialog.cc:68
+msgid "Pitch"
+msgstr "音高"
+
+#: edit_note_dialog.cc:78 step_entry.cc:408
+msgid "Velocity"
+msgstr "力度"
+
+#: edit_note_dialog.cc:88 patch_change_dialog.cc:66
+msgid "Time"
+msgstr "时间"
+
+#: edit_note_dialog.cc:98 editor_regions.cc:115 export_timespan_selector.cc:378
+#: export_timespan_selector.cc:440 location_ui.cc:320 midi_list_editor.cc:115
+#: time_info_box.cc:108
+msgid "Length"
+msgstr "长度"
+
+#: edit_note_dialog.cc:165
+msgid "edit note"
+msgstr "编辑音符"
+
+#: editor.cc:147
+msgid "CD Frames"
+msgstr "CD 框架"
+
+#: editor.cc:148
+msgid "TC Frames"
+msgstr "TC 框架"
+
+#: editor.cc:149
+msgid "TC Seconds"
+msgstr "TC 秒"
+
+#: editor.cc:150
+msgid "TC Minutes"
+msgstr "TC 分"
 
-#: plugin_manager.cc:1037
-msgid "unknown plugin type \"%1\" - ignored"
-msgstr "位置插件类型 \"%1\" - 忽略之"
+#: editor.cc:151
+msgid "Seconds"
+msgstr "秒"
 
-#: port.cc:450
-msgid "could not reregister %1"
-msgstr "无法注册 %1."
+#: editor.cc:152
+msgid "Minutes"
+msgstr "分"
 
-#: port_insert.cc:43
-msgid "insert %1"
-msgstr "插入 %1"
+#: editor.cc:153 quantize_dialog.cc:37 quantize_dialog.cc:141
+msgid "Beats/128"
+msgstr "128拍"
 
-#: port_insert.cc:197
-msgid "XML node describing port insert is missing the `type' field"
-msgstr ""
+#: editor.cc:154 quantize_dialog.cc:38 quantize_dialog.cc:143
+msgid "Beats/64"
+msgstr "64拍"
 
-#: port_insert.cc:202
-msgid "non-port insert XML used for port plugin insert"
-msgstr ""
+#: editor.cc:155 quantize_dialog.cc:39 quantize_dialog.cc:145
+msgid "Beats/32"
+msgstr "32拍"
 
-#: port_manager.cc:287
-msgid ""
-"a port with the name \"%1\" already exists: check for duplicated track/bus "
-"names"
-msgstr ""
+#: editor.cc:156
+msgid "Beats/28"
+msgstr "28拍"
 
-#: port_manager.cc:289
-msgid ""
-"No more ports are available. You will need to stop %1 and restart with more "
-"ports if you need this many tracks."
-msgstr ""
+#: editor.cc:157
+msgid "Beats/24"
+msgstr "24拍"
 
-#: port_manager.cc:292
-msgid "AudioEngine: cannot register port \"%1\": %2"
-msgstr ""
+#: editor.cc:158
+msgid "Beats/20"
+msgstr "20拍"
 
-#: port_manager.cc:331
-msgid "unable to create port: %1"
-msgstr "无法创建端口: %1"
+#: editor.cc:159 quantize_dialog.cc:40 quantize_dialog.cc:147
+msgid "Beats/16"
+msgstr "16拍"
 
-#: port_manager.cc:418
-msgid "AudioEngine: cannot connect %1 (%2) to %3 (%4)"
-msgstr "音频引擎: 无法连接 %1 (%2) 到 %3 (%4)"
+#: editor.cc:160
+msgid "Beats/14"
+msgstr "14拍"
 
-#: port_manager.cc:470 port_manager.cc:471
-msgid "Re-establising port %1 failed"
-msgstr ""
+#: editor.cc:161
+msgid "Beats/12"
+msgstr "12拍"
 
-#: processor.cc:214
-msgid "No %1 property flag in element %2"
-msgstr ""
+#: editor.cc:162
+msgid "Beats/10"
+msgstr "10拍"
 
-#: processor.cc:223
-msgid "No child node with active property"
-msgstr ""
+#: editor.cc:163 quantize_dialog.cc:41 quantize_dialog.cc:149
+msgid "Beats/8"
+msgstr "8拍"
 
-#: rc_configuration.cc:91
-msgid "Loading system configuration file %1"
-msgstr "载入系统配置文件 %1"
+#: editor.cc:164
+msgid "Beats/7"
+msgstr "7拍"
 
-#: rc_configuration.cc:95
-msgid "%1: cannot read system configuration file \"%2\""
-msgstr "%1: 无法读取系统配置文件\"%2\""
+#: editor.cc:165
+msgid "Beats/6"
+msgstr "6拍"
 
-#: rc_configuration.cc:100
-msgid "%1: system configuration file \"%2\" not loaded successfully."
-msgstr "%1: 系统配置文件 \"%2\" 载入不成功"
+#: editor.cc:166
+msgid "Beats/5"
+msgstr "5拍"
 
-#: rc_configuration.cc:104
-msgid ""
-"Your system %1 configuration file is empty. This probably means that there "
-"was an error installing %1"
-msgstr ""
+#: editor.cc:167 quantize_dialog.cc:42 quantize_dialog.cc:151
+msgid "Beats/4"
+msgstr "4拍"
 
-#: rc_configuration.cc:119
-msgid "Loading user configuration file %1"
-msgstr "载入用户配置文件 %1"
+#: editor.cc:168 quantize_dialog.cc:43 quantize_dialog.cc:153
+msgid "Beats/3"
+msgstr "3拍"
 
-#: rc_configuration.cc:123
-msgid "%1: cannot read configuration file \"%2\""
-msgstr "%1: 无法读取配置文件 \"%2\""
+#: editor.cc:169 quantize_dialog.cc:44 quantize_dialog.cc:155
+msgid "Beats/2"
+msgstr "2拍"
 
-#: rc_configuration.cc:128
-msgid "%1: user configuration file \"%2\" not loaded successfully."
-msgstr "%1: 用户配置文件 \"%2\" 载入不成功"
+#: editor.cc:170 quantize_dialog.cc:45 quantize_dialog.cc:157
+msgid "Beats"
+msgstr "1拍"
 
-#: rc_configuration.cc:132
-msgid "your %1 configuration file is empty. This is not normal."
-msgstr ""
+#: editor.cc:171
+msgid "Bars"
+msgstr "小节"
 
-#: rc_configuration.cc:149
-msgid "Config file %1 not saved"
-msgstr "配置文件 %1 没有保存"
+#: editor.cc:172
+msgid "Marks"
+msgstr "标记"
 
-#: recent_sessions.cc:54
-msgid "cannot open recent session file %1 (%2)"
-msgstr "无法打开最近会话文件%1 (%2)"
+#: editor.cc:173
+msgid "Region starts"
+msgstr "区域开始"
 
-#: region_factory.cc:78 region_factory.cc:120 region_factory.cc:161
-#: region_factory.cc:203
-msgid ""
-"programming error: RegionFactory::create() called with unknown Region type"
-msgstr ""
+#: editor.cc:174
+msgid "Region ends"
+msgstr "区域结束"
 
-#: region_factory.cc:565
-msgid "%1 compound-%2 (%3)"
-msgstr ""
+#: editor.cc:175
+msgid "Region syncs"
+msgstr "区域同步"
 
-#: region_factory.cc:567
-msgid "%1 compound-%2.1 (%3)"
-msgstr ""
+#: editor.cc:176
+msgid "Region bounds"
+msgstr "区域边界"
 
-#: region_factory.cc:629
-msgid "cannot create new name for region \"%1\""
-msgstr ""
+#: editor.cc:181 editor_actions.cc:510
+msgid "No Grid"
+msgstr "无网格"
 
-#: resampled_source.cc:102
-msgid "Import: %1"
-msgstr "导入: %1"
+#: editor.cc:182 editor_actions.cc:511
+msgid "Grid"
+msgstr "网格"
 
-#: resampled_source.cc:132 srcfilesource.cc:75
-msgid "Import: src_new() failed : %1"
-msgstr "导入: src_new() 失败 : %1"
+#: editor.cc:183 editor_actions.cc:512
+msgid "Magnetic"
+msgstr "磁性吸附"
 
-#: return.cc:41
-msgid "return %1"
-msgstr "返回 %1"
+#: editor.cc:188 editor.cc:206 editor_actions.cc:121 editor_actions.cc:493
+msgid "Playhead"
+msgstr "指针"
 
-#: route.cc:1218 route.cc:2701
-msgid "unknown Processor type \"%1\"; ignored"
-msgstr ""
+#: editor.cc:189 editor_actions.cc:495
+msgid "Marker"
+msgstr "标记"
 
-#: route.cc:1240
-msgid "processor could not be created. Ignored."
-msgstr ""
+#: editor.cc:190 editor.cc:207 editor_actions.cc:494
+msgid "Mouse"
+msgstr "é¼ æ ‡"
 
-#: route.cc:2126 route.cc:2355
-msgid "Bad node sent to Route::set_state() [%1]"
-msgstr "损坏的符号发送至 Route::set_state() [%1]"
+#: editor.cc:195 editor_actions.cc:502
+msgid "Slide"
+msgstr "滑行"
 
-#: route.cc:2186
-msgid "Pannable state found for route (%1) without a panner!"
-msgstr ""
+#: editor.cc:196
+msgid "Splice"
+msgstr "拼接"
 
-#: route.cc:2260 route.cc:2264 route.cc:2469 route.cc:2473
-msgid "badly formed order key string in state file! [%1] ... ignored."
-msgstr ""
+#: editor.cc:197 editor_actions.cc:501
+msgid "Ripple"
+msgstr "波纹"
 
-#: route.cc:2479
-msgid "Converting deprecated order key for %1 using Editor order %2"
-msgstr ""
+#: editor.cc:198 editor_actions.cc:157 editor_actions.cc:503 editor_actions.cc:1789
+#: editor_markers.cc:905 editor_rulers.cc:260 location_ui.cc:58 mixer_strip.cc:195
+#: mixer_strip.cc:2028
+msgid "Lock"
+msgstr "锁定"
 
-#: route_group.cc:459
-msgid "You cannot subgroup MIDI tracks at this time"
-msgstr "此时你无法子分组MIDI声道"
+#: editor.cc:203 mono_panner_editor.cc:42
+msgid "Left"
+msgstr "å·¦"
+
+#: editor.cc:204 mono_panner_editor.cc:47
+msgid "Right"
+msgstr "右"
+
+#: editor.cc:205
+msgid "Center"
+msgstr "中"
+
+#: editor.cc:208 editor.cc:3231
+msgid "Edit point"
+msgstr "编辑点"
+
+#: editor.cc:214
+msgid "Mushy"
+msgstr "模糊"
+
+#: editor.cc:215
+msgid "Smooth"
+msgstr "平滑"
+
+#: editor.cc:216
+msgid "Balanced multitimbral mixture"
+msgstr "平衡的多重音色混响乐"
+
+#: editor.cc:217
+msgid "Unpitched percussion with stable notes"
+msgstr "带有稳定音符的未定音高打击乐"
+
+#: editor.cc:218
+msgid "Crisp monophonic instrumental"
+msgstr "欢快的单声调乐器"
+
+#: editor.cc:219
+msgid "Unpitched solo percussion"
+msgstr "未定音高的独奏打击乐"
+
+#: editor.cc:220
+msgid "Resample without preserving pitch"
+msgstr "不保持音高的重新采样"
+
+#: editor.cc:256
+msgid "Mins:Secs"
+msgstr "分:秒"
+
+#: editor.cc:262
+msgid "Location Markers"
+msgstr "位置标记"
+
+#: editor.cc:263
+msgid "Range Markers"
+msgstr "范围标记"
+
+#: editor.cc:264
+msgid "Loop/Punch Ranges"
+msgstr "循环 / 切换范围"
+
+#: editor.cc:265 editor_actions.cc:565
+msgid "CD Markers"
+msgstr "CD标记"
+
+#: editor.cc:266
+msgid "Video Timeline"
+msgstr "视频时间线"
+
+#: editor.cc:283
+msgid "mode"
+msgstr "模式"
+
+#: editor.cc:459 editor_actions.cc:114 editor_actions.cc:564
+msgid "Markers"
+msgstr "标记"
+
+#: editor.cc:577 rc_option_editor.cc:1939
+msgid "Regions"
+msgstr "区域"
+
+#: editor.cc:578
+msgid "Tracks & Busses"
+msgstr "音轨 & 总线"
+
+#: editor.cc:579
+msgid "Snapshots"
+msgstr "å¿«ç…§"
+
+#: editor.cc:580
+msgid "Track & Bus Groups"
+msgstr "音轨 & 总线分组"
+
+#: editor.cc:581
+msgid "Ranges & Marks"
+msgstr "范围 & 标记"
+
+#: editor.cc:728 editor.cc:5754 rc_option_editor.cc:1619 rc_option_editor.cc:1627
+#: rc_option_editor.cc:1635 rc_option_editor.cc:1643 rc_option_editor.cc:1667
+#: rc_option_editor.cc:1679 rc_option_editor.cc:1681 rc_option_editor.cc:1689
+#: rc_option_editor.cc:1697 rc_option_editor.cc:1717 rc_option_editor.cc:1729
+#: rc_option_editor.cc:1731 rc_option_editor.cc:1733 rc_option_editor.cc:1741
+#: rc_option_editor.cc:1749 rc_option_editor.cc:1757 rc_option_editor.cc:1772
+#: rc_option_editor.cc:1776 rc_option_editor.cc:1800
+msgid "Editor"
+msgstr "编辑器"
+
+#: editor.cc:1331 editor.cc:4735 editor_actions.cc:134 editor_actions.cc:1865
+msgid "Loop"
+msgstr "循环"
+
+#: editor.cc:1337 editor.cc:4762 editor_actions.cc:135 time_info_box.cc:68
+msgid "Punch"
+msgstr "切换"
+
+#: editor.cc:1449 rc_option_editor.cc:1661
+msgid "Linear (for highly correlated material)"
+msgstr "线性(高度相关的材料)"
+
+#: editor.cc:1459 rc_option_editor.cc:1662
+msgid "Constant power"
+msgstr "恒定功率"
+
+#: editor.cc:1468 rc_option_editor.cc:1663
+msgid "Symmetric"
+msgstr "对称"
+
+#: editor.cc:1478 rc_option_editor.cc:1664
+msgid "Slow"
+msgstr "æ…¢"
+
+#: editor.cc:1487 rc_option_editor.cc:1665 sfdb_ui.cc:1771 sfdb_ui.cc:1881
+msgid "Fast"
+msgstr "å¿«"
+
+#: editor.cc:1509 editor.cc:1534
+msgid "Deactivate"
+msgstr "取消激活"
+
+#: editor.cc:1511 editor.cc:1536
+msgid "Activate"
+msgstr "激活"
+
+#: editor.cc:1637 editor.cc:1645 editor_ops.cc:3824
+msgid "Freeze"
+msgstr "冻结"
+
+#: editor.cc:1641
+msgid "Unfreeze"
+msgstr "取消冻结"
+
+#: editor.cc:1780
+msgid "Selected Regions"
+msgstr "已选择的区域"
+
+#: editor.cc:1816 editor_markers.cc:940
+msgid "Play Range"
+msgstr "播放范围"
+
+#: editor.cc:1817 editor_markers.cc:943
+msgid "Loop Range"
+msgstr "循环范围"
+
+#: editor.cc:1820 editor_markers.cc:950
+msgid "Zoom to Range"
+msgstr "缩放至整个范围"
+
+#: editor.cc:1829 editor_actions.cc:369
+msgid "Move Range Start to Previous Region Boundary"
+msgstr "移动范围起点到上一个区域边界"
+
+#: editor.cc:1836 editor_actions.cc:376
+msgid "Move Range Start to Next Region Boundary"
+msgstr "移动范围起点到下一个区域边界"
+
+#: editor.cc:1843 editor_actions.cc:383
+msgid "Move Range End to Previous Region Boundary"
+msgstr "移动范围终点到上一个区域边界"
+
+#: editor.cc:1850 editor_actions.cc:390
+msgid "Move Range End to Next Region Boundary"
+msgstr "移动范围终点到下一个区域边界"
+
+#: editor.cc:1856 editor_actions.cc:133 editor_actions.cc:325
+msgid "Separate"
+msgstr "分离"
+
+#: editor.cc:1857
+msgid "Convert to Region in Region List"
+msgstr "在区域列表转换至区域"
+
+#: editor.cc:1860 editor_markers.cc:970
+msgid "Select All in Range"
+msgstr "在范围内全选"
+
+#: editor.cc:1863 editor_actions.cc:297
+msgid "Set Loop from Selection"
+msgstr "从已选择部分设置循环"
+
+#: editor.cc:1864 editor_actions.cc:298
+msgid "Set Punch from Selection"
+msgstr "从已选择部分设置切换"
 
-#: rb_effect.cc:229 rb_effect.cc:269
-msgid "tempoize: error reading data from %1 at %2 (wanted %3, got %4)"
-msgstr ""
+#: editor.cc:1865 editor_actions.cc:299
+msgid "Set Session Start/End from Selection"
+msgstr "从已选择部分设置会话起点/终点"
 
-#: rb_effect.cc:298 rb_effect.cc:320
-msgid "error writing tempo-adjusted data to %1"
-msgstr ""
+#: editor.cc:1868
+msgid "Add Range Markers"
+msgstr "添加范围标记"
 
-#: send.cc:61
-msgid "aux %1"
-msgstr ""
+#: editor.cc:1871
+msgid "Crop Region to Range"
+msgstr "裁剪区域到范围"
 
-#: send.cc:65
-msgid "send %1"
-msgstr "发送 %1"
+#: editor.cc:1872
+msgid "Fill Range with Region"
+msgstr "用区域填充范围"
 
-#: send.cc:67
-msgid "programming error: send created using role %1"
-msgstr ""
+#: editor.cc:1873 editor_actions.cc:311
+msgid "Duplicate Range"
+msgstr "复制范围"
 
-#: session.cc:357
-msgid "Connect to engine"
-msgstr "连接到引擎"
+#: editor.cc:1876
+msgid "Consolidate Range"
+msgstr "合并范围"
 
-#: session.cc:362
-msgid "Session loading complete"
-msgstr "会话载入完成"
+#: editor.cc:1877
+msgid "Consolidate Range With Processing"
+msgstr "合并范围并处理"
 
-#: session.cc:434
-msgid "Set up LTC"
-msgstr ""
+#: editor.cc:1878
+msgid "Bounce Range to Region List"
+msgstr "欢跳弹奏范围到区域列表"
 
-#: session.cc:436
-msgid "Set up Click"
-msgstr ""
+#: editor.cc:1879
+msgid "Bounce Range to Region List With Processing"
+msgstr "欢跳弹奏范围到区域列表并处理"
 
-#: session.cc:438
-msgid "Set up standard connections"
-msgstr "设置标准连接"
+#: editor.cc:1880 editor_markers.cc:953
+msgid "Export Range..."
+msgstr "导出范围…"
 
-#: session.cc:664
-msgid "could not setup Click I/O"
-msgstr ""
+#: editor.cc:1882
+msgid "Export Video Range..."
+msgstr "导出视频范围…"
 
-#: session.cc:727
-#, c-format
-msgid "out %s"
-msgstr ""
+#: editor.cc:1898 editor.cc:1979 editor_actions.cc:303
+msgid "Play From Edit Point"
+msgstr "从编辑点播放"
 
-#: session.cc:729
-#, c-format
-msgid "out %<PRIu32>"
-msgstr ""
+#: editor.cc:1899 editor.cc:1980
+msgid "Play From Start"
+msgstr "从起点播放"
 
-#: session.cc:744
-#, c-format
-msgid "out %<PRIu32>+%<PRIu32>"
-msgstr ""
+#: editor.cc:1900
+msgid "Play Region"
+msgstr "播放区域"
 
-#: session.cc:761
-#, c-format
-msgid "in %s"
-msgstr ""
+#: editor.cc:1902
+msgid "Loop Region"
+msgstr "循环区域"
 
-#: session.cc:763
-#, c-format
-msgid "in %<PRIu32>"
-msgstr ""
+#: editor.cc:1912 editor.cc:1989
+msgid "Select All in Track"
+msgstr "在音轨上全选所有"
 
-#: session.cc:778
-#, c-format
-msgid "in %<PRIu32>+%<PRIu32>"
-msgstr ""
+#: editor.cc:1913 editor.cc:1990 editor_actions.cc:194
+msgid "Select All Objects"
+msgstr "全选所有对象物体"
 
-#: session.cc:852
-msgid "cannot connect master output %1 to %2"
-msgstr ""
+#: editor.cc:1914 editor.cc:1991
+msgid "Invert Selection in Track"
+msgstr "在音轨反选"
 
-#: session.cc:921
-msgid "Monitor"
-msgstr ""
+#: editor.cc:1915 editor.cc:1992 editor_actions.cc:197
+msgid "Invert Selection"
+msgstr "反选"
 
-#: session.cc:966
-msgid "cannot connect control input %1 to %2"
-msgstr ""
+#: editor.cc:1917
+msgid "Set Range to Loop Range"
+msgstr "设置范围到循环范围"
 
-#: session.cc:986
-msgid "The preferred I/O for the monitor bus (%1) cannot be found"
-msgstr ""
+#: editor.cc:1918
+msgid "Set Range to Punch Range"
+msgstr "设置范围到切换区间"
 
-#: session.cc:1017
-msgid "cannot connect control output %1 to %2"
-msgstr ""
+#: editor.cc:1920 editor.cc:1994 editor_actions.cc:199 editor_actions.cc:200
+msgid "Select All After Edit Point"
+msgstr "全选编辑点后所有"
 
-#: session.cc:1085
-msgid "cannot create Auditioner: no auditioning of regions possible"
-msgstr ""
+#: editor.cc:1921 editor.cc:1995 editor_actions.cc:201 editor_actions.cc:202
+msgid "Select All Before Edit Point"
+msgstr "全选编辑前所有"
 
-#: session.cc:1270
-msgid "Session: you can't use that location for auto punch (start <= end)"
-msgstr ""
+#: editor.cc:1922 editor.cc:1996
+msgid "Select All After Playhead"
+msgstr "全选指针后所有"
 
-#: session.cc:1297
-msgid "Session: you can't use that location for session start/end)"
-msgstr ""
+#: editor.cc:1923 editor.cc:1997
+msgid "Select All Before Playhead"
+msgstr "全选指针前所有"
 
-#: session.cc:1329
-msgid ""
-"You cannot use this location for auto-loop because it has zero or negative "
-"length"
-msgstr ""
+#: editor.cc:1924
+msgid "Select All Between Playhead and Edit Point"
+msgstr "全选指针和编辑点之间所有"
 
-#: session.cc:1497
-msgid "programming error: session range removed!"
-msgstr ""
+#: editor.cc:1925
+msgid "Select All Within Playhead and Edit Point"
+msgstr "全选指针和编辑点内部所有"
 
-#: session.cc:1751
-msgid "feedback loop setup between %1 and %2"
-msgstr ""
+#: editor.cc:1926
+msgid "Select Range Between Playhead and Edit Point"
+msgstr "选择指针和编辑点之间范围"
 
-#: session.cc:2047
-msgid "Session: could not create new midi track."
-msgstr ""
+#: editor.cc:1928 editor.cc:1999 editor_actions.cc:131 editor_actions.cc:132
+msgid "Select"
+msgstr "选择"
 
-#: session.cc:2053
-msgid ""
-"No more JACK ports are available. You will need to stop %1 and restart JACK "
-"with more ports if you need this many tracks."
-msgstr ""
+#: editor.cc:1936 editor.cc:2007 editor_actions.cc:337 processor_box.cc:2451
+msgid "Cut"
+msgstr "剪切"
 
-#: session.cc:2239 session.cc:2242
-msgid "Audio"
-msgstr "音频"
+#: editor.cc:1937 editor.cc:2008 editor_actions.cc:341 processor_box.cc:2454
+msgid "Copy"
+msgstr "复制"
 
-#: session.cc:2266 session.cc:2274 session.cc:2352 session.cc:2360
-msgid "cannot configure %1 in/%2 out configuration for new audio track"
-msgstr ""
+#: editor.cc:1938 editor.cc:2009 editor_actions.cc:342 processor_box.cc:2462
+msgid "Paste"
+msgstr "粘贴"
 
-#: session.cc:2297
-msgid "Session: could not create new audio track."
-msgstr ""
+#: editor.cc:1942 editor_actions.cc:91
+msgid "Align"
+msgstr "对齐"
 
-#: session.cc:2330 session.cc:2333
-msgid "Bus"
-msgstr "总线"
+#: editor.cc:1943
+msgid "Align Relative"
+msgstr "对齐相关"
 
-#: session.cc:2383
-msgid "Session: could not create new audio route."
-msgstr ""
+#: editor.cc:1950
+msgid "Insert Selected Region"
+msgstr "插入已选择的区域"
 
-#: session.cc:2443 session.cc:2453
-msgid "Session: UINT_MAX routes? impossible!"
-msgstr ""
+#: editor.cc:1951
+msgid "Insert Existing Media"
+msgstr "插入已存在的媒体"
 
-#: session.cc:2475
-msgid "Session: cannot create track/bus from template description"
-msgstr ""
+#: editor.cc:1960 editor.cc:2016
+msgid "Nudge Entire Track Later"
+msgstr "向后微调整个音轨"
 
-#: session.cc:2501
-msgid "Session: could not create new route from template"
-msgstr ""
+#: editor.cc:1961 editor.cc:2017
+msgid "Nudge Track After Edit Point Later"
+msgstr "向后微调编辑点以后的音轨"
 
-#: session.cc:2531
-msgid "Adding new tracks/busses failed"
-msgstr ""
+#: editor.cc:1962 editor.cc:2018
+msgid "Nudge Entire Track Earlier"
+msgstr "向前微调整个音轨"
 
-#: session.cc:3671
-msgid "Merging embedded file %1: name collision AND md5 hash collision!"
-msgstr ""
+#: editor.cc:1963 editor.cc:2019
+msgid "Nudge Track After Edit Point Earlier"
+msgstr "向前微调编辑点以后的音轨"
 
-#: session.cc:3801 session.cc:3874
-msgid "There are already %1 recordings for %2, which I consider too many."
-msgstr ""
+#: editor.cc:1965 editor.cc:2021
+msgid "Nudge"
+msgstr "微调"
 
-#: session.cc:4316
-msgid "send ID %1 appears to be in use already"
-msgstr ""
+#: editor.cc:2235
+msgid "Playhead position stored with a negative value - ignored (use zero instead)"
+msgstr "指针位置存储为一个负值——忽略(用零代替)"
 
-#: session.cc:4328
-msgid "aux send ID %1 appears to be in use already"
-msgstr ""
+#: editor.cc:3006 editor.cc:3707 editor.cc:3778 midi_channel_selector.cc:157
+#: midi_channel_selector.cc:395 midi_channel_selector.cc:431
+msgid "All"
+msgstr "所有"
 
-#: session.cc:4340
-msgid "return ID %1 appears to be in use already"
-msgstr ""
+#: editor.cc:3210
+msgid "Smart Mode (add Range functions to Grab mode)"
+msgstr "智能模式(添加范围功能到抓取模式)"
 
-#: session.cc:4352
-msgid "insert ID %1 appears to be in use already"
-msgstr ""
+#: editor.cc:3211
+msgid "Grab Mode (select/move objects)"
+msgstr "抓取模式(选择/移动对象物体)"
 
-#: session.cc:4477
-msgid "Cannot write a range where end <= start (e.g. %1 <= %2)"
-msgstr ""
+#: editor.cc:3212
+msgid "Cut Mode (split regions)"
+msgstr "切割模式(拆分区域)"
 
-#: session.cc:4486
-msgid "Cannot write a range with no data."
-msgstr ""
+#: editor.cc:3213
+msgid "Range Mode (select time ranges)"
+msgstr "范围模式(选择时间范围)"
 
-#: session.cc:4528
-msgid "cannot create new file \"%1\" for %2"
-msgstr ""
+#: editor.cc:3214
+msgid "Draw Mode (draw and edit gain/notes/automation)"
+msgstr "描绘模式(描绘和编辑增益/音符/自动化)"
 
-#: session_click.cc:161
-msgid "cannot open click soundfile %1 (%2)"
-msgstr "无法打开click声音文件 %1 (%2)"
+#: editor.cc:3215
+msgid "Stretch Mode (time-stretch audio and midi regions, preserving pitch)"
+msgstr "延伸模式(时间延伸音频和MIDI区域,保持音高)"
 
-#: session_click.cc:174
-msgid "cannot read data from click soundfile"
-msgstr ""
+#: editor.cc:3216
+msgid "Audition Mode (listen to regions)"
+msgstr "监听模式(试听区域)"
 
-#: session_command.cc:87
-msgid "Tried to reconstitute a MementoCommand with no contents, failing. id=%1"
-msgstr ""
+#: editor.cc:3217
+msgid "Internal Edit Mode (edit notes and gain curves inside regions)"
+msgstr "内部编辑模式(在区域内编辑音符和增益曲线)"
 
-#: session_command.cc:148
+#: editor.cc:3218
 msgid ""
-"could not reconstitute MementoCommand from XMLNode. object type = %1 id = %2"
+"Groups: click to (de)activate\n"
+"Context-click for other operations"
 msgstr ""
+"分组:点击(不)启用\n"
+"右键点击其它操作"
 
-#: session_command.cc:177
-msgid ""
-"could not reconstitute StatefulDiffCommand from XMLNode. object type = %1 id "
-"= %2"
-msgstr ""
+#: editor.cc:3219
+msgid "Nudge Region/Selection Later"
+msgstr "向后微调区域/已选择部分"
 
-#: session_configuration.cc:150
-msgid "%1: cannot part default session options \"%2\""
-msgstr ""
+#: editor.cc:3220
+msgid "Nudge Region/Selection Earlier"
+msgstr "向前微调区域/已选择部分"
 
-#: session_configuration.cc:156
-msgid "Invalid session default XML Root."
-msgstr ""
+#: editor.cc:3221 editor_actions.cc:262
+msgid "Zoom In"
+msgstr "放大"
 
-#: session_configuration.cc:164
-msgid "Loaded custom session defaults."
-msgstr ""
+#: editor.cc:3222 editor_actions.cc:261
+msgid "Zoom Out"
+msgstr "缩小"
 
-#: session_configuration.cc:166
-msgid "Found no session defaults in XML file."
-msgstr ""
+#: editor.cc:3223
+msgid "Zoom to Time Scale"
+msgstr "缩放至时间比例"
 
-#: session_configuration.cc:192
-msgid "Could not save session options"
-msgstr ""
+#: editor.cc:3224 editor.cc:3729 editor_actions.cc:263
+msgid "Zoom to Session"
+msgstr "缩放至整个会话"
 
-#: session_directory.cc:59
-msgid "Cannot create Session directory at path %1 Error: %2"
-msgstr "无法创建会话目录在路径 %1 错误: %2"
+#: editor.cc:3225
+msgid "Zoom focus"
+msgstr "缩放焦点"
 
-#: session_directory.cc:76
-msgid "Session subdirectory does not exist at path %1"
-msgstr "会话子目录不存在于路径 %1"
+#: editor.cc:3226
+msgid "Expand Tracks"
+msgstr "扩展音轨"
 
-#: session_events.cc:234
-msgid "Session: cannot have two events of type %1 at the same frame (%2)."
-msgstr ""
+#: editor.cc:3227
+msgid "Shrink Tracks"
+msgstr "收缩音轨"
 
-#: session_export.cc:125
-msgid "%1: cannot seek to %2 for export"
-msgstr ""
+#: editor.cc:3228
+msgid "Number of visible tracks"
+msgstr "可见音轨数量"
 
-#: session_export.cc:182
-msgid "Export ended unexpectedly: %1"
-msgstr ""
+#: editor.cc:3229
+msgid "Snap/Grid Units"
+msgstr "吸附/网格单位"
+
+#: editor.cc:3230
+msgid "Snap/Grid Mode"
+msgstr "吸附/网格模式"
 
-#: session_ltc.cc:221
+#: editor.cc:3232
+msgid "Edit Mode"
+msgstr "编辑模式"
+
+#: editor.cc:3233
 msgid ""
-"LTC encoder: invalid framerate - LTC encoding is disabled for the remainder "
-"of this session."
+"Nudge Clock\n"
+"(controls distance used to nudge regions and selections)"
 msgstr ""
+"微调计时器\n"
+"(使用微调区域和已选择部分来控制距离)"
 
-#: session_midi.cc:520
-msgid "Session: cannot send quarter-frame MTC message (%1)"
-msgstr ""
+#: editor.cc:3501 editor_actions.cc:313
+msgid "Command|Undo"
+msgstr "命令|撤销"
 
-#: session_playlists.cc:378 session_playlists.cc:397
-msgid "Session: cannot create Playlist from XML description."
-msgstr "会话: 无法从XML描述符创建播放列表."
+#: editor.cc:3503
+msgid "Command|Undo (%1)"
+msgstr "命令|撤销(%1)"
 
-#: session_process.cc:136
-msgid "Session: error in no roll for %1"
-msgstr ""
+#: editor.cc:3510 editor_actions.cc:315 editor_actions.cc:316 editor_actions.cc:317
+msgid "Redo"
+msgstr "重做"
 
-#: session_process.cc:1174
-msgid "Programming error: illegal event type in process_event (%1)"
-msgstr ""
+#: editor.cc:3512
+msgid "Redo (%1)"
+msgstr "重做(%1)"
 
-#: session_state.cc:179
-msgid "solo cut control (dB)"
-msgstr ""
+#: editor.cc:3531 editor.cc:3555 editor_actions.cc:110 editor_actions.cc:1846
+msgid "Duplicate"
+msgstr "复制"
 
-#: session_state.cc:203
-msgid "Set block size and sample rate"
-msgstr ""
+#: editor.cc:3532
+msgid "Number of duplications:"
+msgstr "复制数量:"
 
-#: session_state.cc:208
-msgid "Using configuration"
-msgstr "使用配置"
+#: editor.cc:3706 route_group_dialog.cc:51 time_info_box.cc:67
+msgid "Selection"
+msgstr "已选择部分"
 
-#: session_state.cc:331
-msgid "Reset Remote Controls"
-msgstr ""
+#: editor.cc:3709
+msgid "Fit 1 track"
+msgstr "匹配音轨"
 
-#: session_state.cc:423
-msgid "Session: cannot create session peakfile folder \"%1\" (%2)"
-msgstr "会话: 无法创建会话峰文件的文件夹 \"%1\" (%2)"
+#: editor.cc:3710
+msgid "Fit 2 tracks"
+msgstr "匹配2音轨"
 
-#: session_state.cc:430
-msgid "Session: cannot create session sounds dir \"%1\" (%2)"
-msgstr ""
+#: editor.cc:3711
+msgid "Fit 4 tracks"
+msgstr "匹配4音轨"
 
-#: session_state.cc:437
-msgid "Session: cannot create session midi dir \"%1\" (%2)"
-msgstr ""
+#: editor.cc:3712
+msgid "Fit 8 tracks"
+msgstr "匹配8音轨"
 
-#: session_state.cc:444
-msgid "Session: cannot create session dead sounds folder \"%1\" (%2)"
-msgstr ""
+#: editor.cc:3713
+msgid "Fit 16 tracks"
+msgstr "匹配16音轨"
 
-#: session_state.cc:451
-msgid "Session: cannot create session export folder \"%1\" (%2)"
-msgstr "会话: 无法创建会话导出文件夹 \"%1\" (%2)"
+#: editor.cc:3714
+msgid "Fit 24 tracks"
+msgstr "匹配24音轨"
 
-#: session_state.cc:458
-msgid "Session: cannot create session analysis folder \"%1\" (%2)"
-msgstr "会话: 无法创建会话分析文件夹 \"%1\" (%2)"
+#: editor.cc:3715
+msgid "Fit 32 tracks"
+msgstr "匹配32音轨"
 
-#: session_state.cc:465
-msgid "Session: cannot create session plugins folder \"%1\" (%2)"
-msgstr "会话: 无法创建会话插件文件夹 \"%1\" (%2)"
+#: editor.cc:3716
+msgid "Fit 48 tracks"
+msgstr "匹配48音轨"
 
-#: session_state.cc:472
-msgid "Session: cannot create session externals folder \"%1\" (%2)"
-msgstr ""
+#: editor.cc:3717
+msgid "Fit All tracks"
+msgstr "匹配所有音轨"
 
-#: session_state.cc:486
-msgid "Session: cannot create session folder \"%1\" (%2)"
-msgstr "会话: 无法创建会话文件夹 \"%1\" (%2)"
+#: editor.cc:3718
+msgid "Fit Selection"
+msgstr "匹配已选择部分"
 
-#: session_state.cc:520
-msgid "Could not open %1 for writing session template"
-msgstr ""
+#: editor.cc:3720
+msgid "Zoom to 10 ms"
+msgstr "缩放至 10 毫秒"
 
-#: session_state.cc:526
-msgid "Could not open session template %1 for reading"
-msgstr ""
+#: editor.cc:3721
+msgid "Zoom to 100 ms"
+msgstr "缩放至 100 毫秒"
 
-#: session_state.cc:545
-msgid "Master"
-msgstr ""
+#: editor.cc:3722
+msgid "Zoom to 1 sec"
+msgstr "缩放至 1 秒"
 
-#: session_state.cc:606
-msgid "Could not remove pending capture state at path \"%1\" (%2)"
-msgstr ""
+#: editor.cc:3723
+msgid "Zoom to 10 sec"
+msgstr "缩放至 10 秒"
 
-#: session_state.cc:630
-msgid "could not rename snapshot %1 to %2 (%3)"
-msgstr "无法重命名快照 %1 到 %2 (%3)"
+#: editor.cc:3724
+msgid "Zoom to 1 min"
+msgstr "缩放至 1 分钟"
 
-#: session_state.cc:658
-msgid "Could not remove session file at path \"%1\" (%2)"
-msgstr ""
+#: editor.cc:3725
+msgid "Zoom to 10 min"
+msgstr "缩放至 10 分钟"
 
-#: session_state.cc:685
-msgid ""
-"the %1 audio engine is not connected and state saving would lose all I/O "
-"connections. Session not saved"
-msgstr ""
+#: editor.cc:3726
+msgid "Zoom to 1 hour"
+msgstr "缩放至 1 小时"
 
-#: session_state.cc:736
-msgid "state could not be saved to %1"
-msgstr ""
+#: editor.cc:3727
+msgid "Zoom to 8 hours"
+msgstr "缩放至 8 小时"
 
-#: session_state.cc:738 session_state.cc:749
-msgid "Could not remove temporary session file at path \"%1\" (%2)"
-msgstr ""
+#: editor.cc:3728
+msgid "Zoom to 24 hours"
+msgstr "缩放至 24 小时"
 
-#: session_state.cc:746
-msgid "could not rename temporary session file %1 to %2 (%3)"
-msgstr ""
+#: editor.cc:3730
+msgid "Zoom to Range/Region Selection"
+msgstr "缩放至范围/区域已选择部分"
 
-#: session_state.cc:814
-msgid "%1: session file \"%2\" doesn't exist!"
+#: editor.cc:3800
+msgid "*"
 msgstr ""
 
-#: session_state.cc:826
-msgid "Could not understand session file %1"
-msgstr ""
+#: editor.cc:4120
+msgid "Playlist Deletion"
+msgstr "播放列表删除部分"
 
-#: session_state.cc:835
-msgid "Session file %1 is not a session"
-msgstr "会话文件 %1 不是一个会话"
+#: editor.cc:4121
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If it is kept, its audio files will not be cleaned.\n"
+"If it is deleted, audio files used by it alone will be cleaned."
+msgstr ""
+"播放列表 %1 当前未被使用。\n"
+"如果保留它,它的音频文件将不会被清除。\n"
+"如果删除它,它单独使用过的音频文件将会被清除。"
+
+#: editor.cc:4131
+msgid "Delete Playlist"
+msgstr "删除播放列表"
+
+#: editor.cc:4132
+msgid "Keep Playlist"
+msgstr "保留播放列表"
+
+#: editor.cc:4133 editor_audio_import.cc:594 editor_ops.cc:6174
+#: engine_dialog.cc:2083 sfdb_freesound_mootcher.cc:69 processor_box.cc:2219
+#: processor_box.cc:2244
+msgid "Cancel"
+msgstr "取消"
+
+#: editor.cc:4275
+msgid "new playlists"
+msgstr "新建播放列表"
+
+#: editor.cc:4291
+msgid "copy playlists"
+msgstr "复制播放列表"
+
+#: editor.cc:4306
+msgid "clear playlists"
+msgstr "清除播放列表"
+
+#: editor.cc:5046
+msgid "Please wait while %1 loads visual data."
+msgstr "请等候 %1 载入可见数据。"
+
+#: editor.cc:5901 editor.cc:5932 editor_markers.cc:985 panner_ui.cc:410
+#: processor_box.cc:2482
+msgid "Edit..."
+msgstr "编辑…"
+
+#: editor.cc:5934 editor_actions.cc:1941
+msgid "Legatize"
+msgstr " 合法化"
+
+#: editor.cc:5936 editor_actions.cc:1940
+msgid "Quantize..."
+msgstr "量化…"
+
+#: editor.cc:5938 editor_actions.cc:1943
+msgid "Remove Overlap"
+msgstr "移除重叠"
+
+#: editor.cc:5940 editor_actions.cc:1942
+msgid "Transform..."
+msgstr "变换…"
+
+#: editor_actions.cc:92
+msgid "Autoconnect"
+msgstr "自动连接"
+
+#: editor_actions.cc:93
+msgid "Crossfades"
+msgstr "淡入淡出(交叉淡化)"
+
+#: editor_actions.cc:95
+msgid "Move Selected Marker"
+msgstr "移动已选择的标记"
+
+#: editor_actions.cc:96
+msgid "Select Range Operations"
+msgstr "选择范围操作"
+
+#: editor_actions.cc:97
+msgid "Select Regions"
+msgstr "选择区域"
+
+#: editor_actions.cc:98
+msgid "Edit Point"
+msgstr "编辑点"
+
+#: editor_actions.cc:99
+msgid "Fade"
+msgstr "淡化"
+
+#: editor_actions.cc:100
+msgid "Latch"
+msgstr "短锁"
+
+#: editor_actions.cc:101 editor_regions.cc:112 region_editor.cc:46
+msgid "Region"
+msgstr "区域"
+
+#: editor_actions.cc:102
+msgid "Layering"
+msgstr "分层"
+
+#: editor_actions.cc:103 editor_regions.cc:113 stereo_panner_editor.cc:44
+msgid "Position"
+msgstr "位置"
+
+#: editor_actions.cc:105 gain_meter.cc:156 gain_meter.cc:825 panner_ui.cc:178
+#: panner_ui.cc:635
+msgid "Trim"
+msgstr "修剪"
+
+#: editor_actions.cc:106 editor_actions.cc:126 route_group_dialog.cc:46
+msgid "Gain"
+msgstr "增益"
+
+#: editor_actions.cc:107 editor_actions.cc:563
+msgid "Ranges"
+msgstr "范围"
+
+#: editor_actions.cc:108 editor_actions.cc:1842 session_option_editor.cc:135
+#: session_option_editor.cc:144 session_option_editor.cc:151
+msgid "Fades"
+msgstr "淡化"
+
+#: editor_actions.cc:111
+msgid "Link"
+msgstr "链接"
+
+#: editor_actions.cc:112 editor_actions.cc:145
+msgid "Zoom Focus"
+msgstr "缩放焦点"
+
+#: editor_actions.cc:113
+msgid "Locate to Markers"
+msgstr "定位到标记"
+
+#: editor_actions.cc:115
+msgid "Meter falloff"
+msgstr "节拍衰减"
+
+#: editor_actions.cc:116
+msgid "Meter hold"
+msgstr "节拍保持"
+
+#: editor_actions.cc:117 session_option_editor.cc:321
+msgid "MIDI Options"
+msgstr "MIDI选项"
+
+#: editor_actions.cc:118
+msgid "Misc Options"
+msgstr "其它选项"
+
+#: editor_actions.cc:119 rc_option_editor.cc:1809 route_group_dialog.cc:54
+#: session_option_editor.cc:243 session_option_editor.cc:250
+msgid "Monitoring"
+msgstr "监控中"
 
-#: session_state.cc:1147
-msgid "programming error: Session: incorrect XML node sent to set_state()"
-msgstr ""
+#: editor_actions.cc:120
+msgid "Active Mark"
+msgstr "启用标记"
 
-#: session_state.cc:1201
-msgid "Session: XML state has no options section"
-msgstr ""
+#: editor_actions.cc:123
+msgid "Primary Clock"
+msgstr "主计时器"
 
-#: session_state.cc:1206
-msgid "Session: XML state has no metadata section"
-msgstr ""
+#: editor_actions.cc:124
+msgid "Pullup / Pulldown"
+msgstr "向上拖动/向下拖动"
 
-#: session_state.cc:1217
-msgid "Session: XML state has no sources section"
-msgstr ""
+#: editor_actions.cc:125
+msgid "Region operations"
+msgstr "区域操作"
 
-#: session_state.cc:1224
-msgid "Session: XML state has no Tempo Map section"
-msgstr ""
+#: editor_actions.cc:127 ruler_dialog.cc:28
+msgid "Rulers"
+msgstr "标尺"
 
-#: session_state.cc:1231
-msgid "Session: XML state has no locations section"
-msgstr ""
+#: editor_actions.cc:128
+msgid "Views"
+msgstr "视图"
 
-#: session_state.cc:1244
-msgid "Session: XML state has no Regions section"
-msgstr ""
+#: editor_actions.cc:129
+msgid "Scroll"
+msgstr "滚动"
 
-#: session_state.cc:1251
-msgid "Session: XML state has no playlists section"
-msgstr ""
+#: editor_actions.cc:130
+msgid "Secondary Clock"
+msgstr "第二计时器"
 
-#: session_state.cc:1271
-msgid "Session: XML state has no bundles section"
-msgstr ""
+#: editor_actions.cc:137
+msgid "Subframes"
+msgstr "子框架"
 
-#: session_state.cc:1283
-msgid "Session: XML state has no diskstreams section"
-msgstr ""
+#: editor_actions.cc:140
+msgid "Timecode fps"
+msgstr "时间码FPS"
 
-#: session_state.cc:1291
-msgid "Session: XML state has no routes section"
-msgstr ""
+#: editor_actions.cc:141 route_time_axis.cc:575
+msgid "Height"
+msgstr "高度"
 
-#: session_state.cc:1303
-msgid "Session: XML state has no route groups section"
-msgstr ""
+#: editor_actions.cc:143
+msgid "Tools"
+msgstr "工具"
 
-#: session_state.cc:1312
-msgid "Session: XML state has no edit groups section"
-msgstr ""
+#: editor_actions.cc:144
+msgid "View"
+msgstr "视图"
 
-#: session_state.cc:1319
-msgid "Session: XML state has no mix groups section"
-msgstr ""
+#: editor_actions.cc:146
+msgid "Zoom"
+msgstr "缩放"
 
-#: session_state.cc:1327
-msgid "Session: XML state has no click section"
-msgstr ""
+#: editor_actions.cc:152
+msgid "Break drag or deselect all"
+msgstr "终止拖拽或取消选择所有"
 
-#: session_state.cc:1373
-msgid "Session: cannot create Route from XML description."
-msgstr ""
+#: editor_actions.cc:159
+msgid "Show Editor Mixer"
+msgstr "显示编辑器混音器"
 
-#: session_state.cc:1377
-msgid "Loaded track/bus %1"
-msgstr "载入音轨/总线 %1"
+#: editor_actions.cc:160
+msgid "Show Editor List"
+msgstr "显示编辑器列表"
 
-#: session_state.cc:1382
-msgid "Tracks/busses loaded;  Adding to Session"
-msgstr ""
+#: editor_actions.cc:162
+msgid "Playhead to Next Region Boundary"
+msgstr "指针到下一个区域边界"
 
-#: session_state.cc:1386
-msgid "Finished adding tracks/busses"
-msgstr ""
+#: editor_actions.cc:163
+msgid "Playhead to Next Region Boundary (No Track Selection)"
+msgstr "指针到下一个区域边界(无音轨已选择部分)"
 
-#: session_state.cc:1485
-msgid "Could not find diskstream for route"
-msgstr ""
+#: editor_actions.cc:164
+msgid "Playhead to Previous Region Boundary"
+msgstr "指针到上一个区域边界"
 
-#: session_state.cc:1545
-msgid "Session: cannot create Region from XML description."
-msgstr ""
+#: editor_actions.cc:165
+msgid "Playhead to Previous Region Boundary (No Track Selection)"
+msgstr "指针到上一个区域边界(无音轨已选择部分)"
 
-#: session_state.cc:1549
-msgid "Can not load state for region '%1'"
-msgstr ""
+#: editor_actions.cc:167
+msgid "Playhead to Next Region Start"
+msgstr "指针到下一个区域起点"
 
-#: session_state.cc:1585
-msgid "Regions in compound description not found (ID's %1 and %2): ignored"
-msgstr ""
+#: editor_actions.cc:168
+msgid "Playhead to Next Region End"
+msgstr "指针到下一个区域终点"
 
-#: session_state.cc:1613
-msgid "Nested source has no ID info in session file! (ignored)"
-msgstr ""
+#: editor_actions.cc:169
+msgid "Playhead to Next Region Sync"
+msgstr "播放头到下一个区域同步"
 
-#: session_state.cc:1625
-msgid "Cannot reconstruct nested source for region %1"
-msgstr ""
+#: editor_actions.cc:171
+msgid "Playhead to Previous Region Start"
+msgstr "指针到上一个区域起点"
 
-#: session_state.cc:1687
-msgid "Session: XMLNode describing a AudioRegion is incomplete (no source)"
-msgstr ""
+#: editor_actions.cc:172
+msgid "Playhead to Previous Region End"
+msgstr "指针到上一个区域终点"
 
-#: session_state.cc:1695 session_state.cc:1716 session_state.cc:1736
-msgid ""
-"Session: XMLNode describing a AudioRegion references an unknown source id =%1"
-msgstr ""
+#: editor_actions.cc:173
+msgid "Playhead to Previous Region Sync"
+msgstr "指针到下一个区域同步"
 
-#: session_state.cc:1701 session_state.cc:1722 session_state.cc:1742
-msgid ""
-"Session: XMLNode describing a AudioRegion references a non-audio source id ="
-"%1"
-msgstr ""
+#: editor_actions.cc:175
+msgid "To Next Region Boundary"
+msgstr "到下一个区域边界"
 
-#: session_state.cc:1765
-msgid ""
-"Session: XMLNode describing an AudioRegion is missing some master sources; "
-"ignored"
-msgstr ""
+#: editor_actions.cc:176
+msgid "To Next Region Boundary (No Track Selection)"
+msgstr "到下一个区域边界(无音轨已选择部分)"
 
-#: session_state.cc:1799
-msgid "Session: XMLNode describing a MidiRegion is incomplete (no source)"
-msgstr ""
+#: editor_actions.cc:177
+msgid "To Previous Region Boundary"
+msgstr "到上一个区域边界"
 
-#: session_state.cc:1807
-msgid ""
-"Session: XMLNode describing a MidiRegion references an unknown source id =%1"
-msgstr ""
+#: editor_actions.cc:178
+msgid "To Previous Region Boundary (No Track Selection)"
+msgstr "到上一个区域边界(无音轨已选择部分)"
 
-#: session_state.cc:1813
-msgid ""
-"Session: XMLNode describing a MidiRegion references a non-midi source id =%1"
+#: editor_actions.cc:180
+msgid "To Next Region Start"
+msgstr "到下一个区域起点"
+
+#: editor_actions.cc:181
+msgid "To Next Region End"
+msgstr "到下一个区域终点"
+
+#: editor_actions.cc:182
+msgid "To Next Region Sync"
+msgstr "到下一个区域同步"
+
+#: editor_actions.cc:184
+msgid "To Previous Region Start"
+msgstr "到上一个区域起点"
+
+#: editor_actions.cc:185
+msgid "To Previous Region End"
+msgstr "到上一个区域终点"
+
+#: editor_actions.cc:186
+msgid "To Previous Region Sync"
+msgstr "到上一个区域同步"
+
+#: editor_actions.cc:188
+msgid "To Range Start"
+msgstr "到范围起点"
+
+#: editor_actions.cc:189
+msgid "To Range End"
+msgstr "到范围终点"
+
+#: editor_actions.cc:191
+msgid "Playhead to Range Start"
+msgstr "指针到范围起点"
+
+#: editor_actions.cc:192
+msgid "Playhead to Range End"
+msgstr "指针到范围终点"
+
+#: editor_actions.cc:195
+msgid "Select All Tracks"
+msgstr "选择所有音轨"
+
+#: editor_actions.cc:196 export_timespan_selector.cc:61 processor_box.cc:2468
+msgid "Deselect All"
+msgstr "反选所有"
+
+#: editor_actions.cc:204
+msgid "Select All Overlapping Edit Range"
+msgstr "选择所有重叠的编辑范围"
+
+#: editor_actions.cc:205
+msgid "Select All Inside Edit Range"
+msgstr "选择所有内部的编辑范围"
+
+#: editor_actions.cc:207
+msgid "Select Edit Range"
+msgstr "选择编辑范围"
+
+#: editor_actions.cc:209
+msgid "Select All in Punch Range"
+msgstr "选择所有在切换范围内的"
+
+#: editor_actions.cc:210
+msgid "Select All in Loop Range"
+msgstr "选择所有在循环范围内的"
+
+#: editor_actions.cc:212
+msgid "Select Next Track or Bus"
+msgstr "选择下一个音轨或总线"
+
+#: editor_actions.cc:213
+msgid "Select Previous Track or Bus"
+msgstr "选择上一个音轨或总线"
+
+#: editor_actions.cc:215
+msgid "Toggle Record Enable"
+msgstr "切换录制启用"
+
+#: editor_actions.cc:217
+msgid "Toggle Solo"
+msgstr "切独奏"
+
+#: editor_actions.cc:219
+msgid "Toggle Mute"
+msgstr "切换静音"
+
+#: editor_actions.cc:221
+msgid "Toggle Solo Isolate"
+msgstr "切换独奏隔离"
+
+#: editor_actions.cc:226
+msgid "Save View %1"
+msgstr "保存视图 %1"
+
+#: editor_actions.cc:232
+msgid "Go to View %1"
+msgstr "跳转到视图 %1"
+
+#: editor_actions.cc:238
+msgid "Locate to Mark %1"
+msgstr "定位到标记 %1"
+
+#: editor_actions.cc:242 editor_actions.cc:243
+msgid "Jump to Next Mark"
+msgstr "跳到下一个标记"
+
+#: editor_actions.cc:244 editor_actions.cc:245
+msgid "Jump to Previous Mark"
+msgstr "跳到上一个标记"
+
+#: editor_actions.cc:247 editor_actions.cc:248
+msgid "Add Mark from Playhead"
+msgstr "从指针起添加标记"
+
+#: editor_actions.cc:250 editor_actions.cc:251
+msgid "Remove Mark at Playhead"
+msgstr "移除指针处的标记"
+
+#: editor_actions.cc:253
+msgid "Nudge Next Later"
+msgstr "向后微调下一个"
+
+#: editor_actions.cc:254
+msgid "Nudge Next Earlier"
+msgstr "向前微调下一个"
+
+#: editor_actions.cc:256
+msgid "Nudge Playhead Forward"
+msgstr "微调指针前进"
+
+#: editor_actions.cc:257
+msgid "Nudge Playhead Backward"
+msgstr "微调指针后退"
+
+#: editor_actions.cc:258
+msgid "Playhead To Next Grid"
+msgstr "指针转到下一个网格"
+
+#: editor_actions.cc:259
+msgid "Playhead To Previous Grid"
+msgstr "指针转到上一个网格"
+
+#: editor_actions.cc:264
+msgid "Zoom to Selection"
+msgstr "缩放至已选择部分"
+
+#: editor_actions.cc:265
+msgid "Toggle Zoom State"
+msgstr "切换缩放状态"
+
+#: editor_actions.cc:267
+msgid "Expand Track Height"
+msgstr "扩展音轨高度"
+
+#: editor_actions.cc:268
+msgid "Shrink Track Height"
+msgstr "收缩扩展音轨高度"
+
+#: editor_actions.cc:270
+msgid "Move Selected Tracks Up"
+msgstr "向上移动已选中音轨"
+
+#: editor_actions.cc:272
+msgid "Move Selected Tracks Down"
+msgstr "向下移动已选中音轨"
+
+#: editor_actions.cc:275
+msgid "Scroll Tracks Up"
+msgstr "向上滚动音轨"
+
+#: editor_actions.cc:277
+msgid "Scroll Tracks Down"
+msgstr "向下滚动音轨"
+
+#: editor_actions.cc:279
+msgid "Step Tracks Up"
+msgstr "向上步进音轨"
+
+#: editor_actions.cc:281
+msgid "Step Tracks Down"
+msgstr "向下步进音轨"
+
+#: editor_actions.cc:284
+msgid "Scroll Backward"
+msgstr "向后滚动"
+
+#: editor_actions.cc:285
+msgid "Scroll Forward"
+msgstr "向前滚动"
+
+#: editor_actions.cc:286
+msgid "Center Playhead"
+msgstr "指针置中"
+
+#: editor_actions.cc:287
+msgid "Center Edit Point"
+msgstr "编辑点置中"
+
+#: editor_actions.cc:289
+msgid "Playhead Forward"
+msgstr "指针前进"
+
+#: editor_actions.cc:290
+msgid "Playhead Backward"
+msgstr "指针后退"
+
+#: editor_actions.cc:292
+msgid "Playhead to Active Mark"
+msgstr "指针跳转到激活的标记处"
+
+#: editor_actions.cc:293
+msgid "Active Mark to Playhead"
+msgstr "激活的标记跳转到指针处"
+
+#: editor_actions.cc:295
+msgid "Use Skip Ranges"
+msgstr "使用不连续的范围"
+
+#: editor_actions.cc:302
+msgid "Play Selected Regions"
+msgstr "播放已选中的区域"
+
+#: editor_actions.cc:304
+msgid "Play from Edit Point and Return"
+msgstr "从编辑点播放并返回"
+
+#: editor_actions.cc:306
+msgid "Play Edit Range"
+msgstr "播放编辑范围"
+
+#: editor_actions.cc:308
+msgid "Playhead to Mouse"
+msgstr "指针跳转到鼠标处"
+
+#: editor_actions.cc:309
+msgid "Active Marker to Mouse"
+msgstr "激活的标记跳转到鼠标处"
+
+#: editor_actions.cc:319
+msgid "Undo Selection Change"
+msgstr "撤销已选中部分的改动"
+
+#: editor_actions.cc:320
+msgid "Redo Selection Change"
+msgstr "重做已选中部分的改动"
+
+#: editor_actions.cc:322
+msgid "Export Audio"
+msgstr "导出音频"
+
+#: editor_actions.cc:323 export_dialog.cc:396
+msgid "Export Range"
+msgstr "导出范围"
+
+#: editor_actions.cc:328
+msgid "Separate Using Punch Range"
+msgstr "使用切换范围分离"
+
+#: editor_actions.cc:331
+msgid "Separate Using Loop Range"
+msgstr "使用循环范围分离"
+
+#: editor_actions.cc:334 editor_actions.cc:356
+msgid "Crop"
+msgstr "剪裁"
+
+#: editor_actions.cc:344
+msgid "Fade Range Selection"
+msgstr "淡化范围已选中部分"
+
+#: editor_actions.cc:346
+msgid "Set Tempo from Edit Range = Bar"
+msgstr "从编辑范围设置节奏 = 小节"
+
+#: editor_actions.cc:348
+msgid "Log"
+msgstr "日志"
+
+#: editor_actions.cc:351 editor_actions.cc:353
+msgid "Move to Next Transient"
+msgstr "移动到下一个过渡"
+
+#: editor_actions.cc:352 editor_actions.cc:354
+msgid "Move to Previous Transient"
+msgstr "移动到上一个过渡"
+
+#: editor_actions.cc:358 editor_actions.cc:361
+msgid "Start Range"
+msgstr "开始范围"
+
+#: editor_actions.cc:359 editor_actions.cc:362
+msgid "Finish Range"
+msgstr "结束范围"
+
+#: editor_actions.cc:394
+msgid "Follow Playhead"
+msgstr "跟随指针"
+
+#: editor_actions.cc:395
+msgid "Remove Last Capture"
+msgstr "移除已捕获内容"
+
+#: editor_actions.cc:397
+msgid "Stationary Playhead"
+msgstr "固定指针"
+
+#: editor_actions.cc:399 insert_time_dialog.cc:32
+msgid "Insert Time"
+msgstr "插入时间"
+
+#: editor_actions.cc:402
+msgid "Toggle Active"
+msgstr "切换激活"
+
+#: editor_actions.cc:407 editor_actions.cc:1768 editor_markers.cc:921
+#: editor_markers.cc:986 editor_snapshots.cc:122 mixer_strip.cc:1543
+#: route_time_axis.cc:856
+msgid "Remove"
+msgstr "移除"
+
+#: editor_actions.cc:411
+msgid "Fit Selection (Vertical)"
+msgstr " 匹配已选择部分(垂直)"
+
+#: editor_actions.cc:413 time_axis_view.cc:1371
+msgid "Largest"
+msgstr "最大的"
+
+#: editor_actions.cc:416 time_axis_view.cc:1372
+msgid "Larger"
+msgstr "更大的"
+
+#: editor_actions.cc:419 editor_rulers.cc:249 time_axis_view.cc:1373
+msgid "Large"
+msgstr "大"
+
+#: editor_actions.cc:425 editor_rulers.cc:253 time_axis_view.cc:1375
+msgid "Small"
+msgstr "小"
+
+#: editor_actions.cc:429
+msgid "Sound Selected MIDI Notes"
+msgstr "声音已选择部分MIDI音符"
+
+#: editor_actions.cc:434
+msgid "Zoom Focus Left"
+msgstr "以左侧为焦点缩放"
+
+#: editor_actions.cc:435
+msgid "Zoom Focus Right"
+msgstr "以右侧为焦点缩放"
+
+#: editor_actions.cc:436
+msgid "Zoom Focus Center"
+msgstr "以中央为焦点缩放"
+
+#: editor_actions.cc:437
+msgid "Zoom Focus Playhead"
+msgstr "以指针为焦点缩放"
+
+#: editor_actions.cc:438
+msgid "Zoom Focus Mouse"
+msgstr "以鼠标为焦点缩放"
+
+#: editor_actions.cc:439
+msgid "Zoom Focus Edit Point"
+msgstr "以编辑点为焦点缩放"
+
+#: editor_actions.cc:441
+msgid "Next Zoom Focus"
+msgstr "下一个缩放焦点"
+
+#: editor_actions.cc:447
+msgid "Smart Object Mode"
+msgstr "智能对象物体模式"
+
+#: editor_actions.cc:450
+msgid "Smart"
+msgstr "智能"
+
+#: editor_actions.cc:453
+msgid "Object Tool"
+msgstr "对象物体工具"
+
+#: editor_actions.cc:458
+msgid "Range Tool"
+msgstr "范围工具"
+
+#: editor_actions.cc:463
+msgid "Note Drawing Tool"
+msgstr "音符描绘工具"
+
+#: editor_actions.cc:468
+msgid "Audition Tool"
+msgstr "监听工具"
+
+#: editor_actions.cc:473
+msgid "Time FX Tool"
+msgstr "时间特效工具"
+
+#: editor_actions.cc:478
+msgid "Content Tool"
+msgstr "内容工具"
+
+#: editor_actions.cc:484
+msgid "Cut Tool"
+msgstr " 切割工具"
+
+#: editor_actions.cc:490
+msgid "Step Mouse Mode"
+msgstr "步进鼠标模式"
+
+#: editor_actions.cc:497
+msgid "Change Edit Point"
+msgstr "改变编辑点"
+
+#: editor_actions.cc:498
+msgid "Change Edit Point Including Marker"
+msgstr "改变编辑点包括标记"
+
+#: editor_actions.cc:504
+msgid "Cycle Edit Mode"
+msgstr "循环编辑模式"
+
+#: editor_actions.cc:506
+msgid "Snap to"
+msgstr "吸附到"
+
+#: editor_actions.cc:507
+msgid "Snap Mode"
+msgstr "吸附模式"
+
+#: editor_actions.cc:514
+msgid "Next Snap Mode"
+msgstr "下一个吸附模式"
+
+#: editor_actions.cc:515
+msgid "Next Snap Choice"
+msgstr "下一个吸附选择"
+
+#: editor_actions.cc:516
+msgid "Next Musical Snap Choice"
+msgstr "下一个配乐的吸附选择"
+
+#: editor_actions.cc:517
+msgid "Previous Snap Choice"
+msgstr "上一个吸附选择"
+
+#: editor_actions.cc:518
+msgid "Previous Musical Snap Choice"
+msgstr "上一个配乐的吸附选择"
+
+#: editor_actions.cc:523
+msgid "Snap to CD Frame"
+msgstr "吸附到CD框架"
+
+#: editor_actions.cc:524
+msgid "Snap to Timecode Frame"
+msgstr "吸附到时间码框架"
+
+#: editor_actions.cc:525
+msgid "Snap to Timecode Seconds"
+msgstr "吸附到时间码秒"
+
+#: editor_actions.cc:526
+msgid "Snap to Timecode Minutes"
+msgstr "吸附到时间码分"
+
+#: editor_actions.cc:527
+msgid "Snap to Seconds"
+msgstr "吸附到秒"
+
+#: editor_actions.cc:528
+msgid "Snap to Minutes"
+msgstr "吸附到分"
+
+#: editor_actions.cc:530
+msgid "Snap to One Twenty Eighths"
+msgstr "吸附到一百二十八分之一"
+
+#: editor_actions.cc:531
+msgid "Snap to Sixty Fourths"
+msgstr "吸附到六十四分之一"
+
+#: editor_actions.cc:532
+msgid "Snap to Thirty Seconds"
+msgstr "吸附到三十二分之一"
+
+#: editor_actions.cc:533
+msgid "Snap to Twenty Eighths"
+msgstr "吸附到二十八分之一"
+
+#: editor_actions.cc:534
+msgid "Snap to Twenty Fourths"
+msgstr "吸附到二十四分之一"
+
+#: editor_actions.cc:535
+msgid "Snap to Twentieths"
+msgstr "吸附到二十分之一"
+
+#: editor_actions.cc:536
+msgid "Snap to Sixteenths"
+msgstr "吸附到十六分之一"
+
+#: editor_actions.cc:537
+msgid "Snap to Fourteenths"
+msgstr "吸附到十四分之一"
+
+#: editor_actions.cc:538
+msgid "Snap to Twelfths"
+msgstr "吸附到十二分之一"
+
+#: editor_actions.cc:539
+msgid "Snap to Tenths"
+msgstr "吸附到十分之一"
+
+#: editor_actions.cc:540
+msgid "Snap to Eighths"
+msgstr "吸附到八分之一"
+
+#: editor_actions.cc:541
+msgid "Snap to Sevenths"
+msgstr "吸附到七分之一"
+
+#: editor_actions.cc:542
+msgid "Snap to Sixths"
+msgstr "吸附到六分之一"
+
+#: editor_actions.cc:543
+msgid "Snap to Fifths"
+msgstr "吸附到五分之一"
+
+#: editor_actions.cc:544
+msgid "Snap to Quarters"
+msgstr "吸附到四分之一"
+
+#: editor_actions.cc:545
+msgid "Snap to Thirds"
+msgstr "吸附到三分之一"
+
+#: editor_actions.cc:546
+msgid "Snap to Halves"
+msgstr "吸附到二分之一"
+
+#: editor_actions.cc:548
+msgid "Snap to Beat"
+msgstr "吸附到拍子"
+
+#: editor_actions.cc:549
+msgid "Snap to Bar"
+msgstr "吸附到小节"
+
+#: editor_actions.cc:550
+msgid "Snap to Mark"
+msgstr "吸附到标记"
+
+#: editor_actions.cc:551
+msgid "Snap to Region Start"
+msgstr "吸附到区域起点"
+
+#: editor_actions.cc:552
+msgid "Snap to Region End"
+msgstr "吸附到区域终点"
+
+#: editor_actions.cc:553
+msgid "Snap to Region Sync"
+msgstr "吸附到区域同步"
+
+#: editor_actions.cc:554
+msgid "Snap to Region Boundary"
+msgstr "吸附到区域边界"
+
+#: editor_actions.cc:556
+msgid "Show Marker Lines"
+msgstr "显示标记线条"
+
+#: editor_actions.cc:566
+msgid "Loop/Punch"
+msgstr "循环/切换"
+
+#: editor_actions.cc:570
+msgid "Min:Sec"
+msgstr "分:秒"
+
+#: editor_actions.cc:572 editor_actions.cc:575 editor_rulers.cc:271
+msgid "Video Monitor"
+msgstr "视频监控"
+
+#: editor_actions.cc:574 rc_option_editor.cc:2260
+msgid "Video"
+msgstr "视频"
+
+#: editor_actions.cc:577
+msgid "Always on Top"
+msgstr "总是置顶"
+
+#: editor_actions.cc:579
+msgid "Frame number"
+msgstr "帧号码"
+
+#: editor_actions.cc:580
+msgid "Timecode Background"
+msgstr "时间码背景"
+
+#: editor_actions.cc:581
+msgid "Fullscreen"
+msgstr "全屏"
+
+#: editor_actions.cc:582
+msgid "Letterbox"
+msgstr "宽银幕式"
+
+#: editor_actions.cc:583
+msgid "Original Size"
+msgstr "原始尺寸"
+
+#: editor_actions.cc:640
+msgid "Sort"
+msgstr "排序"
+
+#: editor_actions.cc:651 editor_routes.cc:476 mixer_ui.cc:1196
+msgid "Show All"
+msgstr "显示所有"
+
+#: editor_actions.cc:652
+msgid "Show Automatic Regions"
+msgstr "显示自动的区域"
+
+#: editor_actions.cc:654
+msgid "Ascending"
+msgstr "升序"
+
+#: editor_actions.cc:656
+msgid "Descending"
+msgstr "降序"
+
+#: editor_actions.cc:659
+msgid "By Region Name"
+msgstr "以区域名称"
+
+#: editor_actions.cc:661
+msgid "By Region Length"
+msgstr "以区域长度"
+
+#: editor_actions.cc:663
+msgid "By Region Position"
+msgstr "以区域位置"
+
+#: editor_actions.cc:665
+msgid "By Region Timestamp"
+msgstr "以区域时间戳"
+
+#: editor_actions.cc:667
+msgid "By Region Start in File"
+msgstr "以文件内的区域起点"
+
+#: editor_actions.cc:669
+msgid "By Region End in File"
+msgstr "以文件内的区域终点"
+
+#: editor_actions.cc:671
+msgid "By Source File Name"
+msgstr "以源文件名称"
+
+#: editor_actions.cc:673
+msgid "By Source File Length"
+msgstr "以源文件长度"
+
+#: editor_actions.cc:675
+msgid "By Source File Creation Date"
+msgstr "以源文件创建日期"
+
+#: editor_actions.cc:677
+msgid "By Source Filesystem"
+msgstr "以源文件系统"
+
+#: editor_actions.cc:680
+msgid "Remove Unused"
+msgstr "移除未使用的"
+
+#: editor_actions.cc:684 editor_audio_import.cc:282 session_import_dialog.cc:75
+#: session_import_dialog.cc:95 session_metadata_dialog.cc:418
+#: editor_videotimeline.cc:91
+msgid "Import"
+msgstr "导入"
+
+#: editor_actions.cc:687
+msgid "Import to Region List..."
+msgstr "导入到区域列表…"
+
+#: editor_actions.cc:690 session_import_dialog.cc:44
+msgid "Import From Session"
+msgstr "从会话导入"
+
+#: editor_actions.cc:694
+msgid "Bring all media into session folder"
+msgstr "将所有媒体引入会话文件夹"
+
+#: editor_actions.cc:697
+msgid "Show Summary"
+msgstr "显示摘要"
+
+#: editor_actions.cc:699
+msgid "Show Group Tabs"
+msgstr "显示群组标签页"
+
+#: editor_actions.cc:701
+msgid "Show Measure Lines"
+msgstr "显示测量线"
+
+#: editor_actions.cc:705
+msgid "Show Logo"
+msgstr "显示商标"
+
+#: editor_actions.cc:709
+msgid "Toggle MIDI Input Active for Editor-Selected Tracks/Busses"
+msgstr "切换是否为编辑器中已选择的音轨/总线激活MIDI输入"
+
+#: editor_actions.cc:732
+msgid "Loaded editor bindings from %1"
+msgstr "已从 %1 载入编辑器绑定"
+
+#: editor_actions.cc:734
+msgid "Could not find editor.bindings in search path %1"
+msgstr "在搜索路径 %1 找不到编辑器绑定"
+
+#: editor_actions.cc:1078 editor_actions.cc:1474 editor_actions.cc:1485
+#: editor_actions.cc:1538 editor_actions.cc:1549 editor_actions.cc:1596
+#: editor_actions.cc:1606 editor_regions.cc:1563
+msgid "programming error: %1: %2"
+msgstr "程序错误: %1: %2"
+
+#: editor_actions.cc:1774
+msgid "Raise"
+msgstr "提升"
+
+#: editor_actions.cc:1777
+msgid "Raise to Top"
+msgstr "提升到顶部"
+
+#: editor_actions.cc:1780
+msgid "Lower"
+msgstr "沉降"
+
+#: editor_actions.cc:1783
+msgid "Lower to Bottom"
+msgstr "沉降到底部"
+
+#: editor_actions.cc:1786
+msgid "Move to Original Position"
+msgstr "移动到原始位置"
+
+#: editor_actions.cc:1791
+msgid "Lock to Video"
+msgstr "锁定到视频"
+
+#: editor_actions.cc:1796 editor_markers.cc:912
+msgid "Glue to Bars and Beats"
+msgstr "粘连到小节和拍子"
+
+#: editor_actions.cc:1801
+msgid "Remove Sync"
+msgstr "移除同步"
+
+#: editor_actions.cc:1804 mixer_strip.cc:2006 monitor_section.cc:272
+#: route_time_axis.cc:253 route_time_axis.cc:526
+msgid "Mute"
+msgstr "静音"
+
+#: editor_actions.cc:1807
+msgid "Normalize..."
+msgstr "规范化…"
+
+#: editor_actions.cc:1810
+msgid "Reverse"
+msgstr "反转"
+
+#: editor_actions.cc:1813
+msgid "Make Mono Regions"
+msgstr "设为单声道区域"
+
+#: editor_actions.cc:1816
+msgid "Boost Gain"
+msgstr "放大增益"
+
+#: editor_actions.cc:1819
+msgid "Cut Gain"
+msgstr "减小增益"
+
+#: editor_actions.cc:1822
+msgid "Pitch Shift..."
+msgstr "音高替换…"
+
+#: editor_actions.cc:1825
+msgid "Transpose..."
+msgstr "变调…"
+
+#: editor_actions.cc:1828
+msgid "Opaque"
+msgstr "模糊度"
+
+#: editor_actions.cc:1832 editor_regions.cc:117
+msgid "Fade In"
+msgstr "æ·¡å…¥"
+
+#: editor_actions.cc:1837 editor_regions.cc:118
+msgid "Fade Out"
+msgstr "淡出"
+
+#: editor_actions.cc:1852
+msgid "Multi-Duplicate..."
+msgstr "多个副本…"
+
+#: editor_actions.cc:1857
+msgid "Fill Track"
+msgstr "填充音轨"
+
+#: editor_actions.cc:1861 editor_markers.cc:1000
+msgid "Set Loop Range"
+msgstr "设置循环范围"
+
+#: editor_actions.cc:1868
+msgid "Set Punch"
+msgstr "设置切换"
+
+#: editor_actions.cc:1872
+msgid "Add Single Range Marker"
+msgstr "添加单个范围标记"
+
+#: editor_actions.cc:1877
+msgid "Add Range Marker Per Region"
+msgstr "为每个区域添加范围标记"
+
+#: editor_actions.cc:1881
+msgid "Snap Position To Grid"
+msgstr "吸附位置到网格"
+
+#: editor_actions.cc:1884
+msgid "Close Gaps"
+msgstr "封闭间隙"
+
+# 使用方法 http://linuxaudioblog.com/?tag=rhythm-ferret
+#: editor_actions.cc:1887
+msgid "Rhythm Ferret..."
+msgstr "节奏探测…"
+
+#: editor_actions.cc:1890
+msgid "Export..."
+msgstr "导出..."
+
+#: editor_actions.cc:1896
+msgid "Separate Under"
+msgstr "分离位于"
+
+#: editor_actions.cc:1900 editor_actions.cc:1901
+msgid "Set Fade In Length"
+msgstr "设置淡入长度"
+
+#: editor_actions.cc:1902 editor_actions.cc:1903
+msgid "Set Fade Out Length"
+msgstr "设置淡出长度"
+
+#: editor_actions.cc:1905
+msgid "Set Tempo from Region = Bar"
+msgstr "从区域设置节奏=小节"
+
+#: editor_actions.cc:1910
+msgid "Split at Percussion Onsets"
+msgstr "在打击乐击发处拆分"
+
+#: editor_actions.cc:1915
+msgid "List Editor..."
+msgstr "列表编辑器…"
+
+#: editor_actions.cc:1918
+msgid "Properties..."
+msgstr "属性…"
+
+#: editor_actions.cc:1922
+msgid "Bounce (with processing)"
+msgstr "欢跳弹奏(并处理)"
+
+#: editor_actions.cc:1923
+msgid "Bounce (without processing)"
+msgstr "欢跳弹奏(不处理)"
+
+#: editor_actions.cc:1924
+msgid "Combine"
+msgstr "整合"
+
+#: editor_actions.cc:1925
+msgid "Uncombine"
+msgstr "不整合"
+
+#: editor_actions.cc:1927
+msgid "Spectral Analysis..."
+msgstr "频谱分析…"
+
+#: editor_actions.cc:1929
+msgid "Reset Envelope"
+msgstr "重置封装"
+
+#: editor_actions.cc:1931
+msgid "Reset Gain"
+msgstr "重置增益"
+
+#: editor_actions.cc:1936
+msgid "Envelope Active"
+msgstr "封装激活"
+
+#: editor_actions.cc:1944 editor_actions.cc:1945
+msgid "Insert Patch Change..."
+msgstr "插入切变音色…"
+
+#: editor_actions.cc:1946
+msgid "Unlink from other copies"
+msgstr "解除链接其它拷贝"
+
+#: editor_actions.cc:1947
+msgid "Strip Silence..."
+msgstr "片段无声…"
+
+#: editor_actions.cc:1948
+msgid "Set Range Selection"
+msgstr "设置范围已选择部分"
+
+#: editor_actions.cc:1950 editor_actions.cc:1951
+msgid "Nudge Later"
+msgstr "向后微调"
+
+#: editor_actions.cc:1952 editor_actions.cc:1953
+msgid "Nudge Earlier"
+msgstr "向前微调"
+
+#: editor_actions.cc:1955
+msgid "Sequence Regions"
+msgstr "序列区域"
+
+#: editor_actions.cc:1960
+msgid "Nudge Later by Capture Offset"
+msgstr "以捕获部分偏移向后微调"
+
+#: editor_actions.cc:1967
+msgid "Nudge Earlier by Capture Offset"
+msgstr "以捕获部分偏移向前微调"
+
+#: editor_actions.cc:1971
+msgid "Trim to Loop"
+msgstr "修剪到循环"
+
+#: editor_actions.cc:1972
+msgid "Trim to Punch"
+msgstr "修剪到切换"
+
+#: editor_actions.cc:1974
+msgid "Trim to Previous"
+msgstr "修剪到上一个"
+
+#: editor_actions.cc:1975
+msgid "Trim to Next"
+msgstr "修剪到下一个"
+
+#: editor_actions.cc:1982
+msgid "Insert Region From Region List"
+msgstr "从区域列表插入区域"
+
+#: editor_actions.cc:1988
+msgid "Set Sync Position"
+msgstr "设置同步位置"
+
+#: editor_actions.cc:1989
+msgid "Place Transient"
+msgstr "放置过渡"
+
+#: editor_actions.cc:1990
+msgid "Split/Separate"
+msgstr "拆分/分离"
+
+#: editor_actions.cc:1991
+msgid "Trim Start at Edit Point"
+msgstr "在编辑点修剪起点"
+
+#: editor_actions.cc:1992
+msgid "Trim End at Edit Point"
+msgstr "在编辑点修剪终点"
+
+#: editor_actions.cc:1997
+msgid "Align Start"
+msgstr "对齐起点"
+
+#: editor_actions.cc:2004
+msgid "Align Start Relative"
+msgstr "对齐起点相关"
+
+#: editor_actions.cc:2008
+msgid "Align End"
+msgstr "对齐终点"
+
+#: editor_actions.cc:2013
+msgid "Align End Relative"
+msgstr "对齐终点相关"
+
+#: editor_actions.cc:2020
+msgid "Align Sync"
+msgstr "对齐同步"
+
+#: editor_actions.cc:2027
+msgid "Align Sync Relative"
+msgstr "对齐同步相关"
+
+#: editor_actions.cc:2031 editor_actions.cc:2034
+msgid "Choose Top..."
+msgstr "选择顶部…"
+
+#: editor_audio_import.cc:77 editor_audio_import.cc:99
+msgid "You can't import or embed an audiofile until you have a session loaded."
+msgstr "无法导入嵌入的的音频文件,,除非您已经载入一个会话文件。"
+
+#: editor_audio_import.cc:83 editor_audio_import.cc:127
+msgid "Add Existing Media"
+msgstr "添加已存在的媒体"
+
+#: editor_audio_import.cc:175
+msgid ""
+"The session already contains a source file named %1.  Do you want to import %1 as "
+"a new file, or skip it?"
+msgstr ""
+"此会话已经存在一个名为 %1 的源文件。您想把 %1 作为一个新文件导入进来,,或者跳过它?"
+
+#: editor_audio_import.cc:177
+msgid ""
+"The session already contains a source file named %1.  Do you want to import %2 as "
+"a new source, or skip it?"
+msgstr ""
+"此会话已经存在一个名为 %1 的源文件。您想把 %2 作为一个新的源导入进来,,或者跳过它?"
+
+#: editor_audio_import.cc:282 editor_videotimeline.cc:91
+msgid "Cancel Import"
+msgstr "取消导入"
+
+#: editor_audio_import.cc:559
+msgid "Editor: cannot open file \"%1\", (%2)"
+msgstr "编辑器: 无法打开文件 \"%1\", (%2)"
+
+#: editor_audio_import.cc:567
+msgid "Cancel entire import"
+msgstr "取消整体导入"
+
+#: editor_audio_import.cc:568
+msgid "Don't embed it"
+msgstr "不嵌入它"
+
+#: editor_audio_import.cc:569
+msgid "Embed all without questions"
+msgstr "嵌入所有,不必询问"
+
+#: editor_audio_import.cc:572 editor_audio_import.cc:598 export_format_dialog.cc:60
+msgid "Sample rate"
+msgstr "采样率"
+
+#: editor_audio_import.cc:573 editor_audio_import.cc:599
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr ""
+"%1\n"
+"此音频文件的采样率与会话的采样率不匹配!"
+
+#: editor_audio_import.cc:595
+msgid "Embed it anyway"
+msgstr "只管嵌入它"
+
+#: editor_canvas_events.cc:1306 editor_drag.cc:1381
+msgid "Could not create new track after region placed in the drop zone"
+msgstr "区域被放置在落选区后,无法创建新音轨"
+
+#: editor_drag.cc:1266
+msgid "fixed time region drag"
+msgstr "已定型的时间区域拖拽"
+
+#: editor_drag.cc:2214
+msgid "Ripple drag"
+msgstr "波纹拖拽"
+
+#: editor_drag.cc:2365 midi_region_view.cc:2813
+msgid "resize notes"
+msgstr "重设音符大小"
+
+#: editor_drag.cc:2517
+msgid "Video Start:"
+msgstr "视频起点:"
+
+#: editor_drag.cc:2519
+msgid "Diff:"
+msgstr "差别:"
+
+#: editor_drag.cc:2538
+msgid "Move Video"
+msgstr "移动视频"
+
+#: editor_drag.cc:3046
+msgid "copy meter mark"
+msgstr "复制节拍标记"
+
+#: editor_drag.cc:3054
+msgid "move meter mark"
+msgstr "移动节拍标记"
+
+#: editor_drag.cc:3177
+msgid "copy tempo mark"
+msgstr "复制节奏标记"
+
+#: editor_drag.cc:3185
+msgid "move tempo mark"
+msgstr "移动节奏标记"
+
+#: editor_drag.cc:3412
+msgid "change fade in length"
+msgstr "改变渐入长度"
+
+#: editor_drag.cc:3526
+msgid "change fade out length"
+msgstr "改变渐出长度"
+
+#: editor_drag.cc:3880
+msgid "move marker"
+msgstr "移动标记"
+
+#: editor_drag.cc:4490
+msgid "An error occurred while executing time stretch operation"
+msgstr "当执行时间延伸操作时出现错误"
+
+#: editor_drag.cc:4947
+msgid "programming_error: %1"
+msgstr "程序错误:%1"
+
+#: editor_drag.cc:5016 editor_drag.cc:5026
+msgid "new skip marker"
+msgstr "新建跳跃标记"
+
+#: editor_drag.cc:5017
+msgid "skip"
+msgstr "跳跃"
+
+#: editor_drag.cc:5021 location_ui.cc:56
+msgid "CD"
+msgstr ""
+
+#: editor_drag.cc:5022
+msgid "new CD marker"
+msgstr "新建CD标记"
+
+#: editor_drag.cc:5027 editor_route_groups.cc:437 mixer_ui.cc:1493
+msgid "unnamed"
+msgstr "未命名的"
+
+#: editor_drag.cc:5309
+msgid "Automation range drag created for invalid region type"
+msgstr "为无效的区域类型已创建自动范围拖拽"
+
+#: editor_route_groups.cc:96
+msgid "Col"
+msgstr "列"
+
+#: editor_route_groups.cc:96
+msgid "Group Tab Color"
+msgstr "分组标签页颜色"
+
+#: editor_route_groups.cc:97
+msgid "Name of Group"
+msgstr "分组名称"
+
+#: editor_route_groups.cc:98 editor_routes.cc:207
+msgid "V"
+msgstr ""
+
+#: editor_route_groups.cc:98
+msgid "Group is visible?"
+msgstr "分组是否可见?"
+
+#: editor_route_groups.cc:99
+msgid "On"
+msgstr "开启"
+
+#: editor_route_groups.cc:99
+msgid "Group is enabled?"
+msgstr "分组是否可用?"
+
+#: editor_route_groups.cc:100
+msgid "group|G"
+msgstr "分组|G"
+
+#: editor_route_groups.cc:100
+msgid "Sharing Gain?"
+msgstr "分享增益?"
+
+#: editor_route_groups.cc:101
+msgid "relative|Rel"
+msgstr "相关|Rel"
+
+#: editor_route_groups.cc:101
+msgid "Relative Gain Changes?"
+msgstr "相关增益改变?"
+
+#: editor_route_groups.cc:102
+msgid "mute|M"
+msgstr "静音|M"
+
+#: editor_route_groups.cc:102
+msgid "Sharing Mute?"
+msgstr "分享静音?"
+
+#: editor_route_groups.cc:103
+msgid "solo|S"
+msgstr "独奏|S"
+
+#: editor_route_groups.cc:103
+msgid "Sharing Solo?"
+msgstr "分享独奏?"
+
+#: editor_route_groups.cc:104 midi_time_axis.cc:1622 midi_time_axis.cc:1625
+#: midi_time_axis.cc:1628
+msgid "Rec"
+msgstr "录制"
+
+#: editor_route_groups.cc:104
+msgid "Sharing Record-enable Status?"
+msgstr "分享静音?"
+
+#: editor_route_groups.cc:105
+msgid "monitoring|Mon"
+msgstr "监控|Mon"
+
+#: editor_route_groups.cc:105
+msgid "Sharing Monitoring Choice?"
+msgstr "分享监控选择?"
+
+#: editor_route_groups.cc:106
+msgid "selection|Sel"
+msgstr "已选择部分|Sel"
+
+#: editor_route_groups.cc:106
+msgid "Sharing Selected/Editing Status?"
+msgstr "分享已选择/编辑状态?"
+
+#: editor_route_groups.cc:107
+msgid "active|A"
+msgstr "激活"
+
+#: editor_route_groups.cc:107
+msgid "Sharing Active Status?"
+msgstr "分享激活状态?"
+
+#: editor_export_audio.cc:92 editor_markers.cc:740 editor_markers.cc:827
+#: editor_markers.cc:1012 editor_markers.cc:1030 editor_markers.cc:1048
+#: editor_markers.cc:1067 editor_markers.cc:1086 editor_markers.cc:1116
+#: editor_markers.cc:1147 editor_markers.cc:1177 editor_markers.cc:1205
+#: editor_markers.cc:1236 editor_markers.cc:1261 editor_markers.cc:1312
+#: editor_markers.cc:1356 editor_markers.cc:1382 editor_markers.cc:1576
+#: editor_mouse.cc:2120
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr "程序错误:标记版面条目没有标记对象物体指示!"
+
+#: editor_export_audio.cc:145 editor_export_audio.cc:150
+msgid "File Exists!"
+msgstr "文件已存在!"
+
+#: editor_export_audio.cc:153
+msgid "Overwrite Existing File"
+msgstr "覆盖已存在文件"
+
+#: editor_group_tabs.cc:176
+msgid "Fit to Window"
+msgstr "匹配适合窗口"
+
+#: editor_markers.cc:139
+msgid "start"
+msgstr "start"
+
+#: editor_markers.cc:140
+msgid "end"
+msgstr "终点"
+
+#: editor_markers.cc:657 editor_ops.cc:2085 editor_ops.cc:2107 editor_ops.cc:2164
+#: editor_ops.cc:2193 location_ui.cc:1023
+msgid "add marker"
+msgstr "添加标记"
+
+#: editor_markers.cc:689 editor_markers.cc:1456
+msgid "set loop range"
+msgstr "设置切换范围"
+
+#: editor_markers.cc:705 editor_markers.cc:1462
+msgid "set punch range"
+msgstr "设置切换范围"
+
+#: editor_markers.cc:722 editor_ops.cc:4055
+msgid "range"
+msgstr "范围"
+
+#: editor_markers.cc:725
+msgid "new range marker"
+msgstr "新建范围标记"
+
+#: editor_markers.cc:758 editor_ops.cc:2129 location_ui.cc:859
+msgid "remove marker"
+msgstr "移除标记"
+
+#: editor_markers.cc:894
+msgid "Locate to Here"
+msgstr "定位到此处"
+
+#: editor_markers.cc:895
+msgid "Play from Here"
+msgstr "从此处开始播放"
+
+#: editor_markers.cc:896
+msgid "Move Mark to Playhead"
+msgstr "移动标记到指针"
+
+#: editor_markers.cc:900
+msgid "Create Range to Next Marker"
+msgstr "创建范围到下一个标记"
+
+#: editor_markers.cc:941
+msgid "Locate to Marker"
+msgstr "定位到标记"
+
+#: editor_markers.cc:942
+msgid "Play from Marker"
+msgstr "从标记开始播放"
+
+#: editor_markers.cc:945
+msgid "Set Marker from Playhead"
+msgstr "从指针起设置标记"
+
+#: editor_markers.cc:947
+msgid "Set Range from Selection"
+msgstr "从已选择部分起设置范围"
+
+#: editor_markers.cc:957
+msgid "Hide Range"
+msgstr "隐藏范围"
+
+#: editor_markers.cc:958
+msgid "Rename Range..."
+msgstr "重命名范围…"
+
+#: editor_markers.cc:962
+msgid "Remove Range"
+msgstr "移除范围"
+
+#: editor_markers.cc:969
+msgid "Separate Regions in Range"
+msgstr "在范围中分离区域"
+
+#: editor_markers.cc:972
+msgid "Select Range"
+msgstr "选择范围"
+
+#: editor_markers.cc:1001
+msgid "Set Punch Range"
+msgstr "设置切换范围"
+
+#: editor_markers.cc:1407 editor_ops.cc:2040
+msgid "New Name:"
+msgstr "新名称:"
+
+#: editor_markers.cc:1410
+msgid "Rename Mark"
+msgstr "重命名标记"
+
+#: editor_markers.cc:1412
+msgid "Rename Range"
+msgstr "重命名范围"
+
+#: editor_markers.cc:1419 editor_mouse.cc:2137 processor_box.cc:1994
+#: processor_box.cc:2464 route_time_axis.cc:1100 route_ui.cc:1628
+msgid "Rename"
+msgstr "重命名"
+
+#: editor_markers.cc:1432
+msgid "rename marker"
+msgstr "重命名标记"
+
+#: editor_mixer.cc:90
+msgid "This screen is not tall enough to display the editor mixer"
+msgstr "屏幕高度不足以显示编辑器或混音器"
+
+#: editor_mouse.cc:1223 editor_mouse.cc:1241 editor_tempodisplay.cc:270
+msgid "programming error: tempo marker canvas item has no marker object pointer!"
+msgstr "程序错误:节奏标记版面条目没有标记对象物体指示!"
+
+#: editor_mouse.cc:1228 editor_tempodisplay.cc:275
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr "程序错误:节奏上的标记不是一个节奏标记!"
+
+#: editor_mouse.cc:1246 editor_tempodisplay.cc:375
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr "程序错误:节拍上的标记不是一个节拍标记!"
+
+#: editor_mouse.cc:1885 editor_mouse.cc:1910 editor_mouse.cc:1923
+msgid ""
+"programming error: control point canvas item has no control point object pointer!"
+msgstr "程序错误:控制点版面条目没有控制点对象物体指示!"
+
+#: editor_mouse.cc:2058
+msgid "start point trim"
+msgstr "起点修剪"
+
+#: editor_mouse.cc:2083
+msgid "End point trim"
+msgstr "终点修剪"
+
+#: editor_mouse.cc:2135
+msgid "Name for region:"
+msgstr "区域名:"
+
+#: editor_ops.cc:165
+msgid "split"
+msgstr "拆分"
+
+#: editor_ops.cc:339
+msgid "alter selection"
+msgstr "更改已选择部分"
+
+#: editor_ops.cc:381
+msgid "nudge regions forward"
+msgstr "向前微调区域"
+
+#: editor_ops.cc:404 editor_ops.cc:489
+msgid "nudge location forward"
+msgstr "向前微调位置"
+
+#: editor_ops.cc:462
+msgid "nudge regions backward"
+msgstr "向后微调区域"
+
+#: editor_ops.cc:551
+msgid "nudge forward"
+msgstr "向前微调"
+
+#: editor_ops.cc:575
+msgid "nudge backward"
+msgstr "向后微调"
+
+#: editor_ops.cc:618
+msgid "sequence regions"
+msgstr "序列区域"
+
+#: editor_ops.cc:694
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr "构建区域边界缓存调用吸附类型 = %1"
+
+#: editor_ops.cc:2042
+msgid "New Location Marker"
+msgstr "新建位置标记"
+
+#: editor_ops.cc:2164
+msgid "add markers"
+msgstr "添加标记"
+
+#: editor_ops.cc:2274
+msgid "clear markers"
+msgstr "清除表己"
+
+#: editor_ops.cc:2289
+msgid "clear ranges"
+msgstr "清除范围"
+
+#: editor_ops.cc:2305
+msgid "clear locations"
+msgstr "清除位置"
+
+#: editor_ops.cc:2368
+msgid "insert region"
+msgstr "插入区域"
+
+#: editor_ops.cc:2559
+msgid "raise regions"
+msgstr "提升区域"
+
+#: editor_ops.cc:2561
+msgid "raise region"
+msgstr "提升区域"
+
+#: editor_ops.cc:2567
+msgid "raise regions to top"
+msgstr "提升区域到顶部"
+
+#: editor_ops.cc:2569
+msgid "raise region to top"
+msgstr "提升区域到顶部"
+
+#: editor_ops.cc:2575
+msgid "lower regions"
+msgstr "沉降区域"
+
+#: editor_ops.cc:2577 editor_ops.cc:2585
+msgid "lower region"
+msgstr "沉降区域"
+
+#: editor_ops.cc:2583
+msgid "lower regions to bottom"
+msgstr "沉降区域到底部"
+
+#: editor_ops.cc:2668
+msgid "Rename Region"
+msgstr "重命名区域"
+
+#: editor_ops.cc:2670 processor_box.cc:1992 route_ui.cc:1626
+msgid "New name:"
+msgstr "新名称:"
+
+#: editor_ops.cc:2987
+msgid "separate"
+msgstr "分离"
+
+#: editor_ops.cc:3099
+msgid "separate region under"
+msgstr "分离区域位于"
+
+#: editor_ops.cc:3220
+msgid "trim to selection"
+msgstr "修剪到已选中部分"
+
+#: editor_ops.cc:3356
+msgid "set sync point"
+msgstr "设置同步点"
+
+#: editor_ops.cc:3380
+msgid "remove region sync"
+msgstr "移除区域同步"
+
+#: editor_ops.cc:3402
+msgid "move regions to original position"
+msgstr "移动区域到原始位置"
+
+#: editor_ops.cc:3404
+msgid "move region to original position"
+msgstr "移动区域到原始位置"
+
+#: editor_ops.cc:3425
+msgid "align selection"
+msgstr "对齐已选中部分"
+
+#: editor_ops.cc:3499
+msgid "align selection (relative)"
+msgstr "对齐已选中部分(相关)"
+
+#: editor_ops.cc:3533
+msgid "align region"
+msgstr "对齐区域"
+
+#: editor_ops.cc:3584
+msgid "trim front"
+msgstr "修剪前部"
+
+#: editor_ops.cc:3584
+msgid "trim back"
+msgstr "修剪后部"
+
+#: editor_ops.cc:3614
+msgid "trim to loop"
+msgstr "修剪到循环"
+
+#: editor_ops.cc:3624
+msgid "trim to punch"
+msgstr "修剪到切换"
+
+#: editor_ops.cc:3686
+msgid "trim to region"
+msgstr "修剪到区域"
+
+#: editor_ops.cc:3794
+msgid ""
+"This track/bus cannot be frozen because the signal adds or loses channels before "
+"reaching the outputs.\n"
+"This is typically caused by plugins that generate stereo output from mono input or "
+"vice versa."
+msgstr ""
+"这个音轨/总线不能被冻结,因为在信号到达输出前添加或丢失了声道。\n"
+"这通常是由于从单声道输入生成立体声输出(反之亦然)的插件引起的。"
+
+#: editor_ops.cc:3797
+msgid "Cannot freeze"
+msgstr "无法冻结"
+
+#: editor_ops.cc:3803
+msgid ""
+"<b>%1</b>\n"
+"\n"
+"This track has at least one send/insert/return as part of its signal flow.\n"
+"\n"
+"Freezing will only process the signal as far as the first send/insert/return."
+msgstr ""
+"<b>%1</b>\n"
+"\n"
+"这个音轨至少有一个发送/插入/返回作为它的信号流的一部分。\n"
+"\n"
+"冻结将只会处理到信号的第一个发送/插入/返回为止。"
+
+#: editor_ops.cc:3807
+msgid "Freeze anyway"
+msgstr "只管冻结"
+
+#: editor_ops.cc:3808
+msgid "Don't freeze"
+msgstr "不要冻结"
+
+#: editor_ops.cc:3809
+msgid "Freeze Limits"
+msgstr "冻结限制"
+
+#: editor_ops.cc:3824
+msgid "Cancel Freeze"
+msgstr "取消冻结"
+
+#: editor_ops.cc:3854
+msgid ""
+"You can't perform this operation because the processing of the signal will cause "
+"one or more of the tracks to end up with a region with more channels than this "
+"track has inputs.\n"
+"\n"
+"You can do this without processing, which is a different operation."
+msgstr ""
+"您不能执行此操作,因为信号的处理将导致一个或多个音轨以带着多个声道的区域结束,而不"
+"是以这个音轨拥有的输入声道结束。\n"
+"\n"
+"您可以不做任何处理,这是一个不同的操作。"
+
+#: editor_ops.cc:3858
+msgid "Cannot bounce"
+msgstr "不能欢跳弹奏"
+
+#: editor_ops.cc:3869
+msgid "bounce range"
+msgstr "欢跳弹奏范围"
+
+#: editor_ops.cc:3971
+msgid "delete"
+msgstr "删除"
+
+#: editor_ops.cc:3974
+msgid "cut"
+msgstr "剪切"
+
+#: editor_ops.cc:3977
+msgid "copy"
+msgstr "复制"
+
+#: editor_ops.cc:3980
+msgid "clear"
+msgstr "清除"
+
+#: editor_ops.cc:4028
+msgid "objects"
+msgstr "对象物体"
+
+#: editor_ops.cc:4238 editor_ops.cc:4270
+msgid "remove region"
+msgstr "删除区间"
+
+#: editor_ops.cc:4719
+msgid "duplicate selection"
+msgstr "复制已选择部分"
+
+#: editor_ops.cc:4803
+msgid "nudge track"
+msgstr "微调音轨"
+
+#: editor_ops.cc:4840
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"您是否确定要销毁最后已捕获内容?\n"
+"(这个操作有破坏性且不能撤销!)"
+
+#: editor_ops.cc:4843 editor_ops.cc:6838 editor_regions.cc:462
+#: editor_snapshots.cc:159 route_ui.cc:1569
+msgid "No, do nothing."
+msgstr "否, 什么都不做。"
+
+#: editor_ops.cc:4844
+msgid "Yes, destroy it."
+msgstr "是,销毁它。"
+
+#: editor_ops.cc:4846
+msgid "Destroy last capture"
+msgstr "销毁最后捕获的部分"
+
+#: editor_ops.cc:4906
+msgid "normalize"
+msgstr "规范化"
+
+#: editor_ops.cc:5000
+msgid "reverse regions"
+msgstr "反转区域"
+
+#: editor_ops.cc:5034
+msgid "strip silence"
+msgstr "片段无声"
+
+#: editor_ops.cc:5091
+msgid "Fork Region(s)"
+msgstr "分解区域"
+
+#: editor_ops.cc:5112
+msgid "Could not unlink %1"
+msgstr "无法解除链接 %1"
+
+#: editor_ops.cc:5326
+msgid "reset region gain"
+msgstr "重设区域增益"
+
+#: editor_ops.cc:5379
+msgid "region gain envelope active"
+msgstr "区域增益封装激活"
+
+#: editor_ops.cc:5406
+msgid "toggle region lock"
+msgstr "切换区域锁定"
+
+#: editor_ops.cc:5430
+msgid "Toggle Video Lock"
+msgstr "切换视频锁定"
+
+#: editor_ops.cc:5454
+msgid "region lock style"
+msgstr "区域锁定风格"
+
+#: editor_ops.cc:5479
+msgid "change region opacity"
+msgstr "改变区域的模糊度"
+
+#: editor_ops.cc:5572
+msgid "fade range"
+msgstr "淡化范围"
+
+#: editor_ops.cc:5610
+msgid "set fade in length"
+msgstr "设置淡入长度"
+
+#: editor_ops.cc:5617
+msgid "set fade out length"
+msgstr "设置淡出长度"
+
+#: editor_ops.cc:5662
+msgid "set fade in shape"
+msgstr "设置淡入形状"
+
+#: editor_ops.cc:5693
+msgid "set fade out shape"
+msgstr "设置淡出形状"
+
+#: editor_ops.cc:5723
+msgid "set fade in active"
+msgstr "设置淡入启用"
+
+#: editor_ops.cc:5752
+msgid "set fade out active"
+msgstr "设置淡出长度"
+
+#: editor_ops.cc:5994
+msgid "set loop range from selection"
+msgstr "从已选择部分设置循环范围"
+
+#: editor_ops.cc:6008
+msgid "set loop range from region"
+msgstr "从区域设置循环范围"
+
+#: editor_ops.cc:6027
+msgid "set punch range from selection"
+msgstr "从已选择部分设置切换范围"
+
+#: editor_ops.cc:6041
+msgid "set session start/end from selection"
+msgstr "从已选择部分设置会话起点/终点"
+
+#: editor_ops.cc:6066
+msgid "set punch range from region"
+msgstr "从区域设置切换范围"
+
+#: editor_ops.cc:6175
+msgid "Add new marker"
+msgstr "添加新标记"
+
+#: editor_ops.cc:6176
+msgid "Set global tempo"
+msgstr "设置全局节奏"
+
+#: editor_ops.cc:6179
+msgid "Define one bar"
+msgstr "定义一个小节"
+
+#: editor_ops.cc:6180
+msgid "Do you want to set the global tempo or add a new tempo marker?"
+msgstr "您是否要设置全局节奏或者添加一个新的节奏标签?"
+
+#: editor_ops.cc:6206
+msgid "set tempo from region"
+msgstr "从区域设置节奏"
+
+#: editor_ops.cc:6236
+msgid "split regions"
+msgstr "拆分区域"
+
+#: editor_ops.cc:6278
+msgid ""
+"You are about to split\n"
+"%1\n"
+"into %2 pieces.\n"
+"This could take a long time."
+msgstr ""
+"您试图拆分\n"
+" %1\n"
+" 成为 %2 部分。\n"
+"这需要一些时间。"
+
+#: editor_ops.cc:6285
+msgid "Call for the Ferret!"
+msgstr "调用探测!"
+
+#: editor_ops.cc:6286
+msgid ""
+"Press OK to continue with this split operation\n"
+"or ask the Ferret dialog to tune the analysis"
+msgstr ""
+"按OK继续拆分操作\n"
+"或者请求探测对话框进行优化分析"
+
+#: editor_ops.cc:6288
+msgid "Press OK to continue with this split operation"
+msgstr "按OK继续拆分操作"
+
+#: editor_ops.cc:6291
+msgid "Excessive split?"
+msgstr "过多的拆分?"
+
+#: editor_ops.cc:6443
+msgid "place transient"
+msgstr "放置过渡"
+
+#: editor_ops.cc:6478
+msgid "snap regions to grid"
+msgstr "吸附区域到网格"
+
+#: editor_ops.cc:6517
+msgid "Close Region Gaps"
+msgstr "关闭区域空缺"
+
+#: editor_ops.cc:6522
+msgid "Crossfade length"
+msgstr "交叉淡化长度"
+
+#: editor_ops.cc:6531 editor_ops.cc:6542 rhythm_ferret.cc:119
+#: session_option_editor.cc:141
+msgid "ms"
+msgstr ""
+
+#: editor_ops.cc:6533
+msgid "Pull-back length"
+msgstr "撤回长度"
+
+#: editor_ops.cc:6546
+msgid "Ok"
+msgstr ""
+
+#: editor_ops.cc:6561
+msgid "close region gaps"
+msgstr "关闭区域空缺"
+
+#: editor_ops.cc:6786 route_ui.cc:1543
+msgid "That would be bad news ...."
+msgstr "这将是个坏消息…"
+
+#: editor_ops.cc:6791 route_ui.cc:1548
+msgid ""
+"Removing the master or monitor bus is such a bad idea\n"
+"that %1 is not going to allow it.\n"
+"\n"
+"If you really want to do this sort of thing\n"
+"edit your ardour.rc file to set the\n"
+"\"allow-special-bus-removal\" option to be \"yes\""
+msgstr ""
+"删除主控或监控总线可不是个好主意\n"
+"且 %1 不允许这样做。\n"
+"\n"
+"如果您真的想做这种事\n"
+"编辑您的 ardour.rc 文件\n"
+"把\"allow-special-bus-removal\" 选项设为 \"yes\" "
+
+#: editor_ops.cc:6809
+msgid "tracks"
+msgstr "音轨"
+
+#: editor_ops.cc:6811 route_ui.cc:1992
+msgid "track"
+msgstr "音轨"
+
+#: editor_ops.cc:6815
+msgid "busses"
+msgstr "总线"
+
+#: editor_ops.cc:6817 route_ui.cc:1992
+msgid "bus"
+msgstr "总线"
+
+#: editor_ops.cc:6822
+msgid ""
+"Do you really want to remove %1 %2 and %3 %4?\n"
+"(You may also lose the playlists associated with the %2)\n"
+"\n"
+"This action cannot be undone, and the session file will be overwritten!"
+msgstr ""
+"您是否确定移除 %1 %2 和 %3 %4 ?\n"
+"(您也可能会丢失与 %2 相关的播放列表)\n"
+"\n"
+"此操作不可撤销, 而且此会话文件将会被重写覆盖!(您也可能会丢失与 %2 相关的播放列"
+"表)"
+
+#: editor_ops.cc:6827
+msgid ""
+"Do you really want to remove %1 %2?\n"
+"(You may also lose the playlists associated with the %2)\n"
+"\n"
+"This action cannot be undone, and the session file will be overwritten!"
+msgstr ""
+"您是否确定移除 %1 %2 \n"
+"(您也可能会丢失与 %2 相关的播放列表)\n"
+"\n"
+"此操作不可撤销, 而且此会话文件将会被重写覆盖!"
+
+#: editor_ops.cc:6833
+msgid ""
+"Do you really want to remove %1 %2?\n"
+"\n"
+"This action cannot be undone, and the session file will be overwritten"
+msgstr ""
+"您是否确定移除 %1 %2 ?\n"
+"\n"
+"此操作不可撤销, 而且此会话文件将会被重写覆盖"
+
+#: editor_ops.cc:6840
+msgid "Yes, remove them."
+msgstr "是的,移除它们。"
+
+#: editor_ops.cc:6842 editor_snapshots.cc:160 route_ui.cc:1570
+msgid "Yes, remove it."
+msgstr "是的,移除它。"
+
+#: editor_ops.cc:6847 editor_ops.cc:6849
+msgid "Remove %1"
+msgstr "移除 %1"
+
+#: editor_ops.cc:6912
+msgid "insert time"
+msgstr "插入时间"
+
+#: editor_ops.cc:7076
+msgid "There are too many tracks to fit in the current window"
+msgstr "音轨太多以至于无法匹配当前窗口。"
+
+#: editor_ops.cc:7137
+msgid "Sel"
+msgstr "选择"
+
+#: editor_ops.cc:7176
+#, c-format
+msgid "Saved view %u"
+msgstr "保存视图 %u"
+
+#: editor_ops.cc:7201
+msgid "mute regions"
+msgstr "静音区域"
+
+#: editor_ops.cc:7203
+msgid "mute region"
+msgstr "静音区域"
+
+#: editor_ops.cc:7240
+msgid "combine regions"
+msgstr "整合区域"
+
+#: editor_ops.cc:7278
+msgid "uncombine regions"
+msgstr "解除整合区域"
+
+#: editor_ops.cc:7315
+msgid "%1: Locked"
+msgstr "%1: 锁定"
+
+#: editor_ops.cc:7322
+msgid "Click to unlock"
+msgstr "点击解除锁定"
+
+#: editor_ops.cc:7376
+msgid "Moving embedded files into session folder"
+msgstr "移动已嵌入的文件到会话文件夹"
+
+#: editor_regions.cc:112
+msgid "Region name, with number of channels in []'s"
+msgstr "区域名,在 [ ] 方括号内附带声道编号"
+
+#: editor_regions.cc:113
+msgid "Position of start of region"
+msgstr "区域起点的位置"
+
+#: editor_regions.cc:114 editor_regions.cc:851 time_info_box.cc:101
+msgid "End"
+msgstr "终点"
+
+#: editor_regions.cc:114
+msgid "Position of end of region"
+msgstr "区域终点的位置"
+
+#: editor_regions.cc:115
+msgid "Length of the region"
+msgstr "区域的长度"
+
+#: editor_regions.cc:116
+msgid "Position of region sync point, relative to start of the region"
+msgstr "区域同步点的位置,与区域起点相关"
+
+#: editor_regions.cc:117
+msgid "Length of region fade-in (units: secondary clock), () if disabled"
+msgstr "区域淡入的长度(如果无效时,加上单位:秒计时器)"
+
+#: editor_regions.cc:118
+msgid "Length of region fade-out (units: secondary clock), () if disabled"
+msgstr "区域淡出的长度(如果无效时,加上单位:秒计时器)"
+
+#: editor_regions.cc:119 mixer_strip.cc:2055 mono_panner.cc:203 panner2d.cc:240
+#: stereo_panner.cc:251 stereo_panner.cc:274
+msgid "L"
+msgstr ""
+
+#: editor_regions.cc:119
+msgid "Region position locked?"
+msgstr "区域位置锁定?"
+
+#: editor_regions.cc:120 route_time_axis.cc:103
+msgid "G"
+msgstr ""
+
+#: editor_regions.cc:120
+msgid "Region position glued to Bars|Beats time?"
+msgstr "区域位置粘连到小节|拍子时间?"
+
+#: editor_regions.cc:121 editor_routes.cc:211 gain_meter.cc:793 mixer_strip.cc:2032
+#: meter_strip.cc:359 panner_ui.cc:603 route_time_axis.cc:2713 stereo_panner.cc:271
+#: time_axis_view.cc:1190
+msgid "M"
+msgstr ""
+
+#: editor_regions.cc:121
+msgid "Region muted?"
+msgstr "区域静音?"
+
+#: editor_regions.cc:122 mixer_strip.cc:1855
+msgid "O"
+msgstr ""
+
+#: editor_regions.cc:122
+msgid "Region opaque (blocks regions below it from being heard)?"
+msgstr "区域模糊(从区域块以下的部分起可以被听见)?"
+
+#: editor_regions.cc:311 editor_regions.cc:316 editor_regions.cc:318
+msgid "Hidden"
+msgstr "隐藏"
+
+#: editor_regions.cc:391
+msgid "(MISSING) "
+msgstr "(缺失)"
+
+#: editor_regions.cc:459
+msgid ""
+"Do you really want to remove unused regions?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"您真的打算移除未使用的区域?\n"
+"(这是破坏性的且无法撤销)"
+
+#: editor_regions.cc:463
+msgid "Yes, remove."
+msgstr "是的,移除。"
+
+#: editor_regions.cc:465
+msgid "Remove unused regions"
+msgstr "移除未使用的区域"
+
+#: editor_regions.cc:818 editor_regions.cc:832 editor_regions.cc:846
+msgid "Mult."
+msgstr "多"
+
+#: editor_regions.cc:849 midi_list_editor.cc:104 time_info_box.cc:94
+msgid "Start"
+msgstr "起点"
+
+#: editor_regions.cc:867 editor_regions.cc:883
+msgid "Multiple"
+msgstr "多个"
+
+#: editor_regions.cc:952
+msgid "MISSING "
+msgstr "缺失"
+
+#: editor_routes.cc:182 editor_routes.cc:214
+msgid "SS"
+msgstr ""
+
+#: editor_routes.cc:206
+msgid "Track/Bus Name"
+msgstr "音轨/总线名称"
+
+#: editor_routes.cc:207
+msgid "Track/Bus visible ?"
+msgstr "音轨/总线可见?"
+
+#: editor_routes.cc:208 mixer_strip.cc:2046 meter_strip.cc:371
+#: route_time_axis.cc:105 route_time_axis.cc:2701
+msgid "A"
+msgstr ""
+
+#: editor_routes.cc:208
+msgid "Track/Bus active ?"
+msgstr "音轨/总线启用?"
+
+#: editor_routes.cc:209 mixer_strip.cc:2033 mixer_strip.cc:2054 meter_strip.cc:379
+msgid "I"
+msgstr ""
+
+#: editor_routes.cc:209
+msgid "MIDI input enabled"
+msgstr "MIDI输入已启用"
+
+#: editor_routes.cc:210 mono_panner.cc:220 panner2d.cc:241 stereo_panner.cc:249
+#: stereo_panner.cc:276
+msgid "R"
+msgstr ""
+
+#: editor_routes.cc:210
+msgid "Record enabled"
+msgstr "录制已启用"
+
+#: editor_routes.cc:211
+msgid "Muted"
+msgstr "已静音"
+
+#: editor_routes.cc:212 mixer_strip.cc:2042 meter_strip.cc:367
+#: route_time_axis.cc:2710
+msgid "S"
+msgstr ""
+
+#: editor_routes.cc:212
+msgid "Soloed"
+msgstr "已独奏"
+
+#: editor_routes.cc:213
+msgid "SI"
+msgstr ""
+
+#: editor_routes.cc:213
+msgid "Solo Isolated"
+msgstr "独奏已隔离"
+
+#: editor_routes.cc:214
+msgid "Solo Safe (Locked)"
+msgstr "独奏安全(锁定)"
+
+#: editor_routes.cc:477 mixer_ui.cc:1197
+msgid "Hide All"
+msgstr "隐藏所有"
+
+#: editor_routes.cc:478 mixer_ui.cc:1198
+msgid "Show All Audio Tracks"
+msgstr "显示所有音频轨道"
+
+#: editor_routes.cc:479 mixer_ui.cc:1199
+msgid "Hide All Audio Tracks"
+msgstr "隐藏所有音频轨道"
+
+#: editor_routes.cc:480 mixer_ui.cc:1200
+msgid "Show All Audio Busses"
+msgstr "显示所有音频总线"
+
+#: editor_routes.cc:481 mixer_ui.cc:1201
+msgid "Hide All Audio Busses"
+msgstr "隐藏所有音频总线"
+
+#: editor_routes.cc:482
+msgid "Show All Midi Tracks"
+msgstr "显示所有MIDI轨"
+
+#: editor_routes.cc:483
+msgid "Hide All Midi Tracks"
+msgstr "隐藏所有MIDI轨"
+
+#: editor_routes.cc:484
+msgid "Show Tracks With Regions Under Playhead"
+msgstr "显示指针后面区域的轨道"
+
+#: editor_rulers.cc:211
+msgid "New location marker"
+msgstr "新建位置标记"
+
+#: editor_rulers.cc:212
+msgid "Clear all locations"
+msgstr "清除所有位置"
+
+#: editor_rulers.cc:213
+msgid "Unhide locations"
+msgstr "取消隐藏位置"
+
+#: editor_rulers.cc:217
+msgid "New range"
+msgstr "新建范围"
+
+#: editor_rulers.cc:218
+msgid "Clear all ranges"
+msgstr "清除所有范围"
+
+#: editor_rulers.cc:219
+msgid "Unhide ranges"
+msgstr "取消隐藏范围"
+
+#: editor_rulers.cc:224
+msgid "Make Loop range"
+msgstr "设为循环范围"
+
+#: editor_rulers.cc:225
+msgid "Make Punch range"
+msgstr "设为切换范围"
+
+#: editor_rulers.cc:230
+msgid "New CD track marker"
+msgstr "新建CD音轨标签"
+
+#: editor_rulers.cc:235 tempo_dialog.cc:38
+msgid "New Tempo"
+msgstr "新节奏"
+
+#: editor_rulers.cc:239 tempo_dialog.cc:296
+msgid "New Meter"
+msgstr "新节拍"
+
+#: editor_snapshots.cc:137
+msgid "Rename Snapshot"
+msgstr "重命名快照"
+
+#: editor_snapshots.cc:139
+msgid "New name of snapshot"
+msgstr "快照的新名称"
+
+#: editor_snapshots.cc:157
+msgid ""
+"Do you really want to remove snapshot \"%1\" ?\n"
+"(which cannot be undone)"
+msgstr ""
+"您是否确定移除快照 \"%1\"?\n"
+"(此操作不可撤销)"
+
+#: editor_snapshots.cc:162
+msgid "Remove snapshot"
+msgstr "移除快照"
+
+#: editor_tempodisplay.cc:194 editor_tempodisplay.cc:234
+msgid "add"
+msgstr "添加"
+
+#: editor_tempodisplay.cc:215
+msgid "add tempo mark"
+msgstr "添加节奏标记"
+
+#: editor_tempodisplay.cc:254
+msgid "add meter mark"
+msgstr "添加节拍标记"
+
+#: editor_tempodisplay.cc:287 editor_tempodisplay.cc:315
+msgid "done"
+msgstr "完成"
+
+#: editor_tempodisplay.cc:304 editor_tempodisplay.cc:330
+msgid "replace tempo mark"
+msgstr "替换节奏标记"
+
+#: editor_tempodisplay.cc:353 editor_tempodisplay.cc:387
+msgid "remove tempo mark"
+msgstr "移除节奏标记"
+
+#: editor_tempodisplay.cc:370
+msgid "programming error: meter marker canvas item has no marker object pointer!"
+msgstr "程序错误:节拍标记版面条目没有标记对象物体指示!"
+
+#: editor_timefx.cc:68
+msgid "stretch/shrink"
+msgstr "延伸/收缩"
+
+#: editor_timefx.cc:129
+msgid "pitch shift"
+msgstr "音高替换"
+
+#: editor_timefx.cc:301
+msgid "timefx cannot be started - thread creation error"
+msgstr "间特效无法启动 - 线程创建错误"
+
+#: engine_dialog.cc:83
+msgid "Device Control Panel"
+msgstr "设备控制面板"
+
+#: engine_dialog.cc:84
+msgid "Midi Device Setup"
+msgstr "MIDI设备设置"
+
+#: engine_dialog.cc:85 engine_dialog.cc:2097
+msgid "Measure"
+msgstr "测量"
+
+#: engine_dialog.cc:86
+msgid "Use results"
+msgstr "使用结果"
+
+#: engine_dialog.cc:87
+msgid "Back to settings ... (ignore results)"
+msgstr "回到设置…(忽略结果)"
+
+#: engine_dialog.cc:88
+msgid "Calibrate Audio"
+msgstr "校正音频"
+
+#: engine_dialog.cc:92
+msgid "Back to settings"
+msgstr "回到设置"
+
+#: engine_dialog.cc:111
+msgid ""
+"No audio/MIDI backends detected. %1 cannot run\n"
+"\n"
+"(This is a build/packaging/system error. It should never happen.)"
+msgstr ""
+"未检测到音频/MIDI后端。 %1 无法运行\n"
+"\n"
+"(这是一个构建/包装/系统错误。它应该永远不会发生。)"
+
+#: engine_dialog.cc:137
+msgid "Latency Measurement Tool"
+msgstr "延迟测量工具"
+
+#: engine_dialog.cc:149
+msgid ""
+"<span weight=\"bold\">Turn down the volume on your audio equipment to a very low "
+"level.</span>"
+msgstr "<span weight=\"bold\">调低您的音频设备音量到一个非常低的水平。</span>"
+
+#: engine_dialog.cc:158
+msgid "Select two channels below and connect them using a cable."
+msgstr "选择下面两个声道并和使用线条连接它们。"
+
+#: engine_dialog.cc:163
+msgid "Output channel"
+msgstr "输出声道"
+
+#: engine_dialog.cc:171
+msgid "Input channel"
+msgstr "输入声道"
+
+#: engine_dialog.cc:206
+msgid "Once the channels are connected, click the \"Measure\" button."
+msgstr "一旦声道已连接好,单击“测量”按钮。"
+
+#: engine_dialog.cc:213
+msgid "When satisfied with the results, click the \"Use results\" button."
+msgstr "如果得到了令人满意的结果,请点击“使用结果”按钮。"
+
+#: engine_dialog.cc:228 engine_dialog.cc:2217 engine_dialog.cc:2227
+msgid "No measurement results yet"
+msgstr "还没有测量结果"
+
+#: engine_dialog.cc:238 route_params_ui.cc:106
+msgid "Latency"
+msgstr "延迟"
+
+#: engine_dialog.cc:372
+msgid "Audio System:"
+msgstr "音频系统:"
+
+#: engine_dialog.cc:409
+msgid "Driver:"
+msgstr "驱动:"
+
+#: engine_dialog.cc:415
+msgid "Device:"
+msgstr "设备:"
+
+#: engine_dialog.cc:420 engine_dialog.cc:519 sfdb_ui.cc:153 sfdb_ui.cc:348
+#: sfdb_ui.cc:353
+msgid "Sample rate:"
+msgstr "采样率:"
+
+#: engine_dialog.cc:426 engine_dialog.cc:526
+msgid "Buffer size:"
+msgstr "缓冲区大小:"
+
+#: engine_dialog.cc:444
+msgid "Input Channels:"
+msgstr "输入声道:"
+
+#: engine_dialog.cc:457
+msgid "Output Channels:"
+msgstr "输出声道:"
+
+#: engine_dialog.cc:469
+msgid "Hardware input latency:"
+msgstr "硬件输入延迟:"
+
+#: engine_dialog.cc:472 engine_dialog.cc:485
+msgid "samples"
+msgstr "采样"
+
+#: engine_dialog.cc:482
+msgid "Hardware output latency:"
+msgstr "硬件输出延迟:"
+
+#: engine_dialog.cc:493
+msgid "MIDI System:"
+msgstr "MIDI系统:"
+
+#: engine_dialog.cc:511
+msgid ""
+"The %1 audio backend was configured and started externally.\n"
+"This limits your control over it."
+msgstr ""
+"音频后端已配置并已在外部启动。\n"
+"这限制了您对它的控制力。"
+
+#: engine_dialog.cc:564
+msgid ""
+"Failed to start or connect to audio-engine.\n"
+"\n"
+"Latency calibration requires a working audio interface."
+msgstr ""
+"启动或链接音频引擎失败。\n"
+"\n"
+"延迟校准需要有一个音频接口在工作。"
+
+#: engine_dialog.cc:570
+msgid ""
+"Your selected audio configuration is playback- or capture-only.\n"
+"\n"
+"Latency calibration requires playback and capture"
+msgstr ""
+"您已选择的音频配置仅供回放或仅供捕获。\n"
+"\n"
+"延迟校准需要回放和捕捉"
+
+#: engine_dialog.cc:651
+msgid "MIDI Devices"
+msgstr "MIDI 设备"
+
+#: engine_dialog.cc:657
+msgid "Device"
+msgstr "设备"
+
+#: engine_dialog.cc:659
+msgid "Hardware Latencies"
+msgstr "硬件延迟"
+
+#: engine_dialog.cc:700
+msgid "Calibrate"
+msgstr "æ ¡æ­£"
+
+#: engine_dialog.cc:800
+msgid "all available channels"
+msgstr "所有可用的声道"
+
+#: engine_dialog.cc:1039 latency_gui.cc:39
+msgid "sample"
+msgid_plural "samples"
+msgstr[0] "采样"
+
+#: engine_dialog.cc:1090
+#, c-format
+msgid "(%.1f ms)"
+msgstr ""
+
+#: engine_dialog.cc:1593
+msgid "Could not start backend engine %1"
+msgstr "无法启动后端引擎 %1"
+
+#: engine_dialog.cc:1644
+msgid "Cannot set driver to %1"
+msgstr "无法设置驱动到 %1"
+
+#: engine_dialog.cc:1648
+msgid "Cannot set device name to %1"
+msgstr "无法设置设备名称到 %1"
+
+#: engine_dialog.cc:1652
+msgid "Cannot set sample rate to %1"
+msgstr "无法设置采样率到 %1"
+
+#: engine_dialog.cc:1656
+msgid "Cannot set buffer size to %1"
+msgstr "无法设置缓冲区大小到 %1"
+
+#: engine_dialog.cc:1662
+msgid "Cannot set input channels to %1"
+msgstr "无法设置输入声道到 %1"
+
+#: engine_dialog.cc:1666
+msgid "Cannot set output channels to %1"
+msgstr "无法设置输出声道到 %1"
+
+#: engine_dialog.cc:1672
+msgid "Cannot set input latency to %1"
+msgstr "无法设置输入延迟到 %1"
+
+#: engine_dialog.cc:1676
+msgid "Cannot set output latency to %1"
+msgstr "无法设置输出延迟到 %1"
+
+#: engine_dialog.cc:1955 engine_dialog.cc:2014
+msgid "No signal detected "
+msgstr "未检测到信号"
+
+#: engine_dialog.cc:1968 engine_dialog.cc:2022 port_insert_ui.cc:70
+#: port_insert_ui.cc:98
+msgid "Disconnected from audio engine"
+msgstr "与音频引擎已断开连接"
+
+#: engine_dialog.cc:1977 engine_dialog.cc:2030
+msgid "Detected roundtrip latency: "
+msgstr "检测到往返延迟:"
+
+#: engine_dialog.cc:1979 engine_dialog.cc:2032
+msgid "Systemic latency: "
+msgstr "系统延迟:"
+
+#: engine_dialog.cc:1986
+msgid "(signal detection error)"
+msgstr "(信号检测错误)"
+
+#: engine_dialog.cc:1992
+msgid "(inverted - bad wiring)"
+msgstr "(反向 - 损坏接线)"
+
+#: engine_dialog.cc:2039
+msgid "(averaging)"
+msgstr "(平均)"
+
+#: engine_dialog.cc:2045
+msgid "(too large jitter)"
+msgstr "(振幅过大)"
+
+#: engine_dialog.cc:2049
+msgid "(large jitter)"
+msgstr "(大振幅)"
+
+#: engine_dialog.cc:2061
+msgid "Timeout - large MIDI jitter."
+msgstr "超时 - 大MIDI振幅。"
+
+#: engine_dialog.cc:2077 port_insert_ui.cc:134
+msgid "Detecting ..."
+msgstr "检测中…"
+
+#: engine_dialog.cc:2171
+msgid "Disconnect from %1"
+msgstr "与 %1 失去连接"
+
+#: engine_dialog.cc:2175 mixer_strip.cc:1522 route_group_dialog.cc:45
+#: route_time_axis.cc:841
+msgid "Active"
+msgstr "激活"
+
+#: engine_dialog.cc:2185
+msgid "Connect to %1"
+msgstr "连接到 %1"
+
+#: engine_dialog.cc:2190
+msgid "Inactive"
+msgstr "未激活"
+
+#: export_channel_selector.cc:45 sfdb_ui.cc:151
+msgid "Channels:"
+msgstr "声道:"
+
+#: export_channel_selector.cc:46
+msgid "Split to mono files"
+msgstr "拆分到单声道文件"
+
+#: export_channel_selector.cc:182
+msgid "Bus or Track"
+msgstr "总线或音轨"
+
+#: export_channel_selector.cc:459
+msgid "Region contents without fades nor region gain (channels: %1)"
+msgstr "区域内容没有淡化也没有区域增益(声道: %1)"
+
+#: export_channel_selector.cc:463
+msgid "Region contents with fades and region gain (channels: %1)"
+msgstr "区域内容带有淡化和区域增益(声道: %1)"
+
+#: export_channel_selector.cc:467
+msgid "Track output (channels: %1)"
+msgstr "音轨输出 (声道: %1)"
+
+#: export_channel_selector.cc:536
+msgid "Export region contents"
+msgstr "导出区域内容"
+
+#: export_channel_selector.cc:537
+msgid "Export track output"
+msgstr "导出音轨输出"
+
+#: export_dialog.cc:46
+msgid ""
+"<span color=\"#ffa755\">Some already existing files will be overwritten.</span>"
+msgstr "<span color=\"#ffa755\">一些已存在的文件将会被写入覆盖。</span>"
+
+#: export_dialog.cc:47
+msgid "List files"
+msgstr "列表文件"
+
+#: export_dialog.cc:158 export_format_dialog.cc:59
+msgid "File format"
+msgstr "文件格式"
+
+#: export_dialog.cc:159 export_timespan_selector.cc:374
+#: export_timespan_selector.cc:436
+msgid "Time Span"
+msgstr "时间跨度"
+
+#: export_dialog.cc:160
+msgid "Channels"
+msgstr "声道"
+
+#: export_dialog.cc:182
+msgid ""
+"Export has been aborted due to an error!\n"
+"See the Log for details."
+msgstr ""
+"导出意外中止,因为有个错误!\n"
+"详情请见日志。"
+
+#: export_dialog.cc:251
+msgid "Files that will be overwritten"
+msgstr "将会被被写入覆盖的文件"
+
+#: export_dialog.cc:296
+msgid "Export initialization failed: %1"
+msgstr "导出初始化失败: %1"
+
+#: export_dialog.cc:306
+msgid "Stop Export"
+msgstr "Stop Export 停止导出"
+
+#: export_dialog.cc:327
+msgid "export"
+msgstr "导出"
+
+#: export_dialog.cc:346
+msgid "Normalizing '%3' (timespan %1 of %2)"
+msgstr "规范化 '%3' (时间跨度 %1 的 %2)"
+
+#: export_dialog.cc:350
+msgid "Exporting '%3' (timespan %1 of %2)"
+msgstr "导出 '%3' (时间跨度 %1 的 %2)"
+
+#: export_dialog.cc:373 export_dialog.cc:375
+msgid "<span color=\"#ffa755\">Error: "
+msgstr "<span color=\"#ffa755\">错误:"
+
+#: export_dialog.cc:385
+msgid "<span color=\"#ffa755\">Warning: "
+msgstr "<span color=\"#ffa755\">警告:"
+
+#: export_dialog.cc:387
+msgid ""
+"\n"
+"<span color=\"#ffa755\">Warning: "
+msgstr ""
+"\n"
+"<span color=\"#ffa755\">警告:"
+
+#: export_dialog.cc:411
+msgid "Export Selection"
+msgstr "导出已选择部分"
+
+#: export_dialog.cc:425
+msgid "Export Region"
+msgstr "导出区域"
+
+#: export_dialog.cc:434
+msgid "Source"
+msgstr "源"
+
+#: export_dialog.cc:450
+msgid "Stem Export"
+msgstr "逆向导出"
+
+#: export_file_notebook.cc:39
+msgid "Add another format"
+msgstr "添加另一个格式"
+
+#: export_file_notebook.cc:193
+msgid "Format"
+msgstr "格式"
+
+#: export_file_notebook.cc:194
+msgid "Location"
+msgstr "位置"
+
+#: export_file_notebook.cc:195
+msgid "Upload to Soundcloud"
+msgstr "上传到Soundcloud"
+
+#: export_file_notebook.cc:273
+msgid "No format!"
+msgstr "不格式化!"
+
+#: export_file_notebook.cc:291
+msgid "Format %1: %2"
+msgstr "格式化 %1: %2"
+
+#: export_filename_selector.cc:32
+msgid "Label:"
+msgstr "标签:"
+
+#: export_filename_selector.cc:33
+msgid "Session Name"
+msgstr "会话名称"
+
+#: export_filename_selector.cc:34
+msgid "Revision:"
+msgstr "修订版本:"
+
+#: export_filename_selector.cc:36
+msgid "Folder:"
+msgstr "文件夹:"
+
+#: export_filename_selector.cc:37 session_import_dialog.cc:45
+#: transcode_video_dialog.cc:59 video_server_dialog.cc:54 video_server_dialog.cc:56
+#: export_video_dialog.cc:81 export_video_dialog.cc:83
+msgid "Browse"
+msgstr "浏览"
+
+#: export_filename_selector.cc:41
+msgid "<i>Build filename(s) from these components:</i>"
+msgstr "<i>从这些组件构建文件名:</i>"
+
+#: export_filename_selector.cc:212
+msgid "<small><i>Sorry, no example filename can be shown at the moment</i></small>"
+msgstr "<small><i>对不起,目前没有例子文件名可以显示</i></small>"
+
+#: export_filename_selector.cc:214
+msgid "<small><i>Current (approximate) filename: \"%1\"</i></small>"
+msgstr "<small><i>当前(近似)文件名: ”%1“</i></small>"
+
+#: export_filename_selector.cc:250 export_filename_selector.cc:336
+msgid ""
+"%1: this is only the directory/folder name, not the filename.\n"
+"The filename will be chosen from the information just above the folder selector."
+msgstr ""
+"%1:这仅是目录/文件夹名称,不是文件名\n"
+"将会从刚才上面的文件选择器信息里选出文件名。"
+
+#: export_filename_selector.cc:322
+msgid "Choose export folder"
+msgstr "选择导出文件夹"
+
+#: export_format_dialog.cc:31
+msgid "New Export Format Profile"
+msgstr "新建导出格式配置文件"
+
+#: export_format_dialog.cc:31
+msgid "Edit Export Format Profile"
+msgstr "编辑导出格式配置文件"
+
+#: export_format_dialog.cc:38
+msgid "Label: "
+msgstr "标签:"
+
+#: export_format_dialog.cc:41 normalize_dialog.cc:42
+msgid "Normalize to:"
+msgstr "规范化到:"
+
+#: export_format_dialog.cc:46
+msgid "Trim silence at start"
+msgstr "在起点修剪无声"
+
+#: export_format_dialog.cc:47
+msgid "Add silence at start:"
+msgstr "在起点添加无声:"
+
+#: export_format_dialog.cc:50
+msgid "Trim silence at end"
+msgstr "在终点修剪无声"
+
+#: export_format_dialog.cc:51
+msgid "Add silence at end:"
+msgstr "在终点添加无声:"
+
+#: export_format_dialog.cc:54
+msgid ""
+"Command to run post-export\n"
+"(%f=full path & filename, %d=directory, %b=basename):"
+msgstr ""
+"运行后置-导出的命令\n"
+"(%f=完整路径和文件名,%d=目录,%b=基本名称):"
+
+#: export_format_dialog.cc:57
+msgid "Compatibility"
+msgstr "兼容性"
+
+#: export_format_dialog.cc:58
+msgid "Quality"
+msgstr "质量"
+
+#: export_format_dialog.cc:61
+msgid "Sample rate conversion quality:"
+msgstr "采样率转换质量:"
+
+#: export_format_dialog.cc:68
+msgid "Dithering"
+msgstr "抖动"
+
+# CUE  cuesheet 是指光盘映像(镜像)辅助文件或称标记文件
+#: export_format_dialog.cc:70
+msgid "Create CUE file for disk-at-once CD/DVD creation"
+msgstr "为创建一次性CD/DVD光盘而创建CUE文件"
+
+# 目录数据 (Table of Content,TOC)
+#: export_format_dialog.cc:71
+msgid "Create TOC file for disk-at-once CD/DVD creation"
+msgstr "为创建一次性CD/DVD光盘而创建TOC文件"
+
+#: export_format_dialog.cc:73
+msgid "Tag file with session's metadata"
+msgstr "会话元数据的标签文件"
+
+#: export_format_dialog.cc:470
+msgid "Best (sinc)"
+msgstr "最佳(sinc)"
+
+#: export_format_dialog.cc:475
+msgid "Medium (sinc)"
+msgstr "中等(sinc)"
+
+#: export_format_dialog.cc:480
+msgid "Fast (sinc)"
+msgstr "快速(sinc)"
+
+#: export_format_dialog.cc:490
+msgid "Zero order hold"
+msgstr "零阶保持"
+
+#: export_format_dialog.cc:895
+msgid "Linear encoding options"
+msgstr "线性编码选项"
+
+#: export_format_dialog.cc:911
+msgid "Ogg Vorbis options"
+msgstr "Ogg Vorbis 选项"
+
+#: export_format_dialog.cc:922
+msgid "FLAC options"
+msgstr "FLAC 选项"
+
+#: export_format_dialog.cc:939
+msgid "Broadcast Wave options"
+msgstr "广播Wave选项"
+
+#: export_format_selector.cc:136
+msgid "Do you really want to remove the format?"
+msgstr "您是否真的要移除这个格式?"
+
+#: export_preset_selector.cc:28
+msgid "Preset"
+msgstr "预设"
+
+#: export_preset_selector.cc:104
+msgid ""
+"The selected preset did not load successfully!\n"
+"Perhaps it references a format that has been removed?"
+msgstr ""
+"被选中的预设载入失败!\n"
+"也许它引用了一个已被删除的格式?"
+
+#: export_preset_selector.cc:156
+msgid "Do you really want to remove this preset?"
+msgstr "您是否真的要移除这个预设?"
+
+#: export_timespan_selector.cc:46
+msgid "Show Times as:"
+msgstr "显示时间为:"
+
+#: export_timespan_selector.cc:53 processor_box.cc:2466
+msgid "Select All"
+msgstr "选择所有"
+
+#: export_timespan_selector.cc:223 transform_dialog.cc:93
+msgid " to "
+msgstr "到"
+
+#: export_timespan_selector.cc:367 export_timespan_selector.cc:426
+msgid "Range"
+msgstr "范围"
+
+#: sfdb_freesound_mootcher.cc:189 sfdb_freesound_mootcher.cc:324
+msgid "curl error %1 (%2)"
+msgstr "回旋错误 %1 (%2)"
+
+#: sfdb_freesound_mootcher.cc:266
+msgid "getSoundResourceFile: There is no valid root in the xml file"
+msgstr "获取声音资源文件:在 xml 文件里没有正确的根"
+
+#: sfdb_freesound_mootcher.cc:271
+msgid "getSoundResourceFile: root = %1, != response"
+msgstr "获取声音资源文件:根 = %1, ! = 响应"
+
+#: sfdb_freesound_mootcher.cc:410 rc_option_editor.cc:1824
+msgid "%1"
+msgstr ""
+
+#: gain_meter.cc:132 gain_meter.cc:400 gain_meter.cc:505 gain_meter.cc:896
+msgid "-inf"
+msgstr ""
+
+#: gain_meter.cc:147 gain_meter.cc:958
+msgid "Fader automation mode"
+msgstr "淡化器自动模式"
+
+#: gain_meter.cc:148 gain_meter.cc:959
+msgid "Fader automation type"
+msgstr "淡化器自动类型"
+
+#: gain_meter.cc:157 gain_meter.cc:829 panner_ui.cc:179 panner_ui.cc:639
+msgid "Abs"
+msgstr ""
+
+#: gain_meter.cc:796 mixer_strip.cc:2049 meter_strip.cc:374 panner_ui.cc:606
+#: route_time_axis.cc:104 route_time_axis.cc:2705
+msgid "P"
+msgstr ""
+
+#: gain_meter.cc:799 panner_ui.cc:609
+msgid "T"
+msgstr ""
+
+#: gain_meter.cc:802 panner_ui.cc:612
+msgid "W"
+msgstr ""
+
+#: generic_pluginui.cc:83
+msgid "<span size=\"large\">Presets</span>"
+msgstr "<span size=\"large\">预设</span>"
+
+#: generic_pluginui.cc:97
+msgid "Manual"
+msgstr "手册"
+
+#: generic_pluginui.cc:106
+msgid "All Automation"
+msgstr "全部自动化"
+
+#: generic_pluginui.cc:250
+msgid "Switches"
+msgstr "转换"
+
+#: generic_pluginui.cc:260 generic_pluginui.cc:436 processor_box.cc:2440
+msgid "Controls"
+msgstr "控制"
+
+#: generic_pluginui.cc:293
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr "插件编辑器:无法为端口 %1 建立控制元素"
+
+#: generic_pluginui.cc:318
+msgid "Plugin Editor: no control for property %1"
+msgstr "插件编辑器:无法控制 %1 属性"
+
+#: generic_pluginui.cc:324
+msgid "Plugin Editor: could not build control element for property %1"
+msgstr "插件编辑器:无法为 %1 属性建立控制元素"
+
+#: generic_pluginui.cc:468
+msgid "Meters"
+msgstr "节拍"
+
+#: generic_pluginui.cc:490
+msgid "Automation control"
+msgstr "自动控制"
+
+#: generic_pluginui.cc:497
+msgid "Mgnual"
+msgstr ""
+
+#: global_port_matrix.cc:158
+msgid "Audio Connection Manager"
+msgstr "音频连结管理器"
+
+#: global_port_matrix.cc:161
+msgid "MIDI Connection Manager"
+msgstr "MIDI连接管理器"
+
+#: global_port_matrix.cc:201 io_selector.cc:211 mixer_strip.cc:793
+#: mixer_strip.cc:894
+msgid "Disconnect"
+msgstr "取消连接"
+
+#: global_port_matrix.cc:207 io_selector.cc:217
+msgid "port"
+msgstr "端口"
+
+#: group_tabs.cc:312
+msgid "Selection..."
+msgstr "已选择部分…"
+
+#: group_tabs.cc:313
+msgid "Record Enabled..."
+msgstr "启用录制…"
+
+#: group_tabs.cc:314
+msgid "Soloed..."
+msgstr "独奏…"
+
+#: group_tabs.cc:320
+msgid "Create New Group ..."
+msgstr "创建新的分组…"
+
+#: group_tabs.cc:321
+msgid "Create New Group From"
+msgstr "创建新的分组来自于"
+
+#: group_tabs.cc:324
+msgid "Edit Group..."
+msgstr "编辑分组…"
+
+#: group_tabs.cc:325
+msgid "Collect Group"
+msgstr "收集分组"
+
+#: group_tabs.cc:326
+msgid "Remove Group"
+msgstr "移除分组"
+
+#: group_tabs.cc:329
+msgid "Remove Subgroup Bus"
+msgstr "移除次级分组总线"
+
+#: group_tabs.cc:331
+msgid "Add New Subgroup Bus"
+msgstr "添加新的次级分组总线"
+
+#: group_tabs.cc:333
+msgid "Add New Aux Bus (pre-fader)"
+msgstr "添加新的辅助总线(前置淡化)"
+
+#: group_tabs.cc:334
+msgid "Add New Aux Bus (post-fader)"
+msgstr "添加新的辅助总线(后置淡化)"
+
+#: group_tabs.cc:340
+msgid "Enable All Groups"
+msgstr "启用所有分组"
+
+#: group_tabs.cc:341
+msgid "Disable All Groups"
+msgstr "禁用所有分组"
+
+#: insert_time_dialog.cc:46
+msgid "Time to insert:"
+msgstr "要插入的时间位置:"
+
+#: insert_time_dialog.cc:54
+msgid "Intersected regions should:"
+msgstr "相交的区域应该:"
+
+#: insert_time_dialog.cc:57
+msgid "stay in position"
+msgstr "停留在原位"
+
+#: insert_time_dialog.cc:58
+msgid "move"
+msgstr "移动"
+
+#: insert_time_dialog.cc:59
+msgid "be split"
+msgstr "拆分"
+
+#: insert_time_dialog.cc:65
+msgid "Insert time on all the track's playlists"
+msgstr "在所有的音轨播放列表上插入时间"
+
+#: insert_time_dialog.cc:68
+msgid "Move glued regions"
+msgstr "移动被粘连的区域"
+
+#: insert_time_dialog.cc:70
+msgid "Move markers"
+msgstr "移动标记"
+
+#: insert_time_dialog.cc:73
+msgid "Move glued markers"
+msgstr "移动被粘连的标记"
+
+#: insert_time_dialog.cc:78
+msgid "Move locked markers"
+msgstr "移动被锁定的标记"
+
+#: insert_time_dialog.cc:83
+msgid ""
+"Move tempo and meter changes\n"
+"<i>(may cause oddities in the tempo map)</i>"
+msgstr ""
+"移动节奏和节拍变化\n"
+"(也许会在节奏图中引发异常)"
+
+#: insert_time_dialog.cc:91
+msgid "Insert time"
+msgstr "插入时间"
+
+#: instrument_selector.cc:62
+msgid "-none-"
+msgstr "— 无 —"
+
+#: interthread_progress_window.cc:103
+msgid "Importing file: %1 of %2"
+msgstr "导入文件: %2 的 %1"
+
+#: io_selector.cc:221
+msgid "I/O selector"
+msgstr "输入/输出选择器"
+
+#: io_selector.cc:266
+msgid "%1 input"
+msgstr "%1 输入"
+
+#: io_selector.cc:268
+msgid "%1 output"
+msgstr "%1 输出"
+
+#: keyboard.cc:70
+msgid "your own"
+msgstr "您自己的"
+
+#: keyboard.cc:133 keyboard.cc:157
+msgid "Default keybindings not found - %1 will be hard to use!"
+msgstr "找不到默认的按键绑定—— %1 将很难使用!"
+
+#: keyboard.cc:136
+msgid "Key bindings file \"%1\" not found. Default bindings used instead"
+msgstr "找不到按键绑定文件 \"%1\"。使用默认绑定替代。"
+
+#: keyeditor.cc:54
+msgid "Remove shortcut"
+msgstr "移除快捷键"
+
+#: keyeditor.cc:63
+msgid "Action"
+msgstr "操作"
+
+#: keyeditor.cc:64
+msgid "Shortcut"
+msgstr "快捷键"
+
+#: keyeditor.cc:84
+msgid "Select an action, then press the key(s) to (re)set its shortcut"
+msgstr "选择一个操作,然后按下按键来(重新)设置快捷键"
+
+#: keyeditor.cc:98
+msgid "Reset Bindings to Defaults"
+msgstr "重置为默认绑定"
+
+#: keyeditor.cc:263
+msgid "Main_menu"
+msgstr "主菜单"
+
+#: keyeditor.cc:265
+msgid "redirectmenu"
+msgstr "重定向菜单"
+
+#: keyeditor.cc:267
+msgid "Editor_menus"
+msgstr "编辑器菜单"
+
+#: keyeditor.cc:269
+msgid "RegionList"
+msgstr "区域列表"
+
+#: keyeditor.cc:271
+msgid "ProcessorMenu"
+msgstr "处理器菜单"
+
+#: latency_gui.cc:40
+msgid "msec"
+msgstr "毫秒"
+
+#: latency_gui.cc:41
+msgid "period"
+msgstr "周期"
+
+#: latency_gui.cc:55
+msgid "%1 sample"
+msgid_plural "%1 samples"
+msgstr[0] "%1 采样"
+
+#: latency_gui.cc:72 panner_ui.cc:409
+msgid "Reset"
+msgstr "预设"
+
+#: latency_gui.cc:149 rhythm_ferret.cc:273 sfdb_ui.cc:1912
+msgid "programming error: %1 (%2)"
+msgstr "程序错误: %1 (%2)"
+
+#: location_ui.cc:52 location_ui.cc:54
+msgid "Use PH"
+msgstr "使用 PH"
+
+#: location_ui.cc:59
+msgid "Glue"
+msgstr "粘连"
+
+#: location_ui.cc:87
+msgid "Performer:"
+msgstr "演奏者:"
+
+#: location_ui.cc:88
+msgid "Composer:"
+msgstr "作曲家:"
+
+#: location_ui.cc:90
+msgid "Pre-Emphasis"
+msgstr "预加重"
+
+#: location_ui.cc:317
+msgid "Remove this range"
+msgstr "移除这个范围"
+
+#: location_ui.cc:318
+msgid "Start time - middle click to locate here"
+msgstr "起点时间——鼠标中键点击放置在此处"
+
+#: location_ui.cc:319
+msgid "End time - middle click to locate here"
+msgstr "终点时间——鼠标中键点击放置在此处"
+
+#: location_ui.cc:322
+msgid "Set range start from playhead location"
+msgstr "从指针位置设置范围起点"
+
+#: location_ui.cc:323
+msgid "Set range end from playhead location"
+msgstr "从指针位置设置范围终点"
+
+#: location_ui.cc:327
+msgid "Remove this marker"
+msgstr "移除这个标记"
+
+#: location_ui.cc:328
+msgid "Position - middle click to locate here"
+msgstr "位置——鼠标中键点击放置在此处"
+
+#: location_ui.cc:330
+msgid "Set marker time from playhead location"
+msgstr "从指针位置设置标记时间"
+
+#: location_ui.cc:499
+msgid "You cannot put a CD marker at the start of the session"
+msgstr "您不能在会话起点处放置CD标记"
+
+#: location_ui.cc:725
+msgid "New Marker"
+msgstr "新建标记"
+
+#: location_ui.cc:726
+msgid "New Range"
+msgstr "新建范围"
+
+#: location_ui.cc:739
+msgid "<b>Loop/Punch Ranges</b>"
+msgstr "<b>循环/切换范围</b>"
+
+#: location_ui.cc:764
+msgid "<b>Markers (Including CD Index)</b>"
+msgstr "<b>标记(包括CD索引)</b>"
+
+#: location_ui.cc:799
+msgid "<b>Ranges (Including CD Track Ranges)</b>"
+msgstr "<b>范围(包括CD音轨范围)</b>"
+
+#: location_ui.cc:1042
+msgid "add range marker"
+msgstr "添加范围标记"
+
+#: main.cc:82
+msgid "%1 could not connect to the audio backend."
+msgstr "%1无法连接到音频后端。"
+
+#: main.cc:107 main.cc:123
+msgid "The audio backend (%1) has failed, or terminated"
+msgstr "音频后端(%1)失效或者中止。"
+
+#: main.cc:110
+msgid ""
+"%2 exited unexpectedly, and without notifying %1.\n"
+"\n"
+"This could be due to misconfiguration or to an error inside %2.\n"
+"\n"
+"Click OK to exit %1."
+msgstr ""
+"%2 意外退出,且没有通知 %1 。\n"
+"\n"
+"这可能是由于错误配置或者定向到错误 %2 内部错误。\n"
+"点击 OK 退出 %1。"
+
+#: main.cc:124
+msgid "%2 exited unexpectedly, and without notifying %1."
+msgstr "%2 exited unexpectedly, and without notifying %1."
+
+#: main.cc:219
+msgid ""
+"\n"
+"   %1 could not understand your command line      "
+msgstr ""
+"\n"
+"   %1 无法识别您的命令行      "
+
+#: main.cc:221
+msgid "An error was encountered while launching %1"
+msgstr "启动 %1 时遇到一个意外错误"
+
+#: main.cc:310
+msgid " (built using "
+msgstr "(构建使用 "
+
+#: main.cc:313
+msgid " and GCC version "
+msgstr "和 GCC 版本 "
+
+#: main.cc:323
+msgid "Copyright (C) 1999-2012 Paul Davis"
+msgstr " 版权 (C) 1999-2012 Paul Davis"
+
+#: main.cc:324
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, "
+"Robin Gareus"
+msgstr ""
+"部分版权 (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, Robin Gareus"
+
+#: main.cc:326
+msgid "%1 comes with ABSOLUTELY NO WARRANTY"
+msgstr "%1 绝对不附带任何担保"
+
+#: main.cc:327
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr " 甚至不包括可销售性质和适用于任何特定目的的保证。"
+
+#: main.cc:328
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr "这是自由软件,且欢迎您分发推广它,"
+
+#: main.cc:329
+msgid "under certain conditions; see the source for copying conditions."
+msgstr "在一定条件下;请参阅复制协议的源文件。"
+
+#: main.cc:334
+msgid "could not initialize %1."
+msgstr "无法初始化 %1 。"
+
+#: main.cc:344
+msgid "Cannot xinstall SIGPIPE error handler"
+msgstr "无法安装卸载 SIGPIPE 错误处理程序"
+
+#: main.cc:351
+msgid "could not create %1 GUI"
+msgstr "无法创建  %1 图形用户界面"
+
+#: main_clock.cc:52
+msgid "Display delta to edit cursor"
+msgstr "显示次级以编辑游标"
+
+#: marker.cc:273
+msgid "MarkerText"
+msgstr "标记文本"
+
+#: midi_channel_selector.cc:161 midi_channel_selector.cc:400
+#: midi_channel_selector.cc:436 rc_option_editor.cc:1573 rc_option_editor.cc:2203
+#: sfdb_ui.cc:665
+msgid "None"
+msgstr "æ— "
+
+#: midi_channel_selector.cc:165 midi_channel_selector.cc:405
+#: midi_channel_selector.cc:441
+msgid "Invert"
+msgstr "反转"
+
+#: midi_channel_selector.cc:169
+msgid "Force"
+msgstr "强制"
+
+#: midi_channel_selector.cc:328 midi_channel_selector.cc:370
+msgid "MIDI Channel Control"
+msgstr "MIDI 声道控制"
+
+#: midi_channel_selector.cc:330
+msgid "Playback all channels"
+msgstr "回放所有声道"
+
+#: midi_channel_selector.cc:331
+msgid "Play only selected channels"
+msgstr "仅播放已选中的声道"
+
+#: midi_channel_selector.cc:332
+msgid "Use a single fixed channel for all playback"
+msgstr "所有回放使用一个单独固定的声道"
+
+#: midi_channel_selector.cc:333
+msgid "Record all channels"
+msgstr "录制所有声道"
+
+#: midi_channel_selector.cc:334
+msgid "Record only selected channels"
+msgstr "仅录制已选中的声道"
+
+#: midi_channel_selector.cc:335
+msgid "Force all channels to 1 channel"
+msgstr "强制所有声道为 1 声道"
+
+#: midi_channel_selector.cc:376
+msgid "Inbound"
+msgstr "进场"
+
+#: midi_channel_selector.cc:396
+msgid "Click to enable recording all channels"
+msgstr "点击启用录制所有声道"
+
+#: midi_channel_selector.cc:401
+msgid "Click to disable recording all channels"
+msgstr "点击禁用录制所有声道"
+
+#: midi_channel_selector.cc:406
+msgid "Click to invert currently selected recording channels"
+msgstr "点击反转当前已选择的录制声道"
+
+#: midi_channel_selector.cc:413
+msgid "Playback"
+msgstr "回放"
+
+#: midi_channel_selector.cc:432
+msgid "Click to enable playback of all channels"
+msgstr "点击启用回放所有声道"
+
+#: midi_channel_selector.cc:437
+msgid "Click to disable playback of all channels"
+msgstr "点击禁用回放所有声道"
+
+#: midi_channel_selector.cc:442
+msgid "Click to invert current selected playback channels"
+msgstr "点击反转当前已选择的回放声道"
+
+#: midi_channel_selector.cc:620
+msgid "Click to toggle playback of channel %1"
+msgstr "点击切换回放声道 %1"
+
+#: midi_channel_selector.cc:628
+msgid "Click to force all MIDI channel messages to channel %1"
+msgstr "点击强制所有MIDI声道发送信息到声道 %1"
+
+#: midi_channel_selector.cc:718
+msgid "Click to toggle recording of channel %1"
+msgstr "点击切换录制声道 %1"
+
+#: midi_channel_selector.cc:726
+msgid "Click to force all recorded channels to %1"
+msgstr "点击强制所有已录制声道到 %1"
+
+#: midi_export_dialog.cc:35
+msgid "Export MIDI: %1"
+msgstr "导出MIDI: %1"
+
+#: midi_list_editor.cc:56
+msgid "Whole"
+msgstr "整体"
+
+#: midi_list_editor.cc:57
+msgid "Half"
+msgstr "一半"
+
+#: midi_list_editor.cc:58
+msgid "Triplet"
+msgstr "三分之一"
+
+#: midi_list_editor.cc:59
+msgid "Quarter"
+msgstr "四分之一"
+
+#: midi_list_editor.cc:60
+msgid "Eighth"
+msgstr "八分之一"
+
+#: midi_list_editor.cc:61
+msgid "Sixteenth"
+msgstr "十六分之一"
+
+#: midi_list_editor.cc:62
+msgid "Thirty-second"
+msgstr "三十二分之一"
+
+#: midi_list_editor.cc:63
+msgid "Sixty-fourth"
+msgstr "六十四分之一"
+
+#: midi_list_editor.cc:106
+msgid "Num"
+msgstr "数值"
+
+#: midi_list_editor.cc:108
+msgid "Vel"
+msgstr "力度"
+
+#: midi_list_editor.cc:216
+msgid "edit note start"
+msgstr "编辑音符起点"
+
+#: midi_list_editor.cc:225
+msgid "edit note channel"
+msgstr "编辑音符声道"
+
+#: midi_list_editor.cc:235
+msgid "edit note number"
+msgstr "编辑音符编号"
+
+#: midi_list_editor.cc:245
+msgid "edit note velocity"
+msgstr "编辑音符力度"
+
+#: midi_list_editor.cc:259
+msgid "edit note length"
+msgstr "编辑音符长度"
+
+#: midi_list_editor.cc:463
+msgid "insert new note"
+msgstr "插入新的音符"
+
+#: midi_list_editor.cc:527
+msgid "delete notes (from list)"
+msgstr "删除音符(从列表中)"
+
+#: midi_list_editor.cc:602
+msgid "change note channel"
+msgstr "切换音符声道"
+
+#: midi_list_editor.cc:610
+msgid "change note number"
+msgstr "切换音符编号"
+
+#: midi_list_editor.cc:620
+msgid "change note velocity"
+msgstr "切换音符力度"
+
+#: midi_list_editor.cc:690
+msgid "change note length"
+msgstr "切换音符长度"
+
+#: midi_port_dialog.cc:39
+msgid "Add MIDI Port"
+msgstr "添加MIDI端口"
+
+#: midi_port_dialog.cc:40
+msgid "Port name:"
+msgstr "端口名称:"
+
+#: midi_port_dialog.cc:45
+msgid "MidiPortDialog"
+msgstr "MIDI端口对话框"
+
+#: midi_region_view.cc:859
+msgid "channel edit"
+msgstr "声道编辑"
+
+#: midi_region_view.cc:895
+msgid "velocity edit"
+msgstr "力度编辑"
+
+#: midi_region_view.cc:954
+msgid "add note"
+msgstr "添加音符"
+
+#: midi_region_view.cc:1885
+msgid "step add"
+msgstr "步进添加"
+
+#: midi_region_view.cc:1979 midi_region_view.cc:2002
+msgid "alter patch change"
+msgstr "更改音色变换"
+
+#: midi_region_view.cc:2038
+msgid "add patch change"
+msgstr "添加音色变换"
+
+#: midi_region_view.cc:2060 midi_region_view.cc:2061
+msgid "move patch change"
+msgstr "移动音色变换"
+
+#: midi_region_view.cc:2073 midi_region_view.cc:2074
+msgid "delete patch change"
+msgstr "删除音色变换"
+
+#: midi_region_view.cc:2112
+msgid "delete selection"
+msgstr "删除已选取部分"
+
+#: midi_region_view.cc:2128
+msgid "delete note"
+msgstr "删除音符"
+
+#: midi_region_view.cc:2587
+msgid "move notes"
+msgstr "移动音符"
+
+#: midi_region_view.cc:3070
+msgid "change velocities"
+msgstr "改变力度"
+
+#: midi_region_view.cc:3136
+msgid "transpose"
+msgstr "变调"
+
+#: midi_region_view.cc:3164
+msgid "change note lengths"
+msgstr "改变音符长度"
+
+#: midi_region_view.cc:3240
+msgid "nudge"
+msgstr "微调"
+
+#: midi_region_view.cc:3255
+msgid "change channel"
+msgstr "改变声道"
+
+#: midi_region_view.cc:3295
+msgid "Bank "
+msgstr "库"
+
+#: midi_region_view.cc:3296
+msgid "Program "
+msgstr "程序"
+
+#: midi_region_view.cc:3297
+msgid "Channel "
+msgstr "声道"
+
+#: midi_region_view.cc:3484
+msgid "paste"
+msgstr "粘贴"
+
+#: midi_streamview.cc:185
+msgid "attempt to display MIDI region with no source"
+msgstr "尝试显示无来源的 MIDI 区域"
+
+#: midi_streamview.cc:195
+msgid "attempt to display MIDI region with no model"
+msgstr "尝试显示无模式的 MIDI 区域"
+
+#: midi_streamview.cc:506
+msgid "failed to create MIDI region"
+msgstr "创建 MIDI 区域失败"
+
+#: midi_time_axis.cc:309
+msgid "External MIDI Device"
+msgstr "外部 MIDI 设备"
+
+#: midi_time_axis.cc:310
+msgid "External Device Mode"
+msgstr "外部设备模式"
+
+#: midi_time_axis.cc:318
+msgid "Chns"
+msgstr "声道"
+
+#: midi_time_axis.cc:320
+msgid "Click to edit channel settings"
+msgstr "点击编辑声道设置"
+
+#: midi_time_axis.cc:519
+msgid "Show Full Range"
+msgstr "显示全部范围"
+
+#: midi_time_axis.cc:524
+msgid "Fit Contents"
+msgstr "匹配内容"
+
+#: midi_time_axis.cc:528
+msgid "Note Range"
+msgstr "音符范围"
+
+#: midi_time_axis.cc:529
+msgid "Note Mode"
+msgstr "音符模式"
+
+#: midi_time_axis.cc:530
+msgid "Channel Selector"
+msgstr "声道选择器"
+
+#: midi_time_axis.cc:535
+msgid "Color Mode"
+msgstr "颜色模式"
+
+#: midi_time_axis.cc:594
+msgid "Bender"
+msgstr "滑音器"
+
+#: midi_time_axis.cc:598
+msgid "Pressure"
+msgstr "压力"
+
+#: midi_time_axis.cc:610
+msgid "Controllers"
+msgstr "控制器 "
+
+#: midi_time_axis.cc:615
+msgid "No MIDI Channels selected"
+msgstr "未选择 MIDI 声道"
+
+#: midi_time_axis.cc:672 midi_time_axis.cc:801
+msgid "Hide all channels"
+msgstr "隐藏所有声道"
+
+#: midi_time_axis.cc:676 midi_time_axis.cc:805
+msgid "Show all channels"
+msgstr "显示所有声道"
+
+#: midi_time_axis.cc:687 midi_time_axis.cc:816
+msgid "Channel %1"
+msgstr "声道 %1"
+
+#: midi_time_axis.cc:942 midi_time_axis.cc:974
+msgid "Controllers %1-%2"
+msgstr "控制器 %1-%2"
+
+#: midi_time_axis.cc:965 midi_time_axis.cc:968
+msgid "Controller %1"
+msgstr "控制器 %1"
+
+#: midi_time_axis.cc:991
+msgid "Sustained"
+msgstr "持续"
+
+#: midi_time_axis.cc:998
+msgid "Percussive"
+msgstr "敲击"
+
+#: midi_time_axis.cc:1018
+msgid "Meter Colors"
+msgstr "节拍颜色"
+
+#: midi_time_axis.cc:1025
+msgid "Channel Colors"
+msgstr " 声道颜色"
+
+#: midi_time_axis.cc:1032
+msgid "Track Color"
+msgstr "音轨颜色"
+
+#: midi_time_axis.cc:1606 midi_time_axis.cc:1612 midi_time_axis.cc:1622
+#: midi_time_axis.cc:1628
+msgid "all"
+msgstr "所有"
+
+#: midi_time_axis.cc:1609 midi_time_axis.cc:1625
+msgid "some"
+msgstr "一些"
+
+#: midi_tracer.cc:48
+msgid "Line history: "
+msgstr "线条历史:"
+
+#: midi_tracer.cc:55
+msgid "Auto-Scroll"
+msgstr "自动滚动"
+
+#: midi_tracer.cc:56
+msgid "Decimal"
+msgstr "十进制"
+
+#: midi_tracer.cc:57 rc_option_editor.cc:740
+msgid "Enabled"
+msgstr "启用"
+
+#: midi_tracer.cc:58
+msgid "Delta times"
+msgstr "次级时间"
+
+#: midi_tracer.cc:71
+msgid "Port:"
+msgstr "端口:"
+
+#: midi_velocity_dialog.cc:31
+msgid "New velocity"
+msgstr "新建力度"
+
+#: missing_file_dialog.cc:35
+msgid "Missing File"
+msgstr "缺失文件"
+
+#: missing_file_dialog.cc:37
+msgid "Select a folder to search"
+msgstr "选择一个要搜索的文件夹"
+
+#: missing_file_dialog.cc:38
+msgid "Add chosen folder to search path, and try again"
+msgstr "请添加已选择的文件夹到搜索路径,然后再试一次"
+
+#: missing_file_dialog.cc:40
+msgid "Stop loading this session"
+msgstr "停止载入此会话"
+
+#: missing_file_dialog.cc:41
+msgid "Skip all missing files"
+msgstr "跳过所有缺失的文件"
+
+#: missing_file_dialog.cc:42
+msgid "Skip this file"
+msgstr "跳过这个文件"
+
+#: missing_file_dialog.cc:53
+msgid "audio"
+msgstr "音频"
+
+#: missing_file_dialog.cc:70
+msgid ""
+"%1 cannot find the %2 file\n"
+"\n"
+"<i>%3</i>\n"
+"\n"
+"in any of these folders:\n"
+"\n"
+"<tt>%4</tt>\n"
+"\n"
+msgstr ""
+"%1 找不到文件 %2\n"
+"\n"
+"<i>%3</i>\n"
+"\n"
+"在下列任何文件夹中:\n"
+"\n"
+"<tt>%4</tt>\n"
+"\n"
+
+#: missing_file_dialog.cc:104
+msgid "Click to choose an additional folder"
+msgstr "点击选择一个额外的文件夹"
+
+#: missing_plugin_dialog.cc:29
+msgid "Missing Plugins"
+msgstr "缺失插件"
+
+#: missing_plugin_dialog.cc:33 transcode_video_dialog.cc:60
+msgid "OK"
+msgstr ""
+
+#: mixer_actor.cc:55
+msgid "Toggle Solo on Mixer-Selected Tracks/Busses"
+msgstr "在混音器已选中的音轨/总线上切换独奏"
+
+#: mixer_actor.cc:56
+msgid "Toggle Mute on Mixer-Selected Tracks/Busses"
+msgstr "在混音器已选中的音轨/总线上切换静音"
+
+#: mixer_actor.cc:57
+msgid "Toggle Rec-enable on Mixer-Selected Tracks/Busses"
+msgstr "在混音器已选中的音轨/总线上切换可录制"
+
+#: mixer_actor.cc:58
+msgid "Decrease Gain on Mixer-Selected Tracks/Busses"
+msgstr "在混音器已选中的音轨/总线上减小增益"
+
+#: mixer_actor.cc:59
+msgid "Increase Gain on Mixer-Selected Tracks/Busses"
+msgstr "在混音器已选中的音轨/总线上加大增益"
+
+#: mixer_actor.cc:60
+msgid "Set Gain to 0dB on Mixer-Selected Tracks/Busses"
+msgstr "在混音器已选中的音轨/总线上设置增益为 0dB"
+
+#: mixer_actor.cc:63
+msgid "Copy Selected Processors"
+msgstr "复制已选中的处理器"
+
+#: mixer_actor.cc:64
+msgid "Cut Selected Processors"
+msgstr "剪切已选中的处理器"
+
+#: mixer_actor.cc:65
+msgid "Paste Selected Processors"
+msgstr "粘贴已选中的处理器"
+
+#: mixer_actor.cc:66
+msgid "Delete Selected Processors"
+msgstr "删除已选中的处理器"
+
+#: mixer_actor.cc:67
+msgid "Select All (visible) Processors"
+msgstr "选择所有(可见的)处理器"
+
+#: mixer_actor.cc:68
+msgid "Toggle Selected Processors"
+msgstr "切换已选中的处理器"
+
+#: mixer_actor.cc:69
+msgid "Toggle Selected Plugins"
+msgstr "切换已选中的插件"
+
+#: mixer_actor.cc:70
+msgid "Deselect all strips and processors"
+msgstr "不选中所有片段和处理器"
+
+#: mixer_actor.cc:72 mixer_actor.cc:73
+msgid "Scroll Mixer Window to the left"
+msgstr "滚动混音器窗口到左侧"
+
+#: mixer_actor.cc:75
+msgid "Toggle MIDI Input Active for Mixer-Selected Tracks/Busses"
+msgstr "为混音器已选中的音轨/总线激活切换 MIDI 输入"
+
+#: mixer_actor.cc:90
+msgid "Loaded mixer bindings from %1"
+msgstr "从 %1 载入混音器绑定"
+
+#: mixer_actor.cc:92
+msgid "Could not find mixer.bindings in search path %1"
+msgstr "在搜索路径 %1 找不到混音器绑定"
+
+#: mixer_strip.cc:96 mixer_strip.cc:125
+msgid "pre"
+msgstr "预先"
+
+#: mixer_strip.cc:98 mixer_strip.cc:127 mixer_strip.cc:372 mixer_strip.cc:1410
+#: rc_option_editor.cc:2331
+msgid "Comments"
+msgstr "注释"
+
+#: mixer_strip.cc:149
+msgid "Click to toggle the width of this mixer strip."
+msgstr "点击切换此混音器片段的宽度。"
+
+#: mixer_strip.cc:151
+msgid ""
+"\n"
+"%1-%2-click to toggle the width of all strips."
+msgstr ""
+"\n"
+"%1-%2-点击切换所有片段的宽度。"
+
+#: mixer_strip.cc:158
+msgid "Hide this mixer strip"
+msgstr "隐藏此混音器片段"
+
+#: mixer_strip.cc:169
+msgid "Click to select metering point"
+msgstr "点击选择节拍点"
+
+#: mixer_strip.cc:185
+msgid "Isolate Solo"
+msgstr "隔离独奏"
+
+#: mixer_strip.cc:193
+msgid "Lock Solo Status"
+msgstr "锁定独奏状态"
+
+#: mixer_strip.cc:196 mixer_strip.cc:2027
+msgid "Iso"
+msgstr "隔离"
+
+#: mixer_strip.cc:250
+msgid "Mix group"
+msgstr "混合分组"
+
+#: mixer_strip.cc:368 rc_option_editor.cc:2327
+msgid "Phase Invert"
+msgstr "相位反转"
+
+#: mixer_strip.cc:369 rc_option_editor.cc:2328
+msgid "Record & Monitor"
+msgstr "录制和监控"
+
+#: mixer_strip.cc:370 rc_option_editor.cc:2329
+msgid "Solo Iso / Lock"
+msgstr "独奏隔离/锁定"
+
+#: mixer_strip.cc:524
+msgid "Enable/Disable MIDI input"
+msgstr "启用/禁用 MIDI 输入"
+
+#: mixer_strip.cc:688
+msgid "Aux"
+msgstr "辅助"
+
+#: mixer_strip.cc:710
+msgid "Snd"
+msgstr "声音"
+
+#: mixer_strip.cc:776 mixer_strip.cc:879 processor_box.cc:2382
+msgid "Not connected to audio engine - no I/O changes are possible"
+msgstr "未连接到音频引擎——不可能改变输入/输出"
+
+#: mixer_strip.cc:833 mixer_strip.cc:935
+msgid "Add %1 port"
+msgstr "添加 %1 端口"
+
+#: mixer_strip.cc:840 mixer_strip.cc:942
+msgid "Routing Grid"
+msgstr "路由网格"
+
+#: mixer_strip.cc:1171
+msgid "<b>INPUT</b> to %1"
+msgstr "<b>输入</b> 到 %1"
+
+#: mixer_strip.cc:1174
+msgid "<b>OUTPUT</b> from %1"
+msgstr "<b>输出</b> 来自 %1"
+
+#: mixer_strip.cc:1287
+msgid "Disconnected"
+msgstr "失去连接"
+
+#: mixer_strip.cc:1413
+msgid "*Comments*"
+msgstr "*注释*"
+
+#: mixer_strip.cc:1420
+msgid "Cmt"
+msgstr "注释"
+
+#: mixer_strip.cc:1423
+msgid "*Cmt*"
+msgstr "*注释*"
+
+#: mixer_strip.cc:1429
+msgid "Click to Add/Edit Comments"
+msgstr "点击添加/编辑注释"
+
+#: mixer_strip.cc:1473
+msgid "Grp"
+msgstr "分组"
+
+#: mixer_strip.cc:1476
+msgid "~G"
+msgstr "~G"
+
+#: mixer_strip.cc:1505 route_time_axis.cc:561
+msgid "Color..."
+msgstr "颜色…"
+
+#: mixer_strip.cc:1507 route_time_axis.cc:563
+msgid "Comments..."
+msgstr "注释…"
+
+#: mixer_strip.cc:1509 route_time_axis.cc:565
+msgid "Inputs..."
+msgstr "输入…"
+
+#: mixer_strip.cc:1511 route_time_axis.cc:567
+msgid "Outputs..."
+msgstr "输出…"
+
+#: mixer_strip.cc:1516
+msgid "Save As Template..."
+msgstr "保存为模板..."
+
+#: mixer_strip.cc:1530
+msgid "Adjust Latency..."
+msgstr "调整延迟..."
+
+#: mixer_strip.cc:1533
+msgid "Protect Against Denormals"
+msgstr "防止异常违反"
+
+#: mixer_strip.cc:1539 route_time_axis.cc:580
+msgid "Remote Control ID..."
+msgstr "远程控制 ID…"
+
+#: mixer_strip.cc:1823
+msgid "Pre"
+msgstr "预先"
+
+#: mixer_strip.cc:1827
+msgid "Post"
+msgstr "后置"
+
+#: mixer_strip.cc:1847
+msgid "Pr"
+msgstr "预先"
+
+#: mixer_strip.cc:1851
+msgid "Po"
+msgstr "后置"
+
+#: mixer_strip.cc:1860
+msgid "C"
+msgstr ""
+
+#: mixer_strip.cc:2008 route_ui.cc:168
+msgid "Disk"
+msgstr "硬盘"
+
+# AFL - Aside Fade Listen. 衰减后监听
+#: mixer_strip.cc:2020 monitor_section.cc:70
+msgid "AFL"
+msgstr "后置淡化试听"
+
+# PFL Pre-Fader-Listen衰减前监听
+#: mixer_strip.cc:2023 monitor_section.cc:71
+msgid "PFL"
+msgstr "前置淡化试听"
+
+#: mixer_strip.cc:2034 meter_strip.cc:380
+msgid "D"
+msgstr ""
+
+#: mixer_strip.cc:2241
+msgid "Pre Fader"
+msgstr "前置淡化"
+
+#: mixer_strip.cc:2242
+msgid "Post Fader"
+msgstr "后置淡化"
+
+#: mixer_strip.cc:2286 meter_strip.cc:847
+msgid "Change all in Group to %1"
+msgstr "改变分组里所有的到 %1"
+
+#: mixer_strip.cc:2288 meter_strip.cc:849
+msgid "Change all to %1"
+msgstr "改变所有的到 %1"
+
+#: mixer_strip.cc:2290 meter_strip.cc:851
+msgid "Change same track-type to %1"
+msgstr "改变相同轨道类型的到 %1"
+
+#: mixer_ui.cc:130 route_time_axis.cc:818
+msgid "Group"
+msgstr "分组"
+
+#: mixer_ui.cc:1224
+msgid "track display list item for renamed strip not found!"
+msgstr "未找到音轨显示列表的重命名片段条目!"
+
+#: mixer_ui.cc:1316
+msgid "-all-"
+msgstr "—所有—"
+
+#: mixer_ui.cc:1853
+msgid "Strips"
+msgstr "片段"
+
+#: meter_strip.cc:157
+msgid "Reset Peak"
+msgstr "重置峰值"
+
+#: meter_strip.cc:883
+msgid "Variable height"
+msgstr "变量高度"
+
+#: meter_strip.cc:884
+msgid "Short"
+msgstr "短小的"
+
+#: meter_strip.cc:885
+msgid "Tall"
+msgstr "高大的"
+
+#: meter_strip.cc:886
+msgid "Grande"
+msgstr ""
+
+#: meter_strip.cc:887
+msgid "Venti"
+msgstr ""
+
+#: meter_patterns.cc:82
+msgid "Peak"
+msgstr "峰值"
+
+#: meter_patterns.cc:85
+msgid "RMS + Peak"
+msgstr "均方根 + 峰值"
+
+#: meter_patterns.cc:88
+msgid "IEC1/DIN"
+msgstr ""
+
+#: meter_patterns.cc:91
+msgid "IEC1/Nordic"
+msgstr ""
+
+#: meter_patterns.cc:94
+msgid "IEC2/BBC"
+msgstr ""
+
+#: meter_patterns.cc:97
+msgid "IEC2/EBU"
+msgstr ""
+
+#: meter_patterns.cc:100
+msgid "K20"
+msgstr ""
+
+#: meter_patterns.cc:103
+msgid "K14"
+msgstr ""
+
+#: meter_patterns.cc:106
+msgid "K12"
+msgstr ""
+
+#: meter_patterns.cc:109
+msgid "VU"
+msgstr ""
+
+#: monitor_section.cc:69
+msgid "SiP"
+msgstr ""
+
+#: monitor_section.cc:96 route_group_dialog.cc:49
+msgid "Soloing"
+msgstr "独奏中"
+
+#: monitor_section.cc:100
+msgid "Isolated"
+msgstr "已隔离"
+
+#: monitor_section.cc:104
+msgid "Auditioning"
+msgstr "监听中"
+
+#: monitor_section.cc:114
+msgid ""
+"When active, something is solo-isolated.\n"
+"Click to de-isolate everything"
+msgstr ""
+"启用时,某些被独奏隔离。\n"
+"点击解除所有的隔离"
+
+#: monitor_section.cc:117
+msgid ""
+"When active, auditioning is active.\n"
+"Click to stop the audition"
+msgstr ""
+"启用时,监听激活。\n"
+"点击停止监听."
+
+#: monitor_section.cc:134
+msgid "Solo controls affect solo-in-place"
+msgstr "独奏控制影响独奏入位"
+
+#: monitor_section.cc:140
+msgid "Solo controls toggle after-fader-listen"
+msgstr "独奏控制切换后置淡化试听"
+
+#: monitor_section.cc:146
+msgid "Solo controls toggle pre-fader-listen"
+msgstr "独奏控制切换前置淡化试听"
+
+#: monitor_section.cc:156
+msgid "Gain increase for soloed signals (0dB is normal)"
+msgstr "为独奏信号加大增益(正常值为 0dB)"
+
+#: monitor_section.cc:170
+msgid "Solo Boost"
+msgstr "独奏提升"
+
+#: monitor_section.cc:185
+msgid ""
+"Gain reduction non-soloed signals\n"
+"A value above -inf dB causes \"solo-in-front\""
+msgstr ""
+"增益减少非独奏信号\n"
+"一个数值高于 -inf dB 引起”独奏在前“"
+
+#: monitor_section.cc:196
+msgid "SiP Cut"
+msgstr "SiP 剪切"
+
+#: monitor_section.cc:211
+msgid "Gain reduction to use when dimming monitor outputs"
+msgstr "当减弱监控输出时,减小增益的使用"
+
+#: monitor_section.cc:225 monitor_section.cc:283
+msgid "Dim"
+msgstr "减弱"
+
+#: monitor_section.cc:235
+msgid "Excl. Solo"
+msgstr "把独奏排除在外"
+
+#: monitor_section.cc:237
+msgid "Exclusive solo means that only 1 solo is active at a time"
+msgstr "专属独奏意味着在同一时间仅有一个独奏是激活的"
+
+#: monitor_section.cc:244
+msgid "Solo » Mute"
+msgstr "独奏 » 静音"
+
+#: monitor_section.cc:246
+msgid ""
+"If enabled, solo will override mute\n"
+"(a soloed & muted track or bus will be audible)"
+msgstr ""
+"如果启用,独奏将覆盖静音\n"
+"(一个独奏且静音的音轨或总线将成为可听见)"
+
+#: monitor_section.cc:323
+msgid "Monitor"
+msgstr "监控"
+
+#: monitor_section.cc:744
+msgid "Switch monitor to mono"
+msgstr "转换监控到单声道"
+
+#: monitor_section.cc:747
+msgid "Cut monitor"
+msgstr "剪切监控"
+
+#: monitor_section.cc:750
+msgid "Dim monitor"
+msgstr "减弱监控"
+
+#: monitor_section.cc:753
+msgid "Toggle exclusive solo mode"
+msgstr "切换专属的独奏模式"
+
+#: monitor_section.cc:759
+msgid "Toggle mute overrides solo mode"
+msgstr "切换静音覆盖独奏模式"
+
+#: monitor_section.cc:771
+msgid "Cut monitor channel %1"
+msgstr "剪切监控声道 %1"
+
+#: monitor_section.cc:776
+msgid "Dim monitor channel %1"
+msgstr "减弱监控声道 %1"
+
+#: monitor_section.cc:781
+msgid "Solo monitor channel %1"
+msgstr "独奏监控声道 %1"
+
+#: monitor_section.cc:786
+msgid "Invert monitor channel %1"
+msgstr "反转监控声道 %1"
+
+#: monitor_section.cc:796
+msgid "In-place solo"
+msgstr "入位独奏"
+
+#: monitor_section.cc:798
+msgid "After Fade Listen (AFL) solo"
+msgstr "衰减后监听(AFL)独奏"
+
+#: monitor_section.cc:800
+msgid "Pre Fade Listen (PFL) solo"
+msgstr "衰减前监听(PFL)独奏"
+
+#: mono_panner.cc:109 stereo_panner.cc:119
+msgid "bypassed"
+msgstr "支路"
+
+#: mono_panner.cc:123
+#, c-format
+msgid "L:%3d R:%3d"
+msgstr "左:%3d 右:%3d"
+
+#: mono_panner_editor.cc:33
+msgid "Mono Panner"
+msgstr "单声道面板"
+
+#: mono_panner_editor.cc:44 mono_panner_editor.cc:49 stereo_panner_editor.cc:46
+#: stereo_panner_editor.cc:51
+msgid "%"
+msgstr ""
+
+#: nag.cc:41
+msgid "Support %1 Development"
+msgstr "支持 %1 的开发"
+
+#: nag.cc:42
+msgid "I'd like to make a one-time donation"
+msgstr "我愿意给予一次性捐助"
+
+#: nag.cc:43
+msgid "Tell me more about becoming a subscriber"
+msgstr "请告知我关于成为捐助者的信息"
+
+#: nag.cc:44
+msgid "I'm already a subscriber!"
+msgstr "我已经是捐助者了!"
+
+#: nag.cc:45
+msgid "Ask about this the next time I export"
+msgstr "在下次我导出时询问这事"
+
+#: nag.cc:46
+msgid "Never ever ask me about this again"
+msgstr "再也不要询问我这事"
+
+#: nag.cc:49
+msgid ""
+"Congratulations on your session export.\n"
+"\n"
+"It looks as if you may already be a subscriber. If so, thanks, and sorry\n"
+"to bother you again about this - I'm working on improving our subscriber system\n"
+"so that I don't have to keep annoying you with this message.\n"
+"\n"
+"If you're not a subscriber, perhaps you might consider supporting my work\n"
+"on Ardour with either a one-time donation or subscription. Nothing will \n"
+"happen if you choose not to do so. However Ardour's continuing development\n"
+"relies on a stable, sustainable income stream. Thanks for using Ardour!"
+msgstr ""
+"恭喜!你的会话已导出。\n"
+"\n"
+"看起来您可能已经是捐助者。 如果是的话,感谢您,\n"
+"抱歉为这事而再次打扰了您——我们正致力于改善我们的捐助系统\n"
+"希望我们就不会再因为这条信息而打扰您。\n"
+"\n"
+"如果您不是捐助者,也许您可以考虑一下支持我们在Ardour上的工作\n"
+"您可以一次性捐赠或者定期捐助均可。 如果您不想这样做的话也没事。\n"
+"不管怎样, Ardour的后续开发需要一个稳定、持续的资金来源。\n"
+"感谢使用Ardour!"
+
+#: nag.cc:58
+msgid ""
+"Congratulations on your session export.\n"
+"\n"
+"I hope you find Ardour a useful tool. I'd like to ask you to consider supporting\n"
+"its development with either a one-time donation or subscription. Nothing\n"
+"will happen if you choose not to do so. However Ardour's continuing development\n"
+"relies on a stable, sustainable income stream. Thanks for using Ardour!"
+msgstr ""
+"恭喜!你的会话已导出。\n"
+"\n"
+"我们希望您觉得Ardour是个有用的工具。我想建议您考虑一下支持它的开发。\n"
+"不论是一次性捐赠或者捐助均可。如果您不想这样做的话也没事。\n"
+"不管怎样, Ardour后续的开发需要一个稳定、持续的资金来源。\n"
+"感谢使用Ardour!"
+
+#: new_plugin_preset_dialog.cc:29
+msgid "New Preset"
+msgstr "新建预设"
+
+#: new_plugin_preset_dialog.cc:30
+msgid "Replace existing preset with this name"
+msgstr "用这个名称替代已存在的预设"
+
+#: new_plugin_preset_dialog.cc:34
+msgid "Name of new preset"
+msgstr "新建预设的名称"
+
+#: normalize_dialog.cc:34
+msgid "Normalize regions"
+msgstr "规范化区域"
+
+#: normalize_dialog.cc:34
+msgid "Normalize region"
+msgstr "规范化区域"
+
+#: normalize_dialog.cc:49 strip_silence_dialog.cc:66
+msgid "dbFS"
+msgstr ""
+
+#: normalize_dialog.cc:56
+msgid "Normalize each region using its own peak value"
+msgstr "用每个区域它自己的峰值数值规范化每个区域"
+
+#: normalize_dialog.cc:58
+msgid "Normalize each region using the peak value of all regions"
+msgstr "用所有区域的峰值数值规范化每个区域"
+
+#: normalize_dialog.cc:73
+msgid "Normalize"
+msgstr "规范化"
+
+#: note_select_dialog.cc:33
+msgid "Select Note"
+msgstr "选择音符"
+
+#: opts.cc:57
+msgid "Usage: "
+msgstr "用法:"
+
+#: opts.cc:58
+msgid "  [SESSION_NAME]              Name of session to load\n"
+msgstr "  [SESSION_NAME]              要载入的会话的名称\n"
+
+#: opts.cc:59
+msgid "  -v, --version               Show version information\n"
+msgstr "  -v, --version               显示版本信息\n"
+
+#: opts.cc:60
+msgid "  -h, --help                  Print this message\n"
+msgstr "  -h, --help                  打印本信息\n"
+
+#: opts.cc:61
+msgid "  -a, --no-announcements      Do not contact website for announcements\n"
+msgstr "  -a, --no-announcements      不联系网站公告\n"
+
+#: opts.cc:62
+msgid "  -b, --bindings              Print all possible keyboard binding names\n"
+msgstr "  -b, --bindings              打印所有可能的键盘绑定名称\n"
+
+#: opts.cc:63
+msgid ""
+"  -c, --name <name>           Use a specific backend client name, default is "
+"ardour\n"
+msgstr "  -c, --name <name>           使用一个特定的后端客户名称,默认是ardour\n"
+
+#: opts.cc:64
+msgid "  -d, --disable-plugins       Disable all plugins in an existing session\n"
+msgstr "  -d, --disable-plugins       在一个已存在的会话中禁用所有插件\n"
+
+#: opts.cc:65
+msgid ""
+"  -D, --debug <options>       Set debug flags. Use \"-D list\" to see available "
+"options\n"
+msgstr ""
+"  -D, --debug <options>       设置调试标志. 使用 \"-D list\" 显示可用的选项\n"
+
+#: opts.cc:66
+msgid "  -n, --no-splash             Do not show splash screen\n"
+msgstr "  -n, --no-splash             不显示闪屏\n"
+
+#: opts.cc:67
+msgid "  -m, --menus file            Use \"file\" to define menus\n"
+msgstr "  -m, --menus file            使用 \"file\" (文件)来定义菜单\n"
+
+#: opts.cc:68
+msgid "  -N, --new session-name      Create a new session from the command line\n"
+msgstr "  -N, --new session-name      从命令行创建一个新的会话\n"
+
+#: opts.cc:69
+msgid "  -O, --no-hw-optimizations   Disable h/w specific optimizations\n"
+msgstr "  -O, --no-hw-optimizations   禁用 h/w 特殊的优化\n"
+
+#: opts.cc:70
+msgid "  -P, --no-connect-ports      Do not connect any ports at startup\n"
+msgstr "  -P, --no-connect-ports     在启动时不连接任何端口 \n"
+
+#: opts.cc:71
+msgid "  -S, --sync                  Draw the gui synchronously \n"
+msgstr "  -S, --sync                  同步绘制用户图形界面 \n"
+
+#: opts.cc:73
+msgid "  -V, --novst                 Do not use VST support\n"
+msgstr "  -V, --novst                 不使用VST支持\n"
+
+#: opts.cc:75
+msgid ""
+"  -E, --save <file>           Load the specified session, save it to <file> and "
+"then quit\n"
+msgstr ""
+"  -E, --save <file>           载入指定的会话, 保存它在 <file 文件> 中并退出\n"
+
+#: opts.cc:76
+msgid "  -C, --curvetest filename    Curve algorithm debugger\n"
+msgstr "  -C, --curvetest filename    曲线算法调试器\n"
+
+#: opts.cc:77
+msgid ""
+"  -k, --keybindings filename  Name of key bindings to load (default is ~/.ardour3/"
+"ardour.bindings)\n"
+msgstr ""
+"  -k, --keybindings 文件名  要载入的按键绑定名称(默认是 ~/.ardour3/ardour."
+"bindings)\n"
+
+#: panner2d.cc:854
+msgid "Panner (2D)"
+msgstr "面板(2D)"
+
+#: panner2d.cc:856 panner_ui.cc:400 plugin_ui.cc:452
+msgid "Bypass"
+msgstr "支路"
+
+#: panner2d.cc:862
+msgid "Panner"
+msgstr "面板"
+
+#: panner_ui.cc:72
+msgid "Pan automation mode"
+msgstr "筛选自动模式"
+
+#: panner_ui.cc:73
+msgid "Pan automation type"
+msgstr "筛选自动类型"
+
+#: playlist_selector.cc:43
+msgid "Playlists"
+msgstr "播放列表"
+
+#: playlist_selector.cc:54
+msgid "Playlists grouped by track"
+msgstr "以音轨对播放列表分组"
+
+#: playlist_selector.cc:101
+msgid "Playlist for %1"
+msgstr "%1 的播放列表"
+
+#: playlist_selector.cc:114
+msgid "Other tracks"
+msgstr "其他音轨"
+
+#: playlist_selector.cc:139
+msgid "unassigned"
+msgstr "未指定"
+
+#: playlist_selector.cc:194
+msgid "Imported"
+msgstr "已导入"
+
+#: plugin_eq_gui.cc:85 plugin_eq_gui.cc:109
+msgid "dB scale"
+msgstr "dB 比例"
+
+#: plugin_eq_gui.cc:116
+msgid "Show phase"
+msgstr "显示相位"
+
+#: plugin_selector.cc:53 plugin_selector.cc:229
+msgid "Name contains"
+msgstr "名称包含"
+
+#: plugin_selector.cc:54 plugin_selector.cc:233
+msgid "Type contains"
+msgstr "类型包含"
+
+#: plugin_selector.cc:55 plugin_selector.cc:231
+msgid "Category contains"
+msgstr "类型包含"
+
+#: plugin_selector.cc:56 plugin_selector.cc:253
+msgid "Author contains"
+msgstr "作者包含"
+
+#: plugin_selector.cc:57 plugin_selector.cc:255
+msgid "Library contains"
+msgstr "库包含"
+
+#: plugin_selector.cc:58 plugin_selector.cc:219 plugin_selector.cc:537
+msgid "Favorites only"
+msgstr "仅收藏"
+
+#: plugin_selector.cc:59 plugin_selector.cc:223 plugin_selector.cc:537
+msgid "Hidden only"
+msgstr "仅隐藏"
+
+#: plugin_selector.cc:64
+msgid "Plugin Manager"
+msgstr "插件管理"
+
+#: plugin_selector.cc:85
+msgid "Fav"
+msgstr "收藏"
+
+#: plugin_selector.cc:87
+msgid "Available Plugins"
+msgstr "可用插件"
+
+#: plugin_selector.cc:88
+msgid "Type"
+msgstr "类型"
+
+#: plugin_selector.cc:89
+msgid "Category"
+msgstr "类别"
+
+#: plugin_selector.cc:90
+msgid "Creator"
+msgstr "创建者"
+
+#: plugin_selector.cc:91
+msgid "# Audio In"
+msgstr "# 音频输入"
+
+#: plugin_selector.cc:92
+msgid "# Audio Out"
+msgstr "# 音频输出"
+
+#: plugin_selector.cc:93
+msgid "# MIDI In"
+msgstr "# MIDI输入"
+
+#: plugin_selector.cc:94
+msgid "# MIDI Out"
+msgstr "# MIDI输出"
+
+#: plugin_selector.cc:116
+msgid "Plugins to be connected"
+msgstr "被连接的插件"
+
+#: plugin_selector.cc:129
+msgid "Add a plugin to the effect list"
+msgstr "添加一个插件到效果列表"
+
+#: plugin_selector.cc:133
+msgid "Remove a plugin from the effect list"
+msgstr "从效果列表中移除一个插件"
+
+#: plugin_selector.cc:135
+msgid "Update available plugins"
+msgstr "更新可用插件"
+
+#: plugin_selector.cc:172
+msgid "Insert Plugin(s)"
+msgstr "插入插件"
+
+#: plugin_selector.cc:337 plugin_selector.cc:338 plugin_selector.cc:339
+#: plugin_selector.cc:340
+msgid "variable"
+msgstr "变量"
+
+#: plugin_selector.cc:496
+msgid ""
+"The plugin \"%1\" could not be loaded\n"
+"\n"
+"See the Log window for more details (maybe)"
+msgstr ""
+"无法载入插件 \"%1\"\n"
+"\n"
+"更多的信息(也许可以)参阅日志窗口"
+
+#: plugin_selector.cc:644
+msgid "Favorites"
+msgstr "收藏"
+
+#: plugin_selector.cc:646
+msgid "Plugin Manager..."
+msgstr "插件管理器…"
+
+#: plugin_selector.cc:650
+msgid "By Creator"
+msgstr "根据创建者"
+
+#: plugin_selector.cc:653
+msgid "By Category"
+msgstr "根据类别"
+
+#: plugin_ui.cc:113
+msgid "Eh? LADSPA plugins don't have editors!"
+msgstr "噢?LADSPA插件没有编辑器!"
+
+#: plugin_ui.cc:122 plugin_ui.cc:227
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this version of "
+"%1)"
+msgstr "未知的编辑器应用插件类型(注意:在这个 %1 版本无 VST 支持)"
+
+#: plugin_ui.cc:125
+msgid "unknown type of editor-supplying plugin"
+msgstr "未知的编辑器应用插件类型"
+
+#: plugin_ui.cc:257
+msgid ""
+"unknown type of editor-supplying plugin (note: no linuxVST support in this version "
+"of %1)"
+msgstr "未知的编辑器应用插件类型(注意:在这个 %1 版本无 linuxVST 支持)"
+
+#: plugin_ui.cc:329
+msgid "create_lv2_editor called on non-LV2 plugin"
+msgstr "创建_lv2_编辑器调用 non-LV2 插件"
+
+#: plugin_ui.cc:418
+msgid "Add"
+msgstr "添加"
+
+#: plugin_ui.cc:422
+msgid "Description"
+msgstr "说明"
+
+#: plugin_ui.cc:423
+msgid "Plugin analysis"
+msgstr "插件分析"
+
+#: plugin_ui.cc:430
+msgid ""
+"Presets (if any) for this plugin\n"
+"(Both factory and user-created)"
+msgstr ""
+"预设这个插件(如果有的话)\n"
+"(包括出厂设置和用户创建的设置)"
+
+#: plugin_ui.cc:431
+msgid "Save a new preset"
+msgstr "保存一个新的预设"
+
+#: plugin_ui.cc:432
+msgid "Save the current preset"
+msgstr "保存当前预设"
+
+#: plugin_ui.cc:433
+msgid "Delete the current preset"
+msgstr "删除当前预设"
+
+#: plugin_ui.cc:434
+msgid "Disable signal processing by the plugin"
+msgstr "按插件禁用信号处理"
+
+#: plugin_ui.cc:467 plugin_ui.cc:663
+msgid ""
+"Click to allow the plugin to receive keyboard events that %1 would normally use as "
+"a shortcut"
+msgstr "单击允许此插件接受键盘事件,以便 %1 可以正常地作为一个快捷键使用"
+
+#: plugin_ui.cc:468
+msgid "Click to enable/disable this plugin"
+msgstr "单击启用/禁用此插件"
+
+#: plugin_ui.cc:507
+msgid "latency (%1 sample)"
+msgid_plural "latency (%1 samples)"
+msgstr[0] "延迟(%1 采样)"
+
+#: plugin_ui.cc:509
+msgid "latency (%1 ms)"
+msgstr "延迟(%1 毫秒)"
+
+#: plugin_ui.cc:520
+msgid "Edit Latency"
+msgstr "编辑延迟"
+
+#: plugin_ui.cc:566
+msgid ""
+"Plugin presets are not supported in this build of %1. Consider paying for a full "
+"version"
+msgstr "插件预设在本个 %1 构建中不支持。请考虑为完整版本付"
+
+#: plugin_ui.cc:574
+msgid ""
+"Plugin presets are not supported in this build, see the Log window for more "
+"information."
+msgstr "插件预设在本构建中不支持,更多信息请参阅日志窗口。"
+
+#: plugin_ui.cc:670
+msgid "Click to allow normal use of %1 keyboard shortcuts"
+msgstr "单击允许正常使用 %1 键盘快捷键"
+
+#: port_group.cc:337
+msgid "%1 Busses"
+msgstr "%1 总线"
+
+#: port_group.cc:338
+msgid "%1 Tracks"
+msgstr "%1 音轨"
+
+#: port_group.cc:339
+msgid "Hardware"
+msgstr "硬件"
+
+#: port_group.cc:340
+msgid "%1 Misc"
+msgstr "%1 杂项"
+
+#: port_group.cc:341
+msgid "Other"
+msgstr "其它"
+
+#: port_group.cc:432 port_group.cc:433
+msgid "LTC Out"
+msgstr "LTC 输出"
+
+#: port_group.cc:436 port_group.cc:437
+msgid "LTC In"
+msgstr "LTC 输入"
+
+#: port_group.cc:463
+msgid "MTC in"
+msgstr "MTC 输入"
+
+#: port_group.cc:466
+msgid "MIDI control in"
+msgstr "MIDI 控制输入"
+
+#: port_group.cc:469
+msgid "MIDI clock in"
+msgstr "MIDI 计时器输入"
+
+#: port_group.cc:472
+msgid "MMC in"
+msgstr "MMC 输入"
+
+#: port_group.cc:476
+msgid "MTC out"
+msgstr "MTC 输出"
+
+#: port_group.cc:479
+msgid "MIDI control out"
+msgstr "MIDI 控制输出"
+
+#: port_group.cc:482
+msgid "MIDI clock out"
+msgstr "MIDI 计时器输出"
+
+#: port_group.cc:485
+msgid "MMC out"
+msgstr "MMC 输出"
+
+#: port_group.cc:532
+msgid ":monitor"
+msgstr ":监控"
+
+#: port_group.cc:544
+msgid "system:"
+msgstr "系统:"
+
+#: port_group.cc:545
+msgid "alsa_pcm"
+msgstr ""
+
+#: port_insert_ui.cc:39
+msgid "Measure Latency"
+msgstr "测量延迟"
+
+#: port_insert_ui.cc:50
+msgid "Send/Output"
+msgstr "发送/输出"
+
+#: port_insert_ui.cc:51
+msgid "Return/Input"
+msgstr "返回/输入"
+
+#: port_insert_ui.cc:85
+msgid "No signal detected"
+msgstr "未检测到信号"
+
+#: port_insert_ui.cc:165
+msgid "Port Insert "
+msgstr "端口插入"
+
+#: port_matrix.cc:331 port_matrix.cc:357
+msgid "<b>Sources</b>"
+msgstr "<b>源</b>"
+
+#: port_matrix.cc:332 port_matrix.cc:358
+msgid "<b>Destinations</b>"
+msgstr "<b>目的地</b>"
+
+#: port_matrix.cc:440 port_matrix.cc:448
+#, c-format
+msgid "Add %s %s"
+msgstr "添加 %s %s"
+
+#: port_matrix.cc:456
+#, c-format
+msgid "Rename '%s'..."
+msgstr "重命名 '%s'..."
+
+#: port_matrix.cc:472
+msgid "Remove all"
+msgstr "移除所有"
+
+#: port_matrix.cc:492 port_matrix.cc:504
+#, c-format
+msgid "%s all"
+msgstr "%s 所有"
+
+#: port_matrix.cc:527
+msgid "Rescan"
+msgstr "重新扫描"
+
+#: port_matrix.cc:529
+msgid "Show individual ports"
+msgstr "显示各个端口"
+
+#: port_matrix.cc:535
+msgid "Flip"
+msgstr "轻弹"
+
+#: port_matrix.cc:722
+msgid ""
+"It is not possible to add a port here, as the first processor in the track or buss "
+"cannot support the new configuration."
+msgstr "不可能在此添加一个端口,作为在音轨或总线里的第一个处理器无法支持新的配置。"
+
+#: port_matrix.cc:725
+msgid "Cannot add port"
+msgstr "无法添加端口"
+
+#: port_matrix.cc:747
+msgid "Port removal not allowed"
+msgstr "不允许移除端口"
+
+#: port_matrix.cc:748
+msgid ""
+"This port cannot be removed.\n"
+"Either the first plugin in the track or buss cannot accept\n"
+"the new number of inputs or the last plugin has more outputs."
+msgstr ""
+"该端口不能被移除。\n"
+"不论是新的输入号码或者最后一个插件有更多的输出,\n"
+"在音轨或总线里的第一个插件都无法接受。"
+
+#: port_matrix.cc:965
+#, c-format
+msgid "Remove '%s'"
+msgstr "移除 '%s'"
+
+#: port_matrix.cc:980
+#, c-format
+msgid "%s all from '%s'"
+msgstr "%s 所有来自于 '%s'"
+
+#: port_matrix.cc:1046 transform_dialog.cc:62
+msgid "channel"
+msgstr "声道"
+
+#: port_matrix_body.cc:82
+msgid "There are no ports to connect."
+msgstr "没有端口可连接。"
+
+#: port_matrix_body.cc:84
+msgid "There are no %1 ports to connect."
+msgstr "没有 %1 端口可连接."
+
+#: processor_box.cc:150
+msgid "Send"
+msgstr "发送"
+
+#: processor_box.cc:152
+msgid "Return"
+msgstr "返回"
+
+#: processor_box.cc:310
+msgid ""
+"\n"
+"This mono plugin has been replicated %1 times."
+msgstr ""
+"\n"
+"这个单声道插件已经被复制了 %1 次。"
+
+#: processor_box.cc:314
+msgid ""
+"<b>%1</b>\n"
+"Double-click to show GUI.\n"
+"Alt+double-click to show generic GUI.%2"
+msgstr ""
+"<b>%1</b>\n"
+"双击显示图形用户界面。\n"
+"Alt+双击显示通用图形用户界面。%2"
+
+#: processor_box.cc:317
+msgid ""
+"<b>%1</b>\n"
+"Double-click to show generic GUI.%2"
+msgstr ""
+"<b>%1</b>\n"
+"双击显示通用图形用户界面。%2"
+
+#: processor_box.cc:361
+#, c-format
+msgid "(%1x1) "
+msgstr ""
+
+#: processor_box.cc:437
+msgid "Show All Controls"
+msgstr "显示所有控制"
+
+#: processor_box.cc:441
+msgid "Hide All Controls"
+msgstr "隐藏所有控制"
+
+#: processor_box.cc:475
+msgid "Link panner controls"
+msgstr "链接面板控制"
+
+#: processor_box.cc:575
+msgid "on"
+msgstr "开启"
+
+#: processor_box.cc:575 rc_option_editor.cc:2360 rc_option_editor.cc:2374
+msgid "off"
+msgstr "关闭"
+
+#: processor_box.cc:957
+msgid ""
+"Right-click to add/remove/edit\n"
+"plugins,inserts,sends and more"
+msgstr ""
+"右键点击添加/移除/编辑\n"
+"插件、插入、发送以及更多"
+
+#: processor_box.cc:1429 processor_box.cc:1804
+msgid "Plugin Incompatibility"
+msgstr "插件不兼容"
+
+#: processor_box.cc:1432
+msgid "You attempted to add the plugin \"%1\" in slot %2.\n"
+msgstr "您试图在空位 %2 中添加插件 \"%1\" 。\n"
+
+#: processor_box.cc:1438
+msgid ""
+"\n"
+"This plugin has:\n"
+msgstr ""
+"\n"
+"此插件有:\n"
+
+#: processor_box.cc:1441
+msgid "\t%1 MIDI input\n"
+msgid_plural "\t%1 MIDI inputs\n"
+msgstr[0] "\t%1 MIDI 输入\n"
+
+#: processor_box.cc:1445
+msgid "\t%1 audio input\n"
+msgid_plural "\t%1 audio inputs\n"
+msgstr[0] "\t%1 音频输出\n"
+
+#: processor_box.cc:1448
+msgid ""
+"\n"
+"but at the insertion point, there are:\n"
+msgstr ""
+"\n"
+"但在插入点那里有:\n"
+
+#: processor_box.cc:1451
+msgid "\t%1 MIDI channel\n"
+msgid_plural "\t%1 MIDI channels\n"
+msgstr[0] "\t%1 MIDI 声道\n"
+
+#: processor_box.cc:1455
+msgid "\t%1 audio channel\n"
+msgid_plural "\t%1 audio channels\n"
+msgstr[0] "\t%1 音频声道\n"
+
+#: processor_box.cc:1458
+msgid ""
+"\n"
+"%1 is unable to insert this plugin here.\n"
+msgstr ""
+"\n"
+"%1 无法在此处再次插入插件.\n"
+
+#: processor_box.cc:1495
+msgid "Cannot set up new send: %1"
+msgstr "无法建立新的发送: %1"
+
+#: processor_box.cc:1807
+msgid ""
+"You cannot reorder these plugins/sends/inserts\n"
+"in that way because the inputs and\n"
+"outputs will not work correctly."
+msgstr ""
+"您不能以这种方式\n"
+"要求这些插件/发送/插入\n"
+"因为输入和输出将无法正确工作。"
+
+#: processor_box.cc:1991
+msgid "Rename Processor"
+msgstr "重命名处理器"
+
+#: processor_box.cc:2022
+msgid "At least 100 IO objects exist with a name like %1 - name not changed"
+msgstr "至少有100个输入输出对象物体存在着像 %1这样的名称——名称没有改变"
+
+#: processor_box.cc:2159
+msgid "plugin insert constructor failed"
+msgstr "插件插入构造函数失败"
+
+#: processor_box.cc:2170
+msgid ""
+"Copying the set of processors on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+"复制剪贴板上的处理器集成失败,\n"
+"可能是因为插件的输入/输出配置\n"
+"无法匹配这条音轨的配置。"
+
+#: processor_box.cc:2216
+msgid ""
+"Do you really want to remove all processors from %1?\n"
+"(this cannot be undone)"
+msgstr ""
+"您是否真的要从 %1 移除所有的处理器?\n"
+"(此操作不可撤销)"
+
+#: processor_box.cc:2220 processor_box.cc:2245
+msgid "Yes, remove them all"
+msgstr "是的,全部移除它们"
+
+#: processor_box.cc:2222 processor_box.cc:2247
+msgid "Remove processors"
+msgstr "移除处理器"
+
+#: processor_box.cc:2237
+msgid ""
+"Do you really want to remove all pre-fader processors from %1?\n"
+"(this cannot be undone)"
+msgstr ""
+"您是否真的要从 %1 移除所有的前置淡化处理器?\n"
+"(此操作不可撤销)"
+
+#: processor_box.cc:2240
+msgid ""
+"Do you really want to remove all post-fader processors from %1?\n"
+"(this cannot be undone)"
+msgstr ""
+"您是否真的要从 %1 移除所有的后置淡化处理器?\n"
+"(此操作不可撤销)"
+
+#: processor_box.cc:2428
+msgid "New Plugin"
+msgstr "新建插件"
+
+#: processor_box.cc:2431
+msgid "New Insert"
+msgstr "新建插入"
+
+#: processor_box.cc:2434
+msgid "New External Send ..."
+msgstr "新建外部发送…"
+
+#: processor_box.cc:2438
+msgid "New Aux Send ..."
+msgstr "新建辅助发送"
+
+#: processor_box.cc:2441
+msgid "Send Options"
+msgstr "发送选项"
+
+#: processor_box.cc:2443
+msgid "Clear (all)"
+msgstr "清除(所有)"
+
+#: processor_box.cc:2445
+msgid "Clear (pre-fader)"
+msgstr "清除(前置淡化)"
+
+#: processor_box.cc:2447
+msgid "Clear (post-fader)"
+msgstr "清除(后置淡化)"
+
+#: processor_box.cc:2473
+msgid "Activate All"
+msgstr "激活所有"
+
+#: processor_box.cc:2475
+msgid "Deactivate All"
+msgstr "不激活所有"
+
+#: processor_box.cc:2477
+msgid "A/B Plugins"
+msgstr "A/B 插件"
+
+#: processor_box.cc:2486
+msgid "Edit with generic controls..."
+msgstr "以通用控制编辑…"
+
+#: processor_box.cc:2789
+msgid "%1: %2 (by %3)"
+msgstr "%1: %2(通过 %3)"
+
+#: processor_box.cc:2791
+msgid "%1 (by %2)"
+msgstr "%1(通过 %2)"
+
+#: patch_change_dialog.cc:50
+msgid "Patch Change"
+msgstr "音色变换"
+
+#: patch_change_dialog.cc:76
+msgid "Patch Bank"
+msgstr "音色库"
+
+#: patch_change_dialog.cc:83
+msgid "Patch"
+msgstr "音色"
+
+#: patch_change_dialog.cc:98 step_entry.cc:430
+msgid "Program"
+msgstr "程序"
+
+#: patch_change_dialog.cc:106 step_entry.cc:422
+msgid "Bank"
+msgstr "库"
+
+#: quantize_dialog.cc:36
+msgid "main grid"
+msgstr "主要网格"
+
+#: quantize_dialog.cc:52 quantize_dialog.cc:109
+msgid "Quantize"
+msgstr "数字转换"
+
+#: quantize_dialog.cc:56
+msgid "Strength"
+msgstr "强度"
+
+#: quantize_dialog.cc:59
+msgid "Swing"
+msgstr "摆动"
+
+#: quantize_dialog.cc:62
+msgid "Threshold (ticks)"
+msgstr "临界值(识别声)"
+
+#: quantize_dialog.cc:63
+msgid "Snap note start"
+msgstr "对齐音符起点"
+
+#: quantize_dialog.cc:64
+msgid "Snap note end"
+msgstr "对齐音符终点"
+
+#: rc_option_editor.cc:77
+msgid "Click audio file:"
+msgstr "单击音频文件:"
+
+#: rc_option_editor.cc:80 rc_option_editor.cc:87
+msgid "Browse..."
+msgstr "浏览…"
+
+#: rc_option_editor.cc:84
+msgid "Click emphasis audio file:"
+msgstr "点击加重音频文件:"
+
+#: rc_option_editor.cc:116
+msgid "Choose Click"
+msgstr "选择点击"
+
+#: rc_option_editor.cc:139
+msgid "Choose Click Emphasis"
+msgstr "选择点击加重"
+
+#: rc_option_editor.cc:170
+msgid "Limit undo history to"
+msgstr "限制撤销历史到"
+
+#: rc_option_editor.cc:171
+msgid "Save undo history of"
+msgstr "保存撤销历史"
+
+#: rc_option_editor.cc:180 rc_option_editor.cc:187
+msgid "commands"
+msgstr "命令"
+
+#: rc_option_editor.cc:325
+msgid "Edit using:"
+msgstr "编辑使用:"
+
+#: rc_option_editor.cc:331 rc_option_editor.cc:357 rc_option_editor.cc:384
+msgid "+ button"
+msgstr "+按钮"
+
+#: rc_option_editor.cc:351
+msgid "Delete using:"
+msgstr "删除使用:"
+
+#: rc_option_editor.cc:378
+msgid "Insert note using:"
+msgstr "插入音符使用:"
+
+#: rc_option_editor.cc:405
+msgid "Ignore snap using:"
+msgstr "忽略音符使用:"
+
+#: rc_option_editor.cc:421
+msgid "Keyboard layout:"
+msgstr "键盘布局:"
+
+#: rc_option_editor.cc:544
+msgid "Font scaling:"
+msgstr "字体缩放:"
+
+#: rc_option_editor.cc:547
+msgid "Default"
+msgstr "默认"
+
+#: rc_option_editor.cc:573
+msgid "Major font-scale changes require an application restart to re-layout."
+msgstr "重要的字体缩放变化要求应用程序重新启动以便于重新布局。"
+
+#: rc_option_editor.cc:614
+msgid "Waveform Clip Level (dBFS):"
+msgstr "波形截波电平(dBFS):"
+
+#: rc_option_editor.cc:666
+msgid "Playback (seconds of buffering):"
+msgstr "回放(缓冲的秒数):"
+
+#: rc_option_editor.cc:679
+msgid "Recording (seconds of buffering):"
+msgstr "录制(缓冲的秒数):"
+
+#: rc_option_editor.cc:737
+msgid "Control Surface Protocol"
+msgstr "控制面协议"
+
+#: rc_option_editor.cc:746
+msgid "Double-click on a name to edit settings for an enabled protocol"
+msgstr "双击名称以便编辑已启用协议的设置"
+
+#: rc_option_editor.cc:903
+msgid "Show Video Export Info before export"
+msgstr "导出前显示视频导出信息"
+
+#: rc_option_editor.cc:904
+msgid "Show Video Server Startup Dialog"
+msgstr "显示视频服务启动对话框"
+
+#: rc_option_editor.cc:905
+msgid "Advanced Setup (remote video server)"
+msgstr "高级设置(远程视频服务)"
+
+#: rc_option_editor.cc:913
+msgid ""
+"<b>When enabled</b> you can speficify a custom video-server URL and docroot. - Do "
+"not enable this option unless you know what you are doing."
+msgstr ""
+"<b>启用时</b> 您可以指定一个定制的视频服务器网址和文档根。——不要启用该选项,除非您"
+"知道您正在做什么。"
+
+#: rc_option_editor.cc:915
+msgid "Video Server URL:"
+msgstr "视频服务器网址:"
+
+#: rc_option_editor.cc:920
+msgid ""
+"Base URL of the video-server including http prefix. This is usually 'http://"
+"hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the "
+"video-server is running locally"
+msgstr ""
+"基于网址的视频服务包括 http 前缀。当视频服务器是运行在本地时,这网址通常是 “http://"
+"hostname.example.org:1554/” 以及默认是 “http://localhost:1554/” 。"
+
+#: rc_option_editor.cc:922
+msgid "Video Folder:"
+msgstr "视频文件夹:"
+
+#: rc_option_editor.cc:927
+msgid ""
+"Local path to the video-server document-root. Only files below this directory will "
+"be accessible by the video-server. If the server run on a remote host, it should "
+"point to a network mounted folder of the server's docroot or be left empty if it "
+"is unvailable. It is used for the local video-monitor and file-browsing when "
+"opening/adding a video file."
+msgstr ""
+"视频服务器文档根的本地路径。视频服务器仅访问这个目录下的文件。如果服务器运行在远程"
+"主机上,它将指向服务器文档根的一个网络挂载文件夹,或者如果它不可用就留着空白。这是"
+"用于在打开/添加一个视频文件时的本地视频监控以及文件浏览。"
+
+#: rc_option_editor.cc:934
+msgid ""
+"<b>When enabled</b> an information window with details is displayed before the "
+"video-export dialog."
+msgstr "<b>启用时</b> 在视频输出对话框前显示一个细节信息窗口。"
+
+#: rc_option_editor.cc:939
+msgid ""
+"<b>When enabled</b> the video server is never launched automatically without "
+"confirmation"
+msgstr "<b>启用时</b> 视频服务器在没有得到确认前不会自动启动。"
+
+#: rc_option_editor.cc:1022
+msgid "Always Display Plugin Scan Progress"
+msgstr "总是显示插件扫描程序"
+
+#: rc_option_editor.cc:1023
+msgid "Scan for [new] VST Plugins on Application Start"
+msgstr "在应用起点扫描 [新] VST 插件"
+
+#: rc_option_editor.cc:1024
+msgid "Scan for AudioUnit Plugins on Application Start"
+msgstr "在应用起点扫描音频单位插件"
+
+#: rc_option_editor.cc:1035
+msgid "General"
+msgstr "通用"
+
+#: rc_option_editor.cc:1041
+msgid "Scan for Plugins"
+msgstr "扫描插件"
+
+#: rc_option_editor.cc:1048
+msgid ""
+"<b>When enabled</b> a popup window showing plugin scan progress is displayed for "
+"indexing (cache load) and discovery (detect new plugins)"
+msgstr ""
+"<b>启用时</b> 一个弹出窗口显示插件扫描程序,以展示索引(缓存载入)和发现(探测新插"
+"件)。"
+
+#: rc_option_editor.cc:1055
+msgid ""
+"Specify the default timeout for plugin instantiation in 1/10 seconds. Plugins that "
+"require more time to load will be blacklisted. A value of 0 disables the timeout."
+msgstr ""
+"插件实例化指定的默认超时在 1/10 以内。需要更多时间载入的插件将被列入黑名单。数值为 "
+"0 则禁用超时。"
+
+#: rc_option_editor.cc:1057
+msgid "Scan Time Out [deciseconds]"
+msgstr "扫描超时 [十分之一秒]"
+
+#: rc_option_editor.cc:1065
+msgid "VST"
+msgstr ""
+
+#: rc_option_editor.cc:1071
+msgid "Clear VST Cache"
+msgstr "清除 VST 缓存"
+
+#: rc_option_editor.cc:1075
+msgid "Clear VST Blacklist"
+msgstr "清除 VST 黑名单"
+
+#: rc_option_editor.cc:1083
+msgid ""
+"<b>When enabled</b> new VST plugins are searched, tested and added to the cache "
+"index on application start. When disabled new plugins will only be available after "
+"triggering a 'Scan' manually"
+msgstr ""
+"<b>启用时</b> 新的 VST 插件被搜索、测试以及添加到应用起点的缓存索引中。当禁用新插件"
+"时,仅在手动触发“扫描”时可用。"
+
+#: rc_option_editor.cc:1086
+msgid "Linux VST Path:"
+msgstr "Linux VST 路径:"
+
+#: rc_option_editor.cc:1093
+msgid "Windows VST Path:"
+msgstr "Windows VST 路径:"
+
+#: rc_option_editor.cc:1102
+msgid "Audio Unit"
+msgstr "音频单位"
+
+#: rc_option_editor.cc:1111
+msgid ""
+"<b>When enabled</b> Audio Unit Plugins are discovered on application start. When "
+"disabled AU plugins will only be available after triggering a 'Scan' manually. The "
+"first successful scan will enable AU auto-scan, Any crash during plugin discovery "
+"will disable it."
+msgstr ""
+"<b>启用时</b> 音频单位插件被应用起点发现。当禁用音频单位插件时,仅在手动触发“扫"
+"描”时可用。第一次成功的扫描将启用音频单位自动扫描,若插件发现任何崩溃的情况都将禁用"
+"自动扫描。"
+
+#: rc_option_editor.cc:1114
+msgid "Clear AU Cache"
+msgstr "清除音频单位缓存"
+
+#: rc_option_editor.cc:1118
+msgid "Clear AU Blacklist"
+msgstr "清除音频单位黑名单"
+
+#: rc_option_editor.cc:1201
+msgid "Set Windows VST Search Path"
+msgstr "设置 Windows VST 搜索路径"
+
+#: rc_option_editor.cc:1216
+msgid "Set Linux VST Search Path"
+msgstr "设置 Linux VST 搜索路径"
+
+#: rc_option_editor.cc:1297
+msgid "%1 Preferences"
+msgstr "%1 首选项"
+
+#: rc_option_editor.cc:1309
+msgid "DSP CPU Utilization"
+msgstr "DSP 的 CPU 利用率"
+
+#: rc_option_editor.cc:1313
+msgid "Signal processing uses"
+msgstr "信号处理使用"
+
+#: rc_option_editor.cc:1318
+msgid "all but one processor"
+msgstr "除了一个处理器外所有的"
+
+#: rc_option_editor.cc:1319
+msgid "all available processors"
+msgstr "所有可用的处理器"
+
+#: rc_option_editor.cc:1322
+msgid "%1 processors"
+msgstr "%1 处理器"
+
+#: rc_option_editor.cc:1325
+msgid "This setting will only take effect when %1 is restarted."
+msgstr "该设置将仅仅在 %1 重新启动时起作用"
+
+#: rc_option_editor.cc:1330
+msgid "Options|Undo"
+msgstr "选项|撤销"
+
+#: rc_option_editor.cc:1337
+msgid "Verify removal of last capture"
+msgstr "确认移除最后的捕获部分"
+
+#: rc_option_editor.cc:1345
+msgid "Make periodic backups of the session file"
+msgstr "定期备份会话文件"
+
+#: rc_option_editor.cc:1350
+msgid "Session Management"
+msgstr "会话管理"
+
+#: rc_option_editor.cc:1355
+msgid "Always copy imported files"
+msgstr "总是复制导入的文件"
+
+#: rc_option_editor.cc:1362
+msgid "Default folder for new sessions:"
+msgstr "新会话的默认文件夹:"
+
+#: rc_option_editor.cc:1370
+msgid "Maximum number of recent sessions"
+msgstr "当前会话的最大数量"
+
+#: rc_option_editor.cc:1383
+msgid "Click gain level"
+msgstr "点击增益电平"
+
+#: rc_option_editor.cc:1388 route_time_axis.cc:266 route_time_axis.cc:821
+msgid "Automation"
+msgstr "自动化"
+
+#: rc_option_editor.cc:1393
+msgid "Thinning factor (larger value => less data)"
+msgstr " 稀释参数(较大的数值 => 较少的数据)"
+
+#: rc_option_editor.cc:1402
+msgid "Automation sampling interval (milliseconds)"
+msgstr "自动化样本间隔(毫秒)"
+
+#: rc_option_editor.cc:1414
+msgid "Keep record-enable engaged on stop"
+msgstr "停止时,保持启用的录制仍在启用中"
+
+#: rc_option_editor.cc:1423
+msgid "Play loop is a transport mode"
+msgstr "播放循环是一个播送模式"
+
+#: rc_option_editor.cc:1428
+msgid ""
+"<b>When enabled</b> the loop button does not start playback but forces playback to "
+"always play the loop\n"
+"\n"
+"<b>When disabled</b> the loop button starts playing the loop, but stop then "
+"cancels loop playback"
+msgstr ""
+"<b>启用时</b> 循环按钮不启动回放,但强制回放总是播放循环\n"
+"\n"
+"<b>禁用时</b> 循环按钮启动播放循环,但停止也取消循环回放"
+
+#: rc_option_editor.cc:1434
+msgid "Stop recording when an xrun occurs"
+msgstr "在x运行出现时停止录制"
+
+#: rc_option_editor.cc:1439
+msgid ""
+"<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by "
+"the audio engine"
+msgstr "<b>启用时</b> 如果音频引擎检测到一个超载或者欠载运行 %1 将停止录制"
+
+#: rc_option_editor.cc:1445
+msgid "Create markers where xruns occur"
+msgstr "在x运行出现时创建标记"
+
+#: rc_option_editor.cc:1454
+msgid "Stop at the end of the session"
+msgstr "在会话终点停止"
+
+#: rc_option_editor.cc:1459
+msgid ""
+"<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport when "
+"it reaches the current session end marker\n"
+"\n"
+"<b>When disabled</b> %1 will continue to roll past the session end marker at all "
+"times"
+msgstr ""
+"<b>启用时</b> 如果 %1 是 <b>非录制中</b>,当它达到当前会话的终点标记时它将停止播"
+"送\n"
+"\n"
+"<b>禁用时</b> %1 将继续一直滚动运行到会话终点标记"
+
+#: rc_option_editor.cc:1467
+msgid "Do seamless looping (not possible when slaved to MTC, LTC etc)"
+msgstr "做无缝循环(当从属于 MTC,LTC 诸如此类时不可能实现)"
+
+#: rc_option_editor.cc:1472
+msgid ""
+"<b>When enabled</b> this will loop by reading ahead and wrapping around at the "
+"loop point, preventing any need to do a transport locate at the end of the loop\n"
+"\n"
+"<b>When disabled</b> looping is done by locating back to the start of the loop "
+"when %1 reaches the end which will often cause a small click or delay"
+msgstr ""
+"<b>启用时</b>这将通过预先读取来循环并且在循环点围绕,防止任何需要把播送定位在循环的"
+"终点的情况\n"
+"\n"
+"<b>禁用时</b> 当 %1 到达会经常引起一个轻微识别声或延迟的终点时,通过定位回到循环的"
+"起点而完成循环"
+
+#: rc_option_editor.cc:1480
+msgid "Disable per-track record disarm while rolling"
+msgstr "当滚动时禁用预先音轨录制解除"
+
+#: rc_option_editor.cc:1484
+msgid ""
+"<b>When enabled</b> this will prevent you from accidentally stopping specific "
+"tracks recording during a take"
+msgstr "<b>启用时</b> 这将防止您在这过程中意外停止指定的音轨录制"
+
+#: rc_option_editor.cc:1489
+msgid "12dB gain reduction during fast-forward and fast-rewind"
+msgstr "快进和倒带时有 12dB 的增益减少"
+
+#: rc_option_editor.cc:1493
+msgid ""
+"This will reduce the unpleasant increase in perceived volume that occurs when fast-"
+"forwarding or rewinding through some kinds of audio"
+msgstr "当快进或倒带通过某些音频类型时,这将减少令人感到不适的可感知音量增加的现像"
+
+#: rc_option_editor.cc:1497
+msgid "Sync/Slave"
+msgstr "同步/从属"
+
+#: rc_option_editor.cc:1501
+msgid "External timecode source"
+msgstr "外部时间码源"
+
+#: rc_option_editor.cc:1510
+msgid "Match session video frame rate to external timecode"
+msgstr "匹配会话视频帧率到外部时间码"
+
+#: rc_option_editor.cc:1516
+msgid ""
+"This option controls the value of the video frame rate <i>while chasing</i> an "
+"external timecode source.\n"
+"\n"
+"<b>When enabled</b> the session video frame rate will be changed to match that of "
+"the selected external timecode source.\n"
+"\n"
+"<b>When disabled</b> the session video frame rate will not be changed to match "
+"that of the selected external timecode source.Instead the frame rate indication in "
+"the main clock will flash red and %1 will convert between the external timecode "
+"standard and the session standard."
+msgstr ""
+"这个选项控制视频帧率的数值<i>当追随</i>一个外部时间码源时\n"
+"\n"
+"<b>启用时</b> 会话视频帧率将被改变为匹配到已选中的外部时间码源。\n"
+"\n"
+"<b>禁用时</b> 会话视频帧率将不会被改变为匹配到已选中的外部时间码源。取而代之的是,"
+"帧率在主计时器里的指示将在转换外部时间代码标准和会话标准两者间转换。"
+
+#: rc_option_editor.cc:1526
+msgid "Sync lock timecode to clock - Disable drift compensation."
+msgstr "同步时间代码到计时器——禁用漂移补偿。"
+
+#: rc_option_editor.cc:1532
+msgid ""
+"<b>When enabled</b> %1 will never varispeed when slaved to external timecode. Sync "
+"Lock indicates that the selected external timecode source shares clock-sync (Black "
+"& Burst, Wordclock, etc) with the audio interface. This option disables drift "
+"compensation. The transport speed is fixed at 1.0.Varispeed LTC will be ignored "
+"and cause drift.\n"
+"\n"
+"<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
+"timecode sources shares clock sync."
+msgstr ""
+"<b>启用时</b> 在从属于外部时间码时 %1 将不会变速。同步锁定表明已选中的外部时间码源"
+"与音频界面共享计时器同步( Black & Burst, Wordclock,等等)。这个选项禁用漂移"
+"补偿。播送速度被修正于 1.0.Varispeed LTC 将被忽略且引起漂移。\n"
+"\n"
+"<b>禁用时</b> %1 将补偿潜在的漂移,不论时间码源是否共享时间同步。"
+
+#: rc_option_editor.cc:1547
+msgid "Lock to 29.9700 fps instead of 30000/1001"
+msgstr "锁定到 29.9700 fps 以替代 30000/1001"
+
+#: rc_option_editor.cc:1553
+msgid ""
+"<b>When enabled</b> the external timecode source is assumed to use 29.97 fps "
+"instead of 30000/1001.\n"
+"SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
+"drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
+"Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * "
+"0.9990 (ie 29.970000). That is not the actual rate. However, some vendors use that "
+"rate - despite it being against the specs - because the variant of using exactly "
+"29.97 fps has zero timecode drift.\n"
+msgstr ""
+"<b>启用时</b> 外部时间码源被假定使用 29.97 fps 以替代 30000/1001 。\n"
+"SMPTE 12M-1999 指定 29.97df 为 30000/1001 。进一步的规范提到丢帧时间码有一个在 24 "
+"小时内 -86ms 的累积错误。\n"
+"丢帧时间码将完全补偿 30 * 0.9990 (ie 29.970000)的 NTSC 色彩帧率。那不是实际帧率。"
+"然而,某些厂商使用这帧率——尽管它违背规范——因为使用实际 29.97 fps 的时间码漂移变化"
+"为 0 。\n"
+
+#: rc_option_editor.cc:1563
+msgid "LTC Reader"
+msgstr "LTC 阅读器"
+
+#: rc_option_editor.cc:1567
+msgid "LTC incoming port"
+msgstr "LTC 导入端口"
+
+#: rc_option_editor.cc:1582
+msgid "LTC Generator"
+msgstr "LTC 生成器"
+
+#: rc_option_editor.cc:1587
+msgid "Enable LTC generator"
+msgstr "启用 LTC 生成器"
+
+#: rc_option_editor.cc:1594
+msgid "Send LTC while stopped"
+msgstr "停止时发送 LTC "
+
+#: rc_option_editor.cc:1600
+msgid ""
+"<b>When enabled</b> %1 will continue to send LTC information even when the "
+"transport (playhead) is not moving"
+msgstr "<b>启用时</b> %1 将继续发送 LTC 信息,即使当播送(指针)不再移动"
+
+#: rc_option_editor.cc:1606
+msgid "LTC generator level"
+msgstr "LTC 生成器电平"
+
+#: rc_option_editor.cc:1610
+msgid ""
+"Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu "
+"^= -18dbFS in an EBU calibrated system"
+msgstr ""
+"以 dbFS 指定生成 LTC 信号音量的峰值。建议的数值是 0dBu ^= -18dbFS 在一个 EBU 校准系"
+"统里"
+
+#: rc_option_editor.cc:1622
+msgid "Allow dragging of playhead"
+msgstr "允许拖拽指针"
+
+#: rc_option_editor.cc:1630
+msgid "Move relevant automation when audio regions are moved"
+msgstr "当音频区域移动时,也移动相关的自动化"
+
+#: rc_option_editor.cc:1638
+msgid "Show meters on tracks in the editor"
+msgstr "在编辑器的音轨上显示节拍"
+
+#: rc_option_editor.cc:1646
+msgid "Display master-meter in the toolbar"
+msgstr "在工具栏里显示主控节拍"
+
+#: rc_option_editor.cc:1653
+msgid "Default fade shape"
+msgstr "默认淡化形状"
+
+#: rc_option_editor.cc:1672
+msgid "Regions in active edit groups are edited together"
+msgstr "区域位于激活编辑的分组里会被彼此编辑"
+
+#: rc_option_editor.cc:1673
+msgid "whenever they overlap in time"
+msgstr "不论何时都及时重叠它们"
+
+#: rc_option_editor.cc:1674
+msgid "only if they have identical length, position and origin"
+msgstr "仅在当它们拥有完全相同的长度、位置和原点时"
+
+#: rc_option_editor.cc:1684
+msgid "Make rubberband selection rectangle snap to the grid"
+msgstr "使橡皮带已选择部分矩形吸附到网格对齐"
+
+#: rc_option_editor.cc:1692
+msgid "Show waveforms in regions"
+msgstr "在区域内显示波形"
+
+#: rc_option_editor.cc:1700
+msgid "Show gain envelopes in audio regions"
+msgstr "在音频区域内显示增益封装"
+
+#: rc_option_editor.cc:1701
+msgid "in all modes"
+msgstr "在所有模式内"
+
+#: rc_option_editor.cc:1702
+msgid "only in region gain mode"
+msgstr "仅在区域增益模式内"
+
+#: rc_option_editor.cc:1709
+msgid "Waveform scale"
+msgstr "波形比例"
+
+#: rc_option_editor.cc:1714
+msgid "linear"
+msgstr "线性"
+
+#: rc_option_editor.cc:1715
+msgid "logarithmic"
+msgstr "对数"
+
+#: rc_option_editor.cc:1721
+msgid "Waveform shape"
+msgstr "波形形状"
+
+#: rc_option_editor.cc:1726
+msgid "traditional"
+msgstr "传统的"
+
+#: rc_option_editor.cc:1727
+msgid "rectified"
+msgstr "已矫正的"
+
+#: rc_option_editor.cc:1736
+msgid "Show waveforms for audio while it is being recorded"
+msgstr "在音频被录制时显示它的波形"
+
+#: rc_option_editor.cc:1744
+msgid "Show zoom toolbar"
+msgstr "显示缩放工具栏"
+
+#: rc_option_editor.cc:1752
+msgid "Update editor window during drags of the summary"
+msgstr "当拖拽摘要时,更新编辑器窗口"
+
+#: rc_option_editor.cc:1760
+msgid "Synchronise editor and mixer selection"
+msgstr "同步编辑器和混音器已选中部分"
+
+#: rc_option_editor.cc:1767
+msgid "Name new markers"
+msgstr "命名新标签"
+
+#: rc_option_editor.cc:1773
+msgid ""
+"If enabled, popup a dialog when a new marker is created to allow its name to be "
+"set as it is created.\n"
+"\n"
+"You can always rename markers by right-clicking on them"
+msgstr ""
+"如果启用,当创建一个新标记时会弹出一个对话框,允许为创建它而设置它的名称。\n"
+"\n"
+"您总是可以通过右键单击它们来重命名标志"
+
+#: rc_option_editor.cc:1779
+msgid "Auto-scroll editor window when dragging near its edges"
+msgstr "当拖动边缘附近时,自动滚动编辑器窗口"
+
+#: rc_option_editor.cc:1786
+msgid "After splitting selected regions, select"
+msgstr "在拆分已选中区域之后,选择"
+
+#: rc_option_editor.cc:1791
+msgid "no regions"
+msgstr "无区域"
+
+#: rc_option_editor.cc:1794
+msgid "newly-created regions"
+msgstr "新创建的区域"
+
+#: rc_option_editor.cc:1798
+msgid "existing selection and newly-created regions"
+msgstr "已存在的已选中部分和新创建的区域"
+
+#: rc_option_editor.cc:1805
+msgid "Buffering"
+msgstr "缓冲中"
+
+#: rc_option_editor.cc:1813
+msgid "Record monitoring handled by"
+msgstr "录制监控的处理是通过"
+
+#: rc_option_editor.cc:1819
+msgid "via Audio Driver"
+msgstr "via 音频驱动"
+
+#: rc_option_editor.cc:1825
+msgid "audio hardware"
+msgstr "音频硬件"
+
+#: rc_option_editor.cc:1832
+msgid "Tape machine mode"
+msgstr "磁带机器模式"
+
+#: rc_option_editor.cc:1837
+msgid "Connection of tracks and busses"
+msgstr "音轨和总线的连接"
+
+#: rc_option_editor.cc:1842
+msgid "Auto-connect master/monitor busses"
+msgstr "自动连接主控/监控总线"
+
+#: rc_option_editor.cc:1849
+msgid "Connect track inputs"
+msgstr "连接音轨输入"
+
+#: rc_option_editor.cc:1854
+msgid "automatically to physical inputs"
+msgstr "自动化物理输入"
+
+#: rc_option_editor.cc:1855 rc_option_editor.cc:1868
+msgid "manually"
+msgstr "手动"
+
+#: rc_option_editor.cc:1861
+msgid "Connect track and bus outputs"
+msgstr "连接音轨和总线输出"
+
+#: rc_option_editor.cc:1866
+msgid "automatically to physical outputs"
+msgstr "自动化物理输出"
+
+#: rc_option_editor.cc:1867
+msgid "automatically to master bus"
+msgstr "自动化主控总线"
+
+#: rc_option_editor.cc:1872
+msgid "Denormals"
+msgstr "异常"
+
+#: rc_option_editor.cc:1877
+msgid "Use DC bias to protect against denormals"
+msgstr "使用直流偏压针对异常防护"
+
+#: rc_option_editor.cc:1884
+msgid "Processor handling"
+msgstr "处理器处理"
+
+#: rc_option_editor.cc:1890
+msgid "no processor handling"
+msgstr "无处理器处理"
+
+#: rc_option_editor.cc:1896
+msgid "use FlushToZero"
+msgstr "使用齐平为零"
+
+#: rc_option_editor.cc:1903
+msgid "use DenormalsAreZero"
+msgstr "使用异常齐平为零"
+
+#: rc_option_editor.cc:1910
+msgid "use FlushToZero and DenormalsAreZero"
+msgstr "使用齐平为零和异常齐平为零"
+
+#: rc_option_editor.cc:1926
+msgid "Silence plugins when the transport is stopped"
+msgstr "当播送停止时插件也无声"
+
+#: rc_option_editor.cc:1934
+msgid "Make new plugins active"
+msgstr "启用新插件"
+
+#: rc_option_editor.cc:1944
+msgid "Enable automatic analysis of audio"
+msgstr "启用音频自动分析"
+
+#: rc_option_editor.cc:1952
+msgid "Replicate missing region channels"
+msgstr "复制缺失的区域声道"
+
+#: rc_option_editor.cc:1959 rc_option_editor.cc:1961 rc_option_editor.cc:1976
+#: rc_option_editor.cc:1988 rc_option_editor.cc:2000 rc_option_editor.cc:2012
+#: rc_option_editor.cc:2016 rc_option_editor.cc:2024 rc_option_editor.cc:2032
+#: rc_option_editor.cc:2040 rc_option_editor.cc:2042 rc_option_editor.cc:2050
+#: rc_option_editor.cc:2058 rc_option_editor.cc:2066 rc_option_editor.cc:2074
+#: rc_option_editor.cc:2076
+msgid "Solo / mute"
+msgstr "独奏 / 静音"
+
+#: rc_option_editor.cc:1964
+msgid "Solo-in-place mute cut (dB)"
+msgstr "适当的独奏削减静音(dB)"
+
+#: rc_option_editor.cc:1971
+msgid "Solo controls are Listen controls"
+msgstr "单独控制即是试听控制"
+
+#: rc_option_editor.cc:1980
+msgid "Listen Position"
+msgstr "试听位置"
+
+#: rc_option_editor.cc:1985
+msgid "after-fader (AFL)"
+msgstr "后置淡化(AFL)"
+
+#: rc_option_editor.cc:1986
+msgid "pre-fader (PFL)"
+msgstr "前置淡化(PFL)"
+
+#: rc_option_editor.cc:1992
+msgid "PFL signals come from"
+msgstr "前置淡化信号来自"
+
+#: rc_option_editor.cc:1997
+msgid "before pre-fader processors"
+msgstr "在前置淡化处理器之前"
+
+#: rc_option_editor.cc:1998
+msgid "pre-fader but after pre-fader processors"
+msgstr "前置淡化但在前置淡化处理器之后"
+
+#: rc_option_editor.cc:2004
+msgid "AFL signals come from"
+msgstr "后置淡化信号来自于"
+
+#: rc_option_editor.cc:2009
+msgid "immediately post-fader"
+msgstr "立即后置淡化"
+
+#: rc_option_editor.cc:2010
+msgid "after post-fader processors (before pan)"
+msgstr "后置淡化处理器之后(平移之前)"
+
+#: rc_option_editor.cc:2019
+msgid "Exclusive solo"
+msgstr "专属独奏"
+
+#: rc_option_editor.cc:2027
+msgid "Show solo muting"
+msgstr "显示独奏静音"
+
+#: rc_option_editor.cc:2035
+msgid "Soloing overrides muting"
+msgstr "独奏覆盖静音"
+
+#: rc_option_editor.cc:2040
+msgid "Default track / bus muting options"
+msgstr "默认音轨 / 总线静音选项"
+
+#: rc_option_editor.cc:2045
+msgid "Mute affects pre-fader sends"
+msgstr "静音效果前置淡化发送"
+
+#: rc_option_editor.cc:2053
+msgid "Mute affects post-fader sends"
+msgstr "静音效果后置淡化发送"
+
+#: rc_option_editor.cc:2061
+msgid "Mute affects control outputs"
+msgstr "静音效果控制输出"
+
+#: rc_option_editor.cc:2069
+msgid "Mute affects main outputs"
+msgstr "静音效果主要输出"
+
+#: rc_option_editor.cc:2074
+msgid "Send Routing"
+msgstr "发送路由"
+
+#: rc_option_editor.cc:2079
+msgid "Link panners of Aux and External Sends with main panner by default"
+msgstr "链接辅助和外部发送面板和默认的主要面板"
+
+#: rc_option_editor.cc:2087
+msgid "MIDI read-ahead time (seconds)"
+msgstr "MIDI 预先读取时间(秒)"
+
+#: rc_option_editor.cc:2105
+msgid "Send MIDI Time Code"
+msgstr "发送 MIDI 时间码"
+
+#: rc_option_editor.cc:2113
+msgid "Percentage either side of normal transport speed to transmit MTC"
+msgstr "正常播送速度与传输 MTC 之间的百分比"
+
+#: rc_option_editor.cc:2122
+msgid "Obey MIDI Machine Control commands"
+msgstr "遵守 MIDI 机器控制命令"
+
+#: rc_option_editor.cc:2130
+msgid "Send MIDI Machine Control commands"
+msgstr "发送 MIDI 机器控制命令"
+
+#: rc_option_editor.cc:2138
+msgid "Send MIDI control feedback"
+msgstr "发送 MIDI 控制反馈"
+
+#: rc_option_editor.cc:2146
+msgid "Inbound MMC device ID"
+msgstr "进场的 MMC 设备 ID"
+
+#: rc_option_editor.cc:2155
+msgid "Outbound MMC device ID"
+msgstr "出场的 MMC 设备 ID"
+
+#: rc_option_editor.cc:2164
+msgid "Initial program change"
+msgstr "初始程序改变"
+
+#: rc_option_editor.cc:2173
+msgid "Display first MIDI bank/program as 0"
+msgstr "显示第一个 MIDI 库/程序为 0"
+
+#: rc_option_editor.cc:2181
+msgid "Never display periodic MIDI messages (MTC, MIDI Clock)"
+msgstr "不再显示定期 MIDI 信息(MTC, MIDI 计时器)"
+
+#: rc_option_editor.cc:2189
+msgid "Sound MIDI notes as they are selected"
+msgstr "当 MIDI 音符被选中时发出声音"
+
+#: rc_option_editor.cc:2194
+msgid "Midi Audition"
+msgstr "Midi 监听"
+
+#: rc_option_editor.cc:2198
+msgid "Midi Audition Synth (LV2)"
+msgstr "Midi 监听合成(LV2)"
+
+#: rc_option_editor.cc:2229 rc_option_editor.cc:2239 rc_option_editor.cc:2241
+msgid "User interaction"
+msgstr "用户交互"
+
+#: rc_option_editor.cc:2232
+msgid ""
+"Use translations of %1 messages\n"
+"   <i>(requires a restart of %1 to take effect)</i>\n"
+"   <i>(if available for your language preferences)</i>"
+msgstr ""
+"%1 信息的用户交互\n"
+"    <i>(要求重启 %1 以生效)</i>\n"
+"     <i>(如果您的语言首选项可用)</i>"
+
+#: rc_option_editor.cc:2239
+msgid "Keyboard"
+msgstr "键盘"
+
+#: rc_option_editor.cc:2249
+msgid "Control surface remote ID"
+msgstr "控制面远程 ID"
+
+#: rc_option_editor.cc:2254
+msgid "assigned by user"
+msgstr "由用户指定"
+
+#: rc_option_editor.cc:2255
+msgid "follows order of mixer"
+msgstr "混音器按如下排序"
+
+#: rc_option_editor.cc:2269 rc_option_editor.cc:2278 rc_option_editor.cc:2287
+#: rc_option_editor.cc:2297 rc_option_editor.cc:2321 rc_option_editor.cc:2334
+#: rc_option_editor.cc:2343
+msgid "Preferences|GUI"
+msgstr "首选项|图形用户界面"
+
+#: rc_option_editor.cc:2272
+msgid "Graphically indicate mouse pointer hovering over various widgets"
+msgstr "当悬停在各种小部件上面时显示鼠标指针"
+
+#: rc_option_editor.cc:2281
+msgid "Show tooltips if mouse hovers over a control"
+msgstr "如果鼠标悬停在一个控件上面时显示工具提示"
+
+#: rc_option_editor.cc:2290
+msgid "Use name highlight bars in region displays (requires a restart)"
+msgstr "在区域显示中使用名称突出显示栏(需要重新启动)"
+
+#: rc_option_editor.cc:2303
+msgid "update transport clock display at FPS instead of every 100ms"
+msgstr "以 FPS 替代每 100ms 更新播送计时器显示"
+
+#: rc_option_editor.cc:2312
+msgid "Lock timeout (seconds)"
+msgstr "锁定超时(秒)"
+
+#: rc_option_editor.cc:2320
+msgid "Lock GUI after this many idle seconds (zero to never lock)"
+msgstr "在空闲这么多秒之后锁定图形用户界面(零则永不锁定)"
+
+#: rc_option_editor.cc:2336
+msgid "Mixer Strip"
+msgstr "混音器栏"
+
+#: rc_option_editor.cc:2346
+msgid "Use narrow strips in the mixer by default"
+msgstr "默认在混音器里使用细长栏"
+
+#: rc_option_editor.cc:2351 rc_option_editor.cc:2365 rc_option_editor.cc:2384
+#: rc_option_editor.cc:2400 rc_option_editor.cc:2416 rc_option_editor.cc:2430
+#: rc_option_editor.cc:2444 rc_option_editor.cc:2446
+msgid "Preferences|Metering"
+msgstr "首选项|节拍"
+
+#: rc_option_editor.cc:2355
+msgid "Peak hold time"
+msgstr "峰值停留时间"
+
+#: rc_option_editor.cc:2361
+msgid "short"
+msgstr "短"
+
+#: rc_option_editor.cc:2362
+msgid "medium"
+msgstr "中"
+
+#: rc_option_editor.cc:2363
+msgid "long"
+msgstr "é•¿"
+
+#: rc_option_editor.cc:2369
+msgid "DPM fall-off"
+msgstr "DPM 衰减"
+
+#: rc_option_editor.cc:2375
+msgid "slowest [6.6dB/sec]"
+msgstr "最慢 [6.6dB/sec]"
+
+#: rc_option_editor.cc:2376
+msgid "slow [8.6dB/sec] (BBC PPM, EBU PPM)"
+msgstr "æ…¢ [8.6dB/sec] (BBC PPM, EBU PPM)"
+
+#: rc_option_editor.cc:2377
+msgid "slowish [12.0dB/sec] (DIN)"
+msgstr "稍慢 [12.0dB/sec] (DIN)"
+
+#: rc_option_editor.cc:2378
+msgid "moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"
+msgstr "稳健 [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"
+
+#: rc_option_editor.cc:2379
+msgid "medium [20dB/sec]"
+msgstr "中等 [20dB/sec]"
+
+#: rc_option_editor.cc:2380
+msgid "fast [32dB/sec]"
+msgstr "å¿« [32dB/sec]"
+
+#: rc_option_editor.cc:2381
+msgid "faster [46dB/sec]"
+msgstr "较快 [46dB/sec]"
+
+#: rc_option_editor.cc:2382
+msgid "fastest [70dB/sec]"
+msgstr "最快 [70dB/sec]"
+
+#: rc_option_editor.cc:2388
+msgid "Meter line-up level; 0dBu"
+msgstr "节拍排队电平;0dBu"
+
+#: rc_option_editor.cc:2393 rc_option_editor.cc:2409
+msgid "-24dBFS (SMPTE US: 4dBu = -20dBFS)"
+msgstr ""
+
+#: rc_option_editor.cc:2394 rc_option_editor.cc:2410
+msgid "-20dBFS (SMPTE RP.0155)"
+msgstr ""
+
+#: rc_option_editor.cc:2395 rc_option_editor.cc:2411
+msgid "-18dBFS (EBU, BBC)"
+msgstr ""
+
+#: rc_option_editor.cc:2396 rc_option_editor.cc:2412
+msgid "-15dBFS (DIN)"
+msgstr ""
+
+#: rc_option_editor.cc:2398
+msgid ""
+"Configure meter-marks and color-knee point for dBFS scale DPM, set reference level "
+"for IEC1/Nordic, IEC2 PPM and VU meter."
+msgstr ""
+"配置节拍标志和转角颜色点用于 dBFS 缩放 DPM,为 IEC1/Nordic、IEC2 PPM 和 VU 节拍设置"
+"参考电平。"
+
+#: rc_option_editor.cc:2404
+msgid "IEC1/DIN Meter line-up level; 0dBu"
+msgstr "IEC1/DIN 节拍排队电平;0dBu"
+
+#: rc_option_editor.cc:2414
+msgid "Reference level for IEC1/DIN meter."
+msgstr "IEC1/DIN 节拍参考电平。"
+
+#: rc_option_editor.cc:2420
+msgid "VU Meter standard"
+msgstr "VU 节拍标准"
+
+#: rc_option_editor.cc:2425
+msgid "0VU = -2dBu (France)"
+msgstr "0VU = -2dBu (法国)"
+
+#: rc_option_editor.cc:2426
+msgid "0VU = 0dBu (North America, Australia)"
+msgstr "0VU = 0dBu (北美,澳洲)"
+
+#: rc_option_editor.cc:2427
+msgid "0VU = +4dBu (standard)"
+msgstr "0VU = +4dBu (标准)"
+
+#: rc_option_editor.cc:2428
+msgid "0VU = +8dBu"
+msgstr ""
+
+#: rc_option_editor.cc:2434
+msgid "Peak threshold [dBFS]"
+msgstr "峰值临界值 [dBFS]"
+
+#: rc_option_editor.cc:2442
+msgid ""
+"Specify the audio signal level in dbFS at and above which the meter-peak indicator "
+"will flash red."
+msgstr "以 dbFS 指定音频信号电平,达到以及超过节拍峰时,值指示器将闪烁红灯。"
+
+#: rc_option_editor.cc:2449
+msgid "LED meter style"
+msgstr "LED 节拍类型"
+
+#: rc_option_editor.cc:2457
+msgid "Theme"
+msgstr "主题"
+
+#: region_editor.cc:79
+msgid "audition this region"
+msgstr "监听此区域"
+
+#: region_editor.cc:88 region_layering_order_editor.cc:75
+msgid "Position:"
+msgstr "位置:"
+
+#: region_editor.cc:90 add_video_dialog.cc:155
+msgid "End:"
+msgstr "终点:"
+
+#: region_editor.cc:92 sfdb_ui.cc:145
+msgid "Length:"
+msgstr "长度:"
+
+#: region_editor.cc:94
+msgid "Sync point (relative to region):"
+msgstr "同步点(相对于区域):"
+
+#: region_editor.cc:96
+msgid "Sync point (absolute):"
+msgstr "同步点(绝对):"
+
+#: region_editor.cc:98
+msgid "File start:"
+msgstr "文件起点:"
+
+#: region_editor.cc:102
+msgid "Sources:"
+msgstr "源:"
+
+#: region_editor.cc:104
+msgid "Source:"
+msgstr "源:"
+
+#: region_editor.cc:166
+msgid "Region '%1'"
+msgstr "区域 '%1'"
+
+#: region_editor.cc:273
+msgid "change region start position"
+msgstr "改变区域起点位置"
+
+#: region_editor.cc:289
+msgid "change region end position"
+msgstr "改变区域终点位置"
+
+#: region_editor.cc:309
+msgid "change region length"
+msgstr "改变区域长度"
+
+#: region_editor.cc:403 region_editor.cc:415
+msgid "change region sync point"
+msgstr "改变区域同步点"
+
+#: region_layering_order_editor.cc:42
+msgid "RegionLayeringOrderEditor"
+msgstr "区域分层排序编辑器"
+
+#: region_layering_order_editor.cc:55
+msgid "Region Name"
+msgstr "区域名称"
+
+#: region_layering_order_editor.cc:72
+msgid "Track:"
+msgstr "音轨:"
+
+#: region_layering_order_editor.cc:104
+msgid "Choose Top Region"
+msgstr "选择顶部区域"
+
+#: region_view.cc:277
+msgid "SilenceText"
+msgstr "无声文本"
+
+#: region_view.cc:292 region_view.cc:311
+msgid "minutes"
+msgstr "分钟"
+
+#: region_view.cc:295 region_view.cc:314
+msgid "msecs"
+msgstr "毫秒"
+
+#: region_view.cc:298 region_view.cc:317
+msgid "secs"
+msgstr "秒"
+
+#: region_view.cc:301
+msgid "%1 silent segment"
+msgid_plural "%1 silent segments"
+msgstr[0] "%1 无声片段"
+
+#: region_view.cc:303
+msgid "shortest = %1 %2"
+msgstr "最短 = %1 %2"
+
+#: region_view.cc:320
+msgid ""
+"\n"
+"  (shortest audible segment = %1 %2)"
+msgstr ""
+"\n"
+"  (最短的可听见片段 = %1 %2)"
+
+#: return_ui.cc:102
+msgid "Return "
+msgstr "返回"
+
+#: rhythm_ferret.cc:48
+msgid "Percussive Onset"
+msgstr "敲击启动"
+
+#: rhythm_ferret.cc:49
+msgid "Note Onset"
+msgstr "音符启动"
+
+#: rhythm_ferret.cc:54
+msgid "Energy Based"
+msgstr "能量基准"
+
+#: rhythm_ferret.cc:55
+msgid "Spectral Difference"
+msgstr "波谱差异"
+
+#: rhythm_ferret.cc:56
+msgid "High-Frequency Content"
+msgstr "高频内容"
+
+#: rhythm_ferret.cc:57
+msgid "Complex Domain"
+msgstr "复合领域"
+
+#: rhythm_ferret.cc:58
+msgid "Phase Deviation"
+msgstr "相位偏差"
+
+#: rhythm_ferret.cc:59
+msgid "Kullback-Liebler"
+msgstr ""
+
+#: rhythm_ferret.cc:60
+msgid "Modified Kullback-Liebler"
+msgstr "改良的 Kullback-Liebler"
+
+#: rhythm_ferret.cc:65
+msgid "Split region"
+msgstr "拆分区域"
+
+#: rhythm_ferret.cc:66
+msgid "Snap regions"
+msgstr "吸附区域"
+
+#: rhythm_ferret.cc:67
+msgid "Conform regions"
+msgstr "适应区域"
+
+#: rhythm_ferret.cc:72
+msgid "Rhythm Ferret"
+msgstr "节奏探测"
+
+#: rhythm_ferret.cc:78
+msgid "Analyze"
+msgstr "分析"
+
+#: rhythm_ferret.cc:113
+msgid "Detection function"
+msgstr "检测功能"
+
+#: rhythm_ferret.cc:117
+msgid "Trigger gap"
+msgstr "触发间隙"
+
+#: rhythm_ferret.cc:122 strip_silence_dialog.cc:64
+msgid "Threshold"
+msgstr "临界值"
+
+#: rhythm_ferret.cc:127
+msgid "Peak threshold"
+msgstr "峰值临界值"
+
+#: rhythm_ferret.cc:132
+msgid "Silence threshold"
+msgstr "无声临界值"
+
+#: rhythm_ferret.cc:137
+msgid "Sensitivity"
+msgstr "灵敏度"
+
+#: rhythm_ferret.cc:141
+msgid "Operation"
+msgstr "操作"
+
+#: rhythm_ferret.cc:355
+msgid "split regions (rhythm ferret)"
+msgstr "拆分区域(节奏探测)"
+
+#: route_group_dialog.cc:42
+msgid "Track/bus Group"
+msgstr "音轨/总线分组"
+
+#: route_group_dialog.cc:47
+msgid "Relative"
+msgstr "关联的"
+
+#: route_group_dialog.cc:48
+msgid "Muting"
+msgstr "静音中"
+
+#: route_group_dialog.cc:50
+msgid "Record enable"
+msgstr "启用录制"
+
+#: route_group_dialog.cc:52
+msgid "Active state"
+msgstr "激活状态"
+
+#: route_group_dialog.cc:53 route_group_dialog.cc:82 theme_manager.cc:90
+msgid "Color"
+msgstr "颜色"
+
+#: route_group_dialog.cc:59
+msgid "RouteGroupDialog"
+msgstr "路由分组对话框"
+
+#: route_group_dialog.cc:100
+msgid "<b>Sharing</b>"
+msgstr "<b>共享中</b>"
+
+#: route_group_dialog.cc:200
+msgid "The group name is not unique. Please use a different name."
+msgstr "分组名称有重复。请使用另一个名称。"
+
+#: route_params_ui.cc:84
+msgid "Tracks/Busses"
+msgstr "音轨/总线"
+
+#: route_params_ui.cc:103
+msgid "Inputs"
+msgstr "输入"
+
+#: route_params_ui.cc:104
+msgid "Outputs"
+msgstr "输出"
+
+#: route_params_ui.cc:105
+msgid "Plugins, Inserts & Sends"
+msgstr "插件,插入和发送"
+
+#: route_params_ui.cc:209
+msgid "route display list item for renamed route not found!"
+msgstr "未找到已重命名路由的路由显示列表条目!"
+
+#: route_params_ui.cc:279 route_params_ui.cc:307
+#, c-format
+msgid "Playback delay: %<PRId64> samples"
+msgstr "回放延迟: %<PRId64> 采样"
+
+#: route_params_ui.cc:499
+msgid "NO TRACK"
+msgstr "没有音轨"
+
+#: route_params_ui.cc:637 route_params_ui.cc:638
+msgid "No Track or Bus Selected"
+msgstr "没有音轨或总线被选中"
+
+#: route_time_axis.cc:181
+msgid "Record (Right-click for Step Edit)"
+msgstr "录制(右键点击步进编辑)"
+
+#: route_time_axis.cc:184
+msgid "Record"
+msgstr "录制"
+
+#: route_time_axis.cc:254
+msgid "Route Group"
+msgstr "路由分组"
+
+#: route_time_axis.cc:264
+msgid "MIDI Controllers and Automation"
+msgstr "MIDI 控制器和自动化"
+
+#: route_time_axis.cc:495
+msgid "Show All Automation"
+msgstr "显示所有的自动化"
+
+#: route_time_axis.cc:498
+msgid "Show Existing Automation"
+msgstr "显示已有的自动化"
+
+#: route_time_axis.cc:501
+msgid "Hide All Automation"
+msgstr "隐藏所有自动化"
+
+#: route_time_axis.cc:510
+msgid "Processor automation"
+msgstr "处理器自动化"
+
+#: route_time_axis.cc:517
+msgid "Fader"
+msgstr "淡化"
+
+#: route_time_axis.cc:535
+msgid "Pan"
+msgstr "平移"
+
+#: route_time_axis.cc:626
+msgid "Overlaid"
+msgstr "重叠"
+
+#: route_time_axis.cc:632
+msgid "Stacked"
+msgstr "堆栈"
+
+#: route_time_axis.cc:640
+msgid "Layers"
+msgstr "层"
+
+#: route_time_axis.cc:709
+msgid "Automatic (based on I/O connections)"
+msgstr "自动的(基于输入/输出连接)"
+
+#: route_time_axis.cc:718
+msgid "(Currently: Existing Material)"
+msgstr "(当前:现有材料)"
+
+#: route_time_axis.cc:721
+msgid "(Currently: Capture Time)"
+msgstr "(当前:捕获时间)"
+
+#: route_time_axis.cc:729
+msgid "Align With Existing Material"
+msgstr "与现有材料对齐"
+
+#: route_time_axis.cc:734
+msgid "Align With Capture Time"
+msgstr "与捕获时间对齐"
+
+#: route_time_axis.cc:739
+msgid "Alignment"
+msgstr "对齐"
+
+#: route_time_axis.cc:774
+msgid "Normal Mode"
+msgstr "正常模式"
+
+#: route_time_axis.cc:780
+msgid "Tape Mode"
+msgstr "磁带模式"
+
+#: route_time_axis.cc:786
+msgid "Non-Layered Mode"
+msgstr "不分层模式"
+
+#: route_time_axis.cc:792
+msgid "Record Mode"
+msgstr "录制模式"
+
+#: route_time_axis.cc:799 route_time_axis.cc:1789
+msgid "Playlist"
+msgstr "播放列表"
+
+#: route_time_axis.cc:1097
+msgid "Rename Playlist"
+msgstr "重命名播放列表"
+
+#: route_time_axis.cc:1098
+msgid "New name for playlist:"
+msgstr "播放列表的新名称:"
+
+#: route_time_axis.cc:1183
+msgid "New Copy Playlist"
+msgstr "新建播放列表拷贝"
+
+#: route_time_axis.cc:1184 route_time_axis.cc:1237
+msgid "Name for new playlist:"
+msgstr "新播放列表名称:"
+
+#: route_time_axis.cc:1236
+msgid "New Playlist"
+msgstr "新建播放列表"
+
+#: route_time_axis.cc:1436
+msgid "You cannot create a track with that name as it is reserved for %1"
+msgstr "无法以此名称创建音轨,因为它被 %1 保留使用"
+
+#: route_time_axis.cc:1678
+msgid "New Copy..."
+msgstr "新建拷贝…"
+
+#: route_time_axis.cc:1682
+msgid "New Take"
+msgstr "新建磁带"
+
+#: route_time_axis.cc:1683
+msgid "Copy Take"
+msgstr "拷贝磁带"
+
+#: route_time_axis.cc:1688
+msgid "Clear Current"
+msgstr "清除当前"
+
+#: route_time_axis.cc:1691
+msgid "Select From All..."
+msgstr "选择所有…"
+
+#: route_time_axis.cc:1779
+msgid "Take: %1.%2"
+msgstr "磁带:%1.%2"
+
+#: route_time_axis.cc:2169 selection.cc:1007 selection.cc:1061
+msgid "programming error: "
+msgstr "程序错误:"
+
+#: route_time_axis.cc:2585
+msgid "Underlays"
+msgstr "底层"
+
+#: route_time_axis.cc:2588
+msgid "Remove \"%1\""
+msgstr "移除 \"%1\""
+
+#: route_time_axis.cc:2638 route_time_axis.cc:2675
+msgid "programming error: underlay reference pointer pairs are inconsistent!"
+msgstr "程序错误:底层参考指针搭配不一致!"
+
+#: route_time_axis.cc:2702
+msgid "After-fade listen (AFL)"
+msgstr "后置淡化试听(AFL)"
+
+#: route_time_axis.cc:2706
+msgid "Pre-fade listen (PFL)"
+msgstr "前置淡化试听(PFL)"
+
+#: route_ui.cc:140
+msgid "Mute this track"
+msgstr "静音此音轨"
+
+#: route_ui.cc:144
+msgid "Mute other (non-soloed) tracks"
+msgstr "静音其它(非独奏)音轨"
+
+#: route_ui.cc:150
+msgid "Enable recording on this track"
+msgstr "在此音轨启用录制"
+
+#: route_ui.cc:158
+msgid "make mixer strips show sends to this bus"
+msgstr "让混音器栏显示发送到该总线"
+
+#: route_ui.cc:163
+msgid "Monitor input"
+msgstr "监控输入"
+
+#: route_ui.cc:169
+msgid "Monitor playback"
+msgstr "监控回放"
+
+#: route_ui.cc:676
+msgid "Not connected to AudioEngine - cannot engage record"
+msgstr "未连接到音频引擎——无法从事录制"
+
+#: route_ui.cc:875
+msgid "Step Entry"
+msgstr "步进入口"
+
+#: route_ui.cc:948
+msgid "Assign all tracks (prefader)"
+msgstr "指定所有音轨(前置淡化)"
+
+#: route_ui.cc:952
+msgid "Assign all tracks and buses (prefader)"
+msgstr "指定所有音轨和总线(前置淡化)"
+
+#: route_ui.cc:956
+msgid "Assign all tracks (postfader)"
+msgstr "指定所有音轨(后置淡化)"
+
+#: route_ui.cc:960
+msgid "Assign all tracks and buses (postfader)"
+msgstr "指定所有音轨和总线(后置淡化)"
+
+#: route_ui.cc:964
+msgid "Assign selected tracks (prefader)"
+msgstr "指定已选中的音轨(前置淡化)"
+
+#: route_ui.cc:968
+msgid "Assign selected tracks and buses (prefader)"
+msgstr "指定已选中的音轨和总线(前置淡化)"
+
+#: route_ui.cc:971
+msgid "Assign selected tracks (postfader)"
+msgstr "指定已选中的音轨(后置淡化)"
+
+#: route_ui.cc:975
+msgid "Assign selected tracks and buses (postfader)"
+msgstr "指定已选中的音轨和总线(后置淡化)"
+
+#: route_ui.cc:978
+msgid "Copy track/bus gains to sends"
+msgstr "复制音轨/总线增益到发送"
+
+#: route_ui.cc:979
+msgid "Set sends gain to -inf"
+msgstr "设置发送增益到 -inf"
+
+#: route_ui.cc:980
+msgid "Set sends gain to 0dB"
+msgstr "设置发送增益到 0dB"
+
+#: route_ui.cc:1300
+msgid "Solo Isolate"
+msgstr "独奏隔离"
+
+#: route_ui.cc:1307
+msgid "Solo Safe"
+msgstr "独奏安全"
+
+#: route_ui.cc:1329
+msgid "Pre Fader Sends"
+msgstr "前置淡化发送"
+
+#: route_ui.cc:1335
+msgid "Post Fader Sends"
+msgstr "后置淡化发送"
+
+#: route_ui.cc:1341
+msgid "Control Outs"
+msgstr "控制输出"
+
+#: route_ui.cc:1347
+msgid "Main Outs"
+msgstr "主要输出"
+
+#: route_ui.cc:1479
+msgid "Color Selection"
+msgstr "颜色已选择部分"
+
+#: route_ui.cc:1564
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"\n"
+"You may also lose the playlist used by this track.\n"
+"\n"
+"(This action cannot be undone, and the session file will be overwritten)"
+msgstr ""
+"您是否真的要移除音轨 \"%1\"?\n"
+"\n"
+"您也可能会失去使用此音轨使用的播放列表。\n"
+"\n"
+"(此操作不可撤销,而且此会话文件将会被重写覆盖)"
+
+#: route_ui.cc:1566
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"\n"
+"(This action cannot be undone, and the session file will be overwritten)"
+msgstr ""
+"您是否真的要移除总线\"%1\" ?\n"
+"\n"
+"(此操作不可撤销,而且此会话文件将会被重写覆盖)"
+
+#: route_ui.cc:1574
+msgid "Remove track"
+msgstr "移除音轨"
+
+#: route_ui.cc:1576
+msgid "Remove bus"
+msgstr "移除总线"
+
+#: route_ui.cc:1604
+msgid ""
+"The use of colons (':') is discouraged in track and bus names.\n"
+"Do you want to use this new name?"
+msgstr ""
+"建议不要在音轨和总线名称中使用冒号(“ : ”)。\n"
+"您是否确定使用这个新名称?"
+
+#: route_ui.cc:1608
+msgid "Use the new name"
+msgstr "使用新名称"
+
+#: route_ui.cc:1609
+msgid "Re-edit the name"
+msgstr "重新编辑名称"
+
+#: route_ui.cc:1622
+msgid "Rename Track"
+msgstr "重命名音轨"
+
+#: route_ui.cc:1624
+msgid "Rename Bus"
+msgstr "重命名总线"
+
+#: route_ui.cc:1692
+msgid ": comment editor"
+msgstr ":注释编辑器"
+
+#: route_ui.cc:1858
+msgid " latency"
+msgstr "延迟"
+
+#: route_ui.cc:1871
+msgid "Cannot create route template directory %1"
+msgstr "无法创建路由模板目录 %1"
+
+#: route_ui.cc:1877
+msgid "Save As Template"
+msgstr "另存为模板"
+
+#: route_ui.cc:1878
+msgid "Template name:"
+msgstr "模板名称:"
+
+#: route_ui.cc:1959
+msgid "Remote Control ID"
+msgstr "移除控制 ID"
+
+#: route_ui.cc:1969
+msgid "Remote control ID:"
+msgstr "移除控制 ID:"
+
+#: route_ui.cc:1983
+msgid ""
+"The remote control ID of %1 is: %2\n"
+"\n"
+"\n"
+"The remote control ID of %3 cannot be changed."
+msgstr ""
+" %1 的远程控制 ID 是:%2\n"
+"\n"
+"\n"
+"%3 的远程控制 ID 无法改变。"
+
+#: route_ui.cc:1987
+msgid "the master bus"
+msgstr "主控总线"
+
+#: route_ui.cc:1987
+msgid "the monitor bus"
+msgstr "监控总线"
+
+#: route_ui.cc:1989
+msgid ""
+"The remote control ID of %5 is: %2\n"
+"\n"
+"\n"
+"Remote Control IDs are currently determined by track/bus ordering in %6.\n"
+"\n"
+"%3Use the User Interaction tab of the Preferences window if you want to change this"
+"%4"
+msgstr ""
+"%5 的远程控制 ID 是:%2\n"
+"\n"
+"\n"
+"远程控制 IDs 是由当前音轨/总线在 %6 里的排序所决定的。\n"
+"\n"
+"如果您想改变 %4,%3 使用首选项窗口的用户交互选项卡"
+
+#: route_ui.cc:2046
+msgid ""
+"Left-click to invert (phase reverse) channel %1 of this track.  Right-click to "
+"show menu."
+msgstr "左键点击反转(相位反转)该音轨的声道 %1 。右键点击显示菜单。"
+
+#: route_ui.cc:2048
+msgid "Click to show a menu of channels for inversion (phase reverse)"
+msgstr "点击显示声道反转(相位反转)菜单"
+
+#: search_path_option.cc:35
+msgid "Select folder to search for media"
+msgstr "选择目录以便搜索媒体"
+
+#: search_path_option.cc:44
+msgid "Click to add a new location"
+msgstr "点击添加一个新位置"
+
+#: search_path_option.cc:51
+msgid "the session folder"
+msgstr "会话文件夹"
+
+#: send_ui.cc:134
+msgid "Send "
+msgstr "发送"
+
+#: session_dialog.cc:61
+msgid "Session Setup"
+msgstr "发送设置"
+
+#: session_dialog.cc:66
+msgid "Advanced options ..."
+msgstr "高级选项…"
+
+#: session_dialog.cc:263
+msgid "New Session"
+msgstr "新建会话"
+
+#: session_dialog.cc:301
+msgid "Check the website for more..."
+msgstr "查询网站以得到更多…"
+
+#: session_dialog.cc:304
+msgid "Click to open the program website in your web browser"
+msgstr "点击以便在您的网页浏览器打开程序网站"
+
+#: session_dialog.cc:324
+msgid "Sample Rate"
+msgstr "采样率"
+
+#: session_dialog.cc:325
+msgid "Disk Format"
+msgstr "硬盘格式化"
+
+#: session_dialog.cc:343
+msgid "Select session file"
+msgstr "选择会话文件"
+
+#: session_dialog.cc:358
+msgid "Other Sessions"
+msgstr "其它会话"
+
+#: session_dialog.cc:384
+msgid "Open"
+msgstr "打开"
+
+#: session_dialog.cc:451
+msgid "Session name:"
+msgstr "会话名称:"
+
+#: session_dialog.cc:473
+msgid "Create session folder in:"
+msgstr "创建会话文件夹在:"
+
+#: session_dialog.cc:496
+msgid "Select folder for session"
+msgstr "为会话选择文件夹"
+
+#: session_dialog.cc:525
+msgid "Use this template"
+msgstr "使用此模板"
+
+#: session_dialog.cc:528
+msgid "no template"
+msgstr "没有模板"
+
+#: session_dialog.cc:663 session_dialog.cc:699
+msgid "32 bit float"
+msgstr "32 位浮点"
+
+#: session_dialog.cc:666 session_dialog.cc:702
+msgid "24 bit"
+msgstr "24 位"
+
+#: session_dialog.cc:669 session_dialog.cc:705
+msgid "16 bit"
+msgstr "16 位"
+
+#: session_dialog.cc:747 session_dialog.cc:748 session_dialog.cc:749
+msgid "channels"
+msgstr "声道"
+
+#: session_dialog.cc:763
+msgid "<b>Busses</b>"
+msgstr "<b>总线</b>"
+
+#: session_dialog.cc:764
+msgid "<b>Inputs</b>"
+msgstr "<b>输入</b>"
+
+#: session_dialog.cc:765
+msgid "<b>Outputs</b>"
+msgstr "<b>输出</b>"
+
+#: session_dialog.cc:773
+msgid "Create master bus"
+msgstr "创建主控总线"
+
+#: session_dialog.cc:783
+msgid "Automatically connect to physical inputs"
+msgstr "自动连接到物理输入"
+
+#: session_dialog.cc:790 session_dialog.cc:849
+msgid "Use only"
+msgstr "仅使用"
+
+#: session_dialog.cc:843
+msgid "Automatically connect outputs"
+msgstr "自动连接到输出"
+
+#: session_dialog.cc:865
+msgid "... to master bus"
+msgstr "…到主控总线"
+
+#: session_dialog.cc:875
+msgid "... to physical outputs"
+msgstr "…到物理输出"
+
+#: session_import_dialog.cc:65
+msgid "Import from Session"
+msgstr "从会话导入"
+
+#: session_import_dialog.cc:74
+msgid "Elements"
+msgstr "元素"
+
+#: session_import_dialog.cc:111
+msgid "Cannot load XML for session from %1"
+msgstr "无法从 %1 为会话载入 XML"
+
+#: session_import_dialog.cc:128 session_import_dialog.cc:212
+msgid "Some elements had errors in them. Please see the log for details"
+msgstr "一些元素出错,详情请参阅日志文件"
+
+#: session_import_dialog.cc:164
+msgid "Import from session"
+msgstr "从会话导入"
+
+#: session_import_dialog.cc:228
+msgid "This will select all elements of this type!"
+msgstr "这将选择此类型的所有元素!"
+
+#: session_metadata_dialog.cc:285
+msgid "EAN Check digit OK"
+msgstr "EAN 校验数位正常"
+
+#: session_metadata_dialog.cc:289
+msgid "EAN Check digit error"
+msgstr "EAN 校验数位出错"
+
+#: session_metadata_dialog.cc:289
+msgid "expected"
+msgstr "期望"
+
+#: session_metadata_dialog.cc:294
+msgid "EAN Length error"
+msgstr "EAN 长度错误"
+
+#: session_metadata_dialog.cc:423
+msgid "Field"
+msgstr "字段"
+
+#: session_metadata_dialog.cc:427
+msgid "Values (current value on top)"
+msgstr "数值(当前数值位于顶部)"
+
+#: session_metadata_dialog.cc:641
+msgid "User"
+msgstr "用户"
+
+#: session_metadata_dialog.cc:649
+msgid "Email"
+msgstr "电子邮件"
+
+#: session_metadata_dialog.cc:652
+msgid "Web"
+msgstr "网站"
+
+#: session_metadata_dialog.cc:655
+msgid "Organization"
+msgstr "组织"
+
+#: session_metadata_dialog.cc:658
+msgid "Country"
+msgstr "国家"
+
+#: session_metadata_dialog.cc:672
+msgid "Title"
+msgstr "标题"
+
+#: session_metadata_dialog.cc:675
+msgid "Track Number"
+msgstr "音轨序号"
+
+#: session_metadata_dialog.cc:678
+msgid "Subtitle"
+msgstr "副标题"
+
+#: session_metadata_dialog.cc:681
+msgid "Grouping"
+msgstr "组合"
+
+#: session_metadata_dialog.cc:684
+msgid "Artist"
+msgstr "艺术家"
+
+#: session_metadata_dialog.cc:687
+msgid "Genre"
+msgstr "流派"
+
+#: session_metadata_dialog.cc:690
+msgid "Comment"
+msgstr "注释"
+
+#: session_metadata_dialog.cc:693
+msgid "Copyright"
+msgstr "版权"
+
+#: session_metadata_dialog.cc:701 session_metadata_dialog.cc:706
+msgid "Album"
+msgstr "专辑"
+
+#: session_metadata_dialog.cc:709
+msgid "Year"
+msgstr "年份"
+
+#: session_metadata_dialog.cc:712
+msgid "Album Artist"
+msgstr "专辑艺术家"
+
+#: session_metadata_dialog.cc:715
+msgid "Total Tracks"
+msgstr "音轨总数"
+
+#: session_metadata_dialog.cc:718
+msgid "Disc Subtitle"
+msgstr "光盘副标题"
+
+#: session_metadata_dialog.cc:721
+msgid "Disc Number"
+msgstr "光盘编号"
+
+#: session_metadata_dialog.cc:724
+msgid "Total Discs"
+msgstr "光盘总数"
+
+#: session_metadata_dialog.cc:727
+msgid "Compilation"
+msgstr "编纂"
+
+#: session_metadata_dialog.cc:730
+msgid "ISRC"
+msgstr "ISRC 国际标准音像制品编码"
+
+#: session_metadata_dialog.cc:733
+msgid "EAN barcode"
+msgstr "EAN 条形码"
+
+#: session_metadata_dialog.cc:746
+msgid "People"
+msgstr "民族"
+
+#: session_metadata_dialog.cc:751
+msgid "Lyricist"
+msgstr "作词"
+
+#: session_metadata_dialog.cc:754
+msgid "Composer"
+msgstr "作曲家"
+
+#: session_metadata_dialog.cc:757
+msgid "Conductor"
+msgstr "指挥家"
+
+#: session_metadata_dialog.cc:760
+msgid "Remixer"
+msgstr "混音师"
+
+#: session_metadata_dialog.cc:763
+msgid "Arranger"
+msgstr "编曲者"
+
+#: session_metadata_dialog.cc:766
+msgid "Engineer"
+msgstr "工程师"
+
+#: session_metadata_dialog.cc:769
+msgid "Producer"
+msgstr "制片人"
+
+#: session_metadata_dialog.cc:772
+msgid "DJ Mixer"
+msgstr "DJ 混音器"
+
+#: session_metadata_dialog.cc:775
+msgid "Metadata|Mixer"
+msgstr "元数据|混音器"
+
+#: session_metadata_dialog.cc:783
+msgid "School"
+msgstr "院校"
+
+#: session_metadata_dialog.cc:788
+msgid "Instructor"
+msgstr "指导员"
+
+#: session_metadata_dialog.cc:791
+msgid "Course"
+msgstr "过程"
+
+#: session_metadata_dialog.cc:799
+msgid "Edit Session Metadata"
+msgstr "标记会话元数据"
+
+#: session_metadata_dialog.cc:830
+msgid "Import session metadata"
+msgstr "导入会话元数据"
+
+#: session_metadata_dialog.cc:851
+msgid "Choose session to import metadata from"
+msgstr "选择导入元数据的来源会话"
+
+#: session_metadata_dialog.cc:889
+msgid "This session file could not be read!"
+msgstr "此会话文件无法读取!"
+
+#: session_metadata_dialog.cc:899
+msgid ""
+"The session file didn't contain metadata!\n"
+"Maybe this is an old session format?"
+msgstr ""
+"此会话文件不包含元数据!\n"
+"也许这是一个旧的会话格式?"
+
+#: session_metadata_dialog.cc:918
+msgid "Import all from:"
+msgstr "导入所有从:"
+
+#: session_option_editor.cc:32
+msgid "Session Properties"
+msgstr "会话属性 "
+
+#: session_option_editor.cc:41
+msgid "Timecode Settings"
+msgstr "时间码设置"
+
+#: session_option_editor.cc:45
+msgid "Timecode frames-per-second"
+msgstr "时间码帧数每秒"
+
+#: session_option_editor.cc:50
+msgid "23.976"
+msgstr ""
+
+#: session_option_editor.cc:51
+msgid "24"
+msgstr ""
+
+#: session_option_editor.cc:52
+msgid "24.975"
+msgstr ""
+
+#: session_option_editor.cc:53
+msgid "25"
+msgstr ""
+
+#: session_option_editor.cc:54
+msgid "29.97"
+msgstr ""
+
+#: session_option_editor.cc:55
+msgid "29.97 drop"
+msgstr "29.97 丢帧"
+
+#: session_option_editor.cc:56
+msgid "30"
+msgstr ""
+
+#: session_option_editor.cc:57
+msgid "30 drop"
+msgstr "30 丢帧"
+
+#: session_option_editor.cc:58
+msgid "59.94"
+msgstr ""
+
+#: session_option_editor.cc:59
+msgid "60"
+msgstr ""
+
+#: session_option_editor.cc:65
+msgid "Pull-up / pull-down"
+msgstr "上拉 / 下拉"
+
+#: session_option_editor.cc:70
+msgid "4.1667 + 0.1%"
+msgstr ""
+
+#: session_option_editor.cc:71
+msgid "4.1667"
+msgstr ""
+
+#: session_option_editor.cc:72
+msgid "4.1667 - 0.1%"
+msgstr ""
+
+#: session_option_editor.cc:73
+msgid "0.1"
+msgstr ""
+
+#: session_option_editor.cc:74
+msgid "none"
+msgstr "æ— "
+
+#: session_option_editor.cc:75
+msgid "-0.1"
+msgstr ""
+
+#: session_option_editor.cc:76
+msgid "-4.1667 + 0.1%"
+msgstr ""
+
+#: session_option_editor.cc:77
+msgid "-4.1667"
+msgstr ""
+
+#: session_option_editor.cc:78
+msgid "-4.1667 - 0.1%"
+msgstr ""
+
+#: session_option_editor.cc:84
+msgid ""
+"Use Video File's FPS Instead of Timecode Value for Timeline and Video Monitor."
+msgstr "为时间线和视频监控使用视频文件的 FPS 替代时间码数值。"
+
+#: session_option_editor.cc:91
+msgid ""
+"Apply Pull-Up/Down to Video Timeline and Video Monitor (Unless using JACK-sync)."
+msgstr "应用上拉/下拉到视频时间线和视频监控(除非使用 JACK-同步)"
+
+#: session_option_editor.cc:96
+msgid "Ext Timecode Offsets"
+msgstr "外部时间码偏移"
+
+#: session_option_editor.cc:100
+msgid "Slave Timecode offset"
+msgstr "从属时间码偏移"
+
+#: session_option_editor.cc:107
+msgid "The specified offset is added to the received timecode (MTC or LTC)."
+msgstr "指定的偏移已被添加到已接收的时间码(MTC 或 LTC)。"
+
+#: session_option_editor.cc:113
+msgid "Timecode Generator offset"
+msgstr "时间码生成器偏移"
+
+#: session_option_editor.cc:120
+msgid "Specify an offset which is added to the generated timecode (so far only LTC)."
+msgstr "指定一个已被添加到通用时间码的偏移(迄今为止仅有 LTC)。"
+
+#: session_option_editor.cc:124
+msgid "JACK Transport/Time Settings"
+msgstr "JACK 播送/时间设置"
+
+#: session_option_editor.cc:128
+msgid "%1 is JACK Time Master (provides Bar|Beat|Tick and other information to JACK)"
+msgstr "%1 是 JACK 时间主控(提供小节|拍子|识别声以及其它信息给 JACK)"
+
+#: session_option_editor.cc:136
+msgid "destructive-xfade-seconds"
+msgstr "销毁前置后置淡化秒数"
+
+#: session_option_editor.cc:137
+msgid "Destructive crossfade length"
+msgstr "销毁交叉淡化长度"
+
+#: session_option_editor.cc:146
+msgid "Region fades active"
+msgstr "区域淡化激活"
+
+#: session_option_editor.cc:153
+msgid "Region fades visible"
+msgstr "区域淡化可见"
+
+#: session_option_editor.cc:160 session_option_editor.cc:173
+#: session_option_editor.cc:187
+msgid "Media"
+msgstr "媒体"
+
+#: session_option_editor.cc:160
+msgid "Audio file format"
+msgstr "音频文件格式"
+
+#: session_option_editor.cc:164
+msgid "Sample format"
+msgstr "采样格式"
+
+#: session_option_editor.cc:169
+msgid "32-bit floating point"
+msgstr "32 位浮点"
+
+#: session_option_editor.cc:170
+msgid "24-bit integer"
+msgstr "24 位整数"
+
+#: session_option_editor.cc:171
+msgid "16-bit integer"
+msgstr "16 位整数"
+
+#: session_option_editor.cc:177
+msgid "File type"
+msgstr "文件类型"
+
+#: session_option_editor.cc:182
+msgid "Broadcast WAVE"
+msgstr "广播 WAVE"
+
+#: session_option_editor.cc:183
+msgid "WAVE"
+msgstr ""
+
+#: session_option_editor.cc:184
+msgid "WAVE-64"
+msgstr ""
+
+#: session_option_editor.cc:189
+msgid "File locations"
+msgstr "文件位置"
+
+#: session_option_editor.cc:191
+msgid "Search for audio files in:"
+msgstr "搜索音频文件于:"
+
+#: session_option_editor.cc:197
+msgid "Search for MIDI files in:"
+msgstr "搜索 MIDI 文件于:"
+
+#: session_option_editor.cc:206 session_option_editor.cc:218
+#: session_option_editor.cc:228 session_option_editor.cc:239
+msgid "Filenames"
+msgstr "文件名"
+
+#: session_option_editor.cc:206
+msgid "File Naming"
+msgstr "文件命名"
+
+#: session_option_editor.cc:212
+msgid "Prefix Track number"
+msgstr "音轨编号前缀"
+
+#: session_option_editor.cc:217
+msgid "Adds the current track number to the beginning of the recorded file name."
+msgstr "添加当前音轨编号到已录制文件名的前端。"
+
+#: session_option_editor.cc:222
+msgid "Prefix Take Name"
+msgstr "磁带名称前缀"
+
+#: session_option_editor.cc:227
+msgid "Adds the Take Name to the beginning of the recorded file name."
+msgstr "添加磁带名称到已录制文件名的前端。"
+
+#: session_option_editor.cc:232
+msgid "Take Name"
+msgstr "磁带名称"
+
+#: session_option_editor.cc:245
+msgid "Track Input Monitoring automatically follows transport state (\"auto-input\")"
+msgstr "音轨输入监控自动化跟随播送状态(“自动输入”)"
+
+#: session_option_editor.cc:252
+msgid "Use monitor section in this session"
+msgstr "在该会话中使用的监控面"
+
+#: session_option_editor.cc:257 session_option_editor.cc:259
+#: session_option_editor.cc:266 session_option_editor.cc:273
+#: session_option_editor.cc:280 session_option_editor.cc:282
+#: session_option_editor.cc:289 session_option_editor.cc:296
+#: session_option_editor.cc:303 session_option_editor.cc:310
+#: session_option_editor.cc:312
+msgid "Meterbridge"
+msgstr "节拍桥接"
+
+#: session_option_editor.cc:257
+msgid "Route Display"
+msgstr "路由显示"
+
+#: session_option_editor.cc:261
+msgid "Show Midi Tracks"
+msgstr "显示 MIDI 音轨"
+
+#: session_option_editor.cc:268
+msgid "Show Busses"
+msgstr "显示总线"
+
+#: session_option_editor.cc:275
+msgid "Include Master Bus"
+msgstr "包括主控总线"
+
+#: session_option_editor.cc:280
+msgid "Button Area"
+msgstr "按钮区域"
+
+#: session_option_editor.cc:284
+msgid "Rec-enable Button"
+msgstr "可录制按钮"
+
+#: session_option_editor.cc:291
+msgid "Mute Button"
+msgstr "静音按钮"
+
+#: session_option_editor.cc:298
+msgid "Solo Button"
+msgstr "独奏按钮"
+
+#: session_option_editor.cc:305
+msgid "Monitor Buttons"
+msgstr "监控按钮"
+
+#: session_option_editor.cc:310
+msgid "Name Labels"
+msgstr "名称标签"
+
+#: session_option_editor.cc:314
+msgid "Track Name"
+msgstr "音轨名称"
+
+#: session_option_editor.cc:325
+msgid "MIDI region copies are independent"
+msgstr "MIDI 区域拷贝不受约束"
+
+#: session_option_editor.cc:332
+msgid ""
+"Policy for handling overlapping notes\n"
+" on the same MIDI channel"
+msgstr "处理位于同一个 MIDI 声道上的重叠音符的策略"
+
+#: session_option_editor.cc:337
+msgid "never allow them"
+msgstr "从不允许它们"
+
+#: session_option_editor.cc:338
+msgid "don't do anything in particular"
+msgstr "不做任何特殊处理"
+
+#: session_option_editor.cc:339
+msgid "replace any overlapped existing note"
+msgstr "替换所有已存在的重叠音符"
+
+#: session_option_editor.cc:340
+msgid "shorten the overlapped existing note"
+msgstr "缩短已存在的重叠音符"
+
+#: session_option_editor.cc:341
+msgid "shorten the overlapping new note"
+msgstr "缩短已存在的新音符"
+
+#: session_option_editor.cc:342
+msgid "replace both overlapping notes with a single note"
+msgstr "把重叠的音符替换为一个单个音符"
+
+#: session_option_editor.cc:346
+msgid "Glue to bars and beats"
+msgstr "粘连到小节和拍子"
+
+#: session_option_editor.cc:350
+msgid "Glue new markers to bars and beats"
+msgstr "粘连新的标记到小节和拍子"
+
+#: session_option_editor.cc:357
+msgid "Glue new regions to bars and beats"
+msgstr "粘连新的区域到小节和拍子"
+
+#: session_option_editor.cc:362
+msgid "Defaults"
+msgstr "默认"
+
+#: session_option_editor.cc:364
+msgid "Use these settings as defaults"
+msgstr "使用这些设置作为默认"
+
+#: sfdb_ui.cc:90 sfdb_ui.cc:110 sfdb_ui.cc:119
+msgid "as new tracks"
+msgstr "作为新的音轨"
+
+#: sfdb_ui.cc:92 sfdb_ui.cc:112
+msgid "to selected tracks"
+msgstr "到已选中的音轨"
+
+#: sfdb_ui.cc:94 sfdb_ui.cc:114
+msgid "to region list"
+msgstr "到区域列表"
+
+#: sfdb_ui.cc:96 sfdb_ui.cc:116
+msgid "as new tape tracks"
+msgstr "作为新的磁带音轨"
+
+#: sfdb_ui.cc:100
+msgid "programming error: unknown import mode string %1"
+msgstr "程序错误:未知的导入模式字符串 %1"
+
+#: sfdb_ui.cc:127
+msgid "Auto-play"
+msgstr "自动播放"
+
+#: sfdb_ui.cc:135 sfdb_ui.cc:324
+msgid "<b>Sound File Information</b>"
+msgstr "<b>声音文件信息</b>"
+
+#: sfdb_ui.cc:147
+msgid "Timestamp:"
+msgstr "时间戳:"
+
+#: sfdb_ui.cc:149
+msgid "Format:"
+msgstr "格式:"
+
+#: sfdb_ui.cc:188 sfdb_ui.cc:653
+msgid "Tags:"
+msgstr "标签:"
+
+#: sfdb_ui.cc:293 sfdb_ui.cc:409
+msgid "Could not read file: %1 (%2)."
+msgstr "无法读取文件: %1 (%2)."
+
+#: sfdb_ui.cc:297
+msgid "<b>Midi File Information</b>"
+msgstr "<b>Midi 文件信息</b>"
+
+#: sfdb_ui.cc:458
+msgid "Could not access soundfile: "
+msgstr "无法访问声音文件: "
+
+#: sfdb_ui.cc:530
+msgid "SoundFileBox: Could not tokenize string: "
+msgstr "声音文件盒:无法令牌化字符串: "
+
+#: sfdb_ui.cc:550 sfdb_ui.cc:552
+msgid "Search"
+msgstr "搜索"
+
+#: sfdb_ui.cc:576
+msgid "Audio and MIDI files"
+msgstr "音频和 MIDI 文件"
+
+#: sfdb_ui.cc:579
+msgid "Audio files"
+msgstr "音频文件"
+
+#: sfdb_ui.cc:582
+msgid "MIDI files"
+msgstr "MIDI 文件"
+
+#: sfdb_ui.cc:585 add_video_dialog.cc:123
+msgid "All files"
+msgstr "所有文件"
+
+#: sfdb_ui.cc:604 add_video_dialog.cc:246
+msgid "Browse Files"
+msgstr "浏览文件"
+
+#: sfdb_ui.cc:633
+msgid "Paths"
+msgstr "路径"
+
+#: sfdb_ui.cc:642
+msgid "Search Tags"
+msgstr "搜索标签"
+
+#: sfdb_ui.cc:658
+msgid "Sort:"
+msgstr "排序:"
+
+#: sfdb_ui.cc:666
+msgid "Longest"
+msgstr "最长"
+
+#: sfdb_ui.cc:667
+msgid "Shortest"
+msgstr "最短"
+
+#: sfdb_ui.cc:668
+msgid "Newest"
+msgstr "最新"
+
+#: sfdb_ui.cc:669
+msgid "Oldest"
+msgstr "最旧"
+
+#: sfdb_ui.cc:670
+msgid "Most downloaded"
+msgstr "最多下载"
+
+#: sfdb_ui.cc:671
+msgid "Least downloaded"
+msgstr "最新下载"
+
+#: sfdb_ui.cc:672
+msgid "Highest rated"
+msgstr "最高评价"
+
+#: sfdb_ui.cc:673
+msgid "Lowest rated"
+msgstr "最低评价"
+
+#: sfdb_ui.cc:678
+msgid "More"
+msgstr "更多"
+
+#: sfdb_ui.cc:682
+msgid "Similar"
+msgstr "类似的"
+
+#: sfdb_ui.cc:694
+msgid "ID"
+msgstr ""
+
+#: sfdb_ui.cc:695 add_video_dialog.cc:83
+msgid "Filename"
+msgstr "文件名"
+
+#: sfdb_ui.cc:697
+msgid "Duration"
+msgstr "音长"
+
+#: sfdb_ui.cc:698
+msgid "Size"
+msgstr "尺寸"
+
+#: sfdb_ui.cc:699
+msgid "Samplerate"
+msgstr "采样率"
+
+#: sfdb_ui.cc:700
+msgid "License"
+msgstr "许可证"
+
+#: sfdb_ui.cc:718
+msgid "Search Freesound"
+msgstr "搜索自由声音"
+
+#: sfdb_ui.cc:738
+msgid "Press to import selected files and close this window"
+msgstr "按下插入已选中的文件并且关闭此窗口"
+
+#: sfdb_ui.cc:739
+msgid "Press to import selected files and leave this window open"
+msgstr "按下插入已选中的文件并且保留此窗口"
+
+#: sfdb_ui.cc:740
+msgid "Press to close this window without importing any files"
+msgstr "按下关闭此窗口并且不插入任何文件"
+
+#: sfdb_ui.cc:936
+msgid "SoundFileBrowser: Could not tokenize string: "
+msgstr "声音文件浏览器:无法令牌化字符串: "
+
+#: sfdb_ui.cc:1136
+msgid "%1 more page of 100 results available"
+msgid_plural "%1 more pages of 100 results available"
+msgstr[0] "%1 有 100 多页结果可用"
+
+#: sfdb_ui.cc:1141
+msgid "No more results available"
+msgstr "无更多结果可用"
+
+#: sfdb_ui.cc:1205
+msgid "B"
+msgstr ""
+
+#: sfdb_ui.cc:1207
+msgid "kB"
+msgstr ""
+
+#: sfdb_ui.cc:1209 sfdb_ui.cc:1211
+msgid "MB"
+msgstr ""
+
+#: sfdb_ui.cc:1213
+msgid "GB"
+msgstr ""
+
+#: sfdb_ui.cc:1425 sfdb_ui.cc:1738 sfdb_ui.cc:1801 sfdb_ui.cc:1819
+msgid "one track per file"
+msgstr "每个文件一个音轨"
+
+#: sfdb_ui.cc:1428 sfdb_ui.cc:1802 sfdb_ui.cc:1820
+msgid "one track per channel"
+msgstr "每个声道一个音轨"
+
+#: sfdb_ui.cc:1436 sfdb_ui.cc:1804 sfdb_ui.cc:1821
+msgid "sequence files"
+msgstr "序列文件"
+
+#: sfdb_ui.cc:1439 sfdb_ui.cc:1809
+msgid "all files in one track"
+msgstr "所有文件在一个音轨上"
+
+#: sfdb_ui.cc:1440 sfdb_ui.cc:1803
+msgid "merge files"
+msgstr "合并文件"
+
+#: sfdb_ui.cc:1446 sfdb_ui.cc:1806
+msgid "one region per file"
+msgstr "每个文件一个区域"
+
+#: sfdb_ui.cc:1449 sfdb_ui.cc:1807
+msgid "one region per channel"
+msgstr "每个声道一个区域"
+
+#: sfdb_ui.cc:1454 sfdb_ui.cc:1808 sfdb_ui.cc:1822
+msgid "all files in one region"
+msgstr "所有文件在一个区域里"
+
+#: sfdb_ui.cc:1521
+msgid ""
+"One or more of the selected files\n"
+"cannot be used by %1"
+msgstr ""
+"一个或多个已选中的文件\n"
+"不能被用于 %1"
+
+#: sfdb_ui.cc:1665
+msgid "Copy files to session"
+msgstr "复制文件到会话"
+
+#: sfdb_ui.cc:1682 sfdb_ui.cc:1859
+msgid "file timestamp"
+msgstr "文件时间戳"
+
+#: sfdb_ui.cc:1683 sfdb_ui.cc:1861
+msgid "edit point"
+msgstr "编辑点"
+
+#: sfdb_ui.cc:1684 sfdb_ui.cc:1863
+msgid "playhead"
+msgstr "指针"
+
+#: sfdb_ui.cc:1685
+msgid "session start"
+msgstr "会话起点"
+
+#: sfdb_ui.cc:1691
+msgid "<b>Add files as ...</b>"
+msgstr "<b>添加文件为…</b>"
+
+#: sfdb_ui.cc:1713
+msgid "<b>Insert at</b>"
+msgstr "<b>插入于</b>"
+
+#: sfdb_ui.cc:1726
+msgid "<b>Mapping</b>"
+msgstr "<b>映射</b>"
+
+#: sfdb_ui.cc:1744
+msgid "<b>Conversion quality</b>"
+msgstr "<b>转换质量</b>"
+
+#: sfdb_ui.cc:1756
+msgid "<b>Instrument</b>"
+msgstr "<b>乐器</b>"
+
+#: sfdb_ui.cc:1768 sfdb_ui.cc:1875
+msgid "Best"
+msgstr "最佳"
+
+#: sfdb_ui.cc:1769 sfdb_ui.cc:1877
+msgid "Good"
+msgstr "好"
+
+#: sfdb_ui.cc:1770 sfdb_ui.cc:1879
+msgid "Quick"
+msgstr "å¿«"
+
+#: sfdb_ui.cc:1772
+msgid "Fastest"
+msgstr "最快"
+
+#: shuttle_control.cc:56
+msgid "Shuttle speed control (Context-click for options)"
+msgstr "往复速度控制(右键点击查看更多选项)"
+
+#: shuttle_control.cc:174
+msgid "Percent"
+msgstr "百分比"
+
+#: shuttle_control.cc:182
+msgid "Units"
+msgstr "单位"
+
+#: shuttle_control.cc:188 shuttle_control.cc:609
+msgid "Sprung"
+msgstr "弹动"
+
+#: shuttle_control.cc:192 shuttle_control.cc:612
+msgid "Wheel"
+msgstr "轮转"
+
+#: shuttle_control.cc:226
+msgid "Maximum speed"
+msgstr "最大速度"
+
+#: shuttle_control.cc:568
+msgid "Playing"
+msgstr "播放中"
+
+#: shuttle_control.cc:583
+#, c-format
+msgid "<<< %+d semitones"
+msgstr "<<< %+d 半音"
+
+#: shuttle_control.cc:585
+#, c-format
+msgid ">>> %+d semitones"
+msgstr ">>> %+d 半音"
+
+#: shuttle_control.cc:590
+msgid "Stopped"
+msgstr "已停止"
+
+#: soundcloud_export_selector.cc:44
+msgid "User Email"
+msgstr "用户电子信箱"
+
+#: soundcloud_export_selector.cc:45
+msgid "Password"
+msgstr "密码"
+
+#: soundcloud_export_selector.cc:46
+msgid "Make files public"
+msgstr "文件公开"
+
+#: soundcloud_export_selector.cc:47
+msgid "Open uploaded files in browser"
+msgstr "在浏览器里打开已上传的文件"
+
+#: soundcloud_export_selector.cc:48
+msgid "Make files downloadable"
+msgstr "文件可下载"
+
+#: soundcloud_export_selector.cc:107
+msgid "%1: %2 of %3 bytes uploaded"
+msgstr "%1: %2 的 %3 字节已上传"
+
+#: splash.cc:73
+msgid "%1 loading ..."
+msgstr "%1 载入中…"
+
+#: speaker_dialog.cc:40
+msgid "Add Speaker"
+msgstr "添加扬声器"
+
+#: speaker_dialog.cc:41
+msgid "Remove Speaker"
+msgstr "移除扬声器"
+
+#: speaker_dialog.cc:63
+msgid "Azimuth:"
+msgstr "方位角:"
+
+#: startup.cc:67
+msgid ""
+"Use an external mixer or the hardware mixer of your audio interface.\n"
+"%1 will play NO role in monitoring"
+msgstr ""
+"使用一个外部混音器或您的音频接口硬件混音器。\n"
+"%1 将不会出现在监控中"
+
+#: startup.cc:69
+msgid "Ask %1 to play back material as it is being recorded"
+msgstr "当 %1 被录制时请求其回放材料"
+
+#: startup.cc:142
+msgid ""
+"<span size=\"larger\">%1 is a digital audio workstation. You can use it to record, "
+"edit and mix multi-track audio. You can produce your own CDs, mix video "
+"soundtracks, or experiment with new ideas about music and sound. \n"
+"\n"
+"There are a few things that need to be configured before you start using the "
+"program.</span> "
+msgstr ""
+"<span size=\"larger\">%1 是一个数字音频工作站。您可以用它录制、编辑并混合多声道音"
+"频。您可以创作自己的CD光盘、混合视频音轨、或者试验与音乐和声音有关的新想法。\n"
+"\n"
+"在您开始使用这个程序之前,需要完成一些配置。</span> "
+
+#: startup.cc:168
+msgid "Welcome to %1"
+msgstr "欢迎使用 %1"
+
+#: startup.cc:191
+msgid "Default folder for %1 sessions"
+msgstr "会话 %1 的默认文件夹"
+
+#: startup.cc:197
+msgid ""
+"Each project that you work on with %1 has its own folder.\n"
+"These can require a lot of disk space if you are recording audio.\n"
+"\n"
+"Where would you like new %1 sessions to be stored by default?\n"
+"\n"
+"<i>(You can put new sessions anywhere, this is just a default)</i>"
+msgstr ""
+"您在 %1 工作的每个项目都有它各自的文件夹。\n"
+"当您在录制音频时,可能需要大量的磁盘空间。\n"
+"\n"
+"您希望新的 %1 会话被默认存放在哪儿?\n"
+"\n"
+"<i>(您可以把新的会话存放在任何位置,这里只是默认文件夹)</i>"
+
+#: startup.cc:220
+msgid "Default folder for new sessions"
+msgstr "新会话的默认文件夹"
+
+#: startup.cc:241
+msgid ""
+"While recording instruments or vocals, you probably want to listen to the\n"
+"signal as well as record it. This is called \"monitoring\". There are\n"
+"different ways to do this depending on the equipment you have and the\n"
+"configuration of that equipment. The two most common are presented here.\n"
+"Please choose whichever one is right for your setup.\n"
+"\n"
+"<i>(You can change this preference at any time, via the Preferences dialog)</i>\n"
+"\n"
+"<i>If you do not understand what this is about, just accept the default.</i>"
+msgstr ""
+"当录制乐器或人声时,您可能希望在录制的同时听到信号。\n"
+"这被称为“监控”。\n"
+"有不同的方法可以做到这一点,这取决于您所拥有的设备以及这些设备的配置。\n"
+"这里有两个最常见的方式。\n"
+"请选择最适合您的设置的那一个。\n"
+"\n"
+"<i>(您可以在任何时候改变这个首选项,就在首选项对话框里)</i>\n"
+"\n"
+"<i>如果您不大了解这方面的信息,保持默认即可。</i>"
+
+#: startup.cc:262
+msgid "Monitoring Choices"
+msgstr "监控选择"
+
+#: startup.cc:285
+msgid "Use a Master bus directly"
+msgstr "直接使用主控总线"
+
+#: startup.cc:287
+msgid ""
+"Connect the Master bus directly to your hardware outputs. This is preferable for "
+"simple usage."
+msgstr "直接连接主控总线到您的硬件输出。这可能更简单易用。"
+
+#: startup.cc:296
+msgid "Use an additional Monitor bus"
+msgstr "使用一个额外的监控总线"
+
+#: startup.cc:299
+msgid ""
+"Use a Monitor bus between Master bus and hardware outputs for \n"
+"greater control in monitoring without affecting the mix."
+msgstr ""
+"在主控总线和硬件输入之间使用一个监控总线\n"
+"监控时可更好的控制,不会影响混音。"
+
+#: startup.cc:321
+msgid ""
+"<i>You can change this preference at any time via the Preferences dialog.\n"
+"You can also add or remove the monitor section to/from any session.</i>\n"
+"\n"
+"<i>If you do not understand what this is about, just accept the default.</i>"
+msgstr ""
+"<i>您可以在任何时候改变这个首选项,就在首选项对话框里。\n"
+"您也可以添加监控面到任何会话,或着从任何会话移除监控面。</i>\n"
+"\n"
+"<i>如果您不大了解这方面的信息,保持默认即可。</i>"
+
+#: startup.cc:332
+msgid "Monitor Section"
+msgstr "监控面"
+
+#: step_entry.cc:60
+msgid "Step Entry: %1"
+msgstr "步进入口:%1"
+
+#: step_entry.cc:65
+msgid ">beat"
+msgstr ">拍子"
+
+#: step_entry.cc:66
+msgid ">bar"
+msgstr ">小节"
+
+#: step_entry.cc:67
+msgid ">EP"
+msgstr ">采样"
+
+#: step_entry.cc:68
+msgid "sustain"
+msgstr "持续"
+
+#: step_entry.cc:69
+msgid "rest"
+msgstr "休止"
+
+#: step_entry.cc:70
+msgid "g-rest"
+msgstr "g-休止"
+
+#: step_entry.cc:71
+msgid "back"
+msgstr "后退"
+
+#: step_entry.cc:82 step_entry.cc:85
+msgid "+"
+msgstr ""
+
+#: step_entry.cc:191
+msgid "Set note length to a whole note"
+msgstr "设置音符长度为全音符"
+
+#: step_entry.cc:192
+msgid "Set note length to a half note"
+msgstr "设置音符长度为半音符"
+
+#: step_entry.cc:193
+msgid "Set note length to a quarter note"
+msgstr "设置音符长度为四分音符"
+
+#: step_entry.cc:194
+msgid "Set note length to a eighth note"
+msgstr "设置音符长度为八分音符"
+
+#: step_entry.cc:195
+msgid "Set note length to a sixteenth note"
+msgstr "设置音符长度为十六分音符"
+
+#: step_entry.cc:196
+msgid "Set note length to a thirty-second note"
+msgstr "设置音符长度为三十二分音符"
+
+#: step_entry.cc:197
+msgid "Set note length to a sixty-fourth note"
+msgstr "设置音符长度为六十四分音符"
+
+#: step_entry.cc:276
+msgid "Set volume (velocity) to pianississimo"
+msgstr "设置音量(力度)为最弱音"
+
+#: step_entry.cc:277
+msgid "Set volume (velocity) to pianissimo"
+msgstr "设置音量(力度)为极弱音"
+
+#: step_entry.cc:278
+msgid "Set volume (velocity) to piano"
+msgstr "设置音量(力度)为弱音"
+
+#: step_entry.cc:279
+msgid "Set volume (velocity) to mezzo-piano"
+msgstr "设置音量(力度)为中弱音"
+
+#: step_entry.cc:280
+msgid "Set volume (velocity) to mezzo-forte"
+msgstr "设置音量(力度)为中强音"
+
+#: step_entry.cc:281
+msgid "Set volume (velocity) to forte"
+msgstr "设置音量(力度)为强音"
+
+#: step_entry.cc:282
+msgid "Set volume (velocity) to fortissimo"
+msgstr "设置音量(力度)为极强音"
+
+#: step_entry.cc:283
+msgid "Set volume (velocity) to fortississimo"
+msgstr "设置音量(力度)为最强音"
+
+#: step_entry.cc:331
+msgid "Stack inserted notes to form a chord"
+msgstr "堆栈已插入的音符形成一个和弦"
+
+#: step_entry.cc:332
+msgid "Extend selected notes by note length"
+msgstr "通过音符长度延伸已选择的音符"
+
+#: step_entry.cc:333
+msgid "Use undotted note lengths"
+msgstr "使用不带点音符长度"
+
+#: step_entry.cc:334
+msgid "Use dotted (* 1.5) note lengths"
+msgstr "使用带点(*1.5)音符长度"
+
+#: step_entry.cc:335
+msgid "Use double-dotted (* 1.75) note lengths"
+msgstr "使用带双点(*1.75)音符长度"
+
+#: step_entry.cc:336
+msgid "Use triple-dotted (* 1.875) note lengths"
+msgstr "使用带三点(* 1.875)音符长度"
+
+#: step_entry.cc:337
+msgid "Insert a note-length's rest"
+msgstr "插入一个音符长度的休止符"
+
+#: step_entry.cc:338
+msgid "Insert a grid-unit's rest"
+msgstr "插入一个网格单位的休止符"
+
+#: step_entry.cc:339
+msgid "Insert a rest until the next beat"
+msgstr "插入一个休止符直到下一拍"
+
+#: step_entry.cc:340
+msgid "Insert a rest until the next bar"
+msgstr "插入一个休止符直到下一小节"
+
+#: step_entry.cc:341
+msgid "Insert a bank change message"
+msgstr "插入一个库变换信息"
+
+#: step_entry.cc:342
+msgid "Insert a program change message"
+msgstr "插入一个程式变换信息"
+
+#: step_entry.cc:343 step_entry.cc:700
+msgid "Move Insert Position Back by Note Length"
+msgstr "按音符长度向后移动插入位置"
+
+#: step_entry.cc:344 step_entry.cc:698
+msgid "Move Insert Position to Edit Point"
+msgstr "移动插入位置到编辑位置"
+
+#: step_entry.cc:401
+msgid "1/Note"
+msgstr "1/音符"
+
+#: step_entry.cc:415
+msgid "Octave"
+msgstr "八度"
+
+#: step_entry.cc:598
+msgid "Insert Note A"
+msgstr "插入音符A"
+
+#: step_entry.cc:599
+msgid "Insert Note A-sharp"
+msgstr "插入音符A#"
+
+#: step_entry.cc:600
+msgid "Insert Note B"
+msgstr "插入音符B"
+
+#: step_entry.cc:601
+msgid "Insert Note C"
+msgstr "插入音符C"
+
+#: step_entry.cc:602
+msgid "Insert Note C-sharp"
+msgstr "插入音符C#"
+
+#: step_entry.cc:603
+msgid "Insert Note D"
+msgstr "插入音符D"
+
+#: step_entry.cc:604
+msgid "Insert Note D-sharp"
+msgstr "插入音符D#"
+
+#: step_entry.cc:605
+msgid "Insert Note E"
+msgstr "插入音符E"
+
+#: step_entry.cc:606
+msgid "Insert Note F"
+msgstr "插入音符F"
+
+#: step_entry.cc:607
+msgid "Insert Note F-sharp"
+msgstr "插入音符F#"
+
+#: step_entry.cc:608
+msgid "Insert Note G"
+msgstr "插入音符G"
+
+#: step_entry.cc:609
+msgid "Insert Note G-sharp"
+msgstr "插入音符G#"
+
+#: step_entry.cc:611
+msgid "Insert a Note-length Rest"
+msgstr "插入一个全休止符"
+
+#: step_entry.cc:612
+msgid "Insert a Snap-length Rest"
+msgstr "插入一个吸附长度的休止符"
+
+#: step_entry.cc:614 step_entry.cc:615
+msgid "Move to next octave"
+msgstr "移动到下一个八度"
+
+#: step_entry.cc:617
+msgid "Move to Next Note Length"
+msgstr "移动到下一个音符长度"
+
+#: step_entry.cc:618
+msgid "Move to Previous Note Length"
+msgstr "移动到上一个音符长度"
+
+#: step_entry.cc:620
+msgid "Increase Note Length"
+msgstr "增加音符长度"
+
+#: step_entry.cc:621
+msgid "Decrease Note Length"
+msgstr "减少音符长度"
+
+#: step_entry.cc:623
+msgid "Move to Next Note Velocity"
+msgstr "移动到下一个音符力度"
+
+#: step_entry.cc:624
+msgid "Move to Previous Note Velocity"
+msgstr "移动到上一个音符力度"
+
+#: step_entry.cc:626
+msgid "Increase Note Velocity"
+msgstr "增加音符力度"
+
+#: step_entry.cc:627
+msgid "Decrease Note Velocity"
+msgstr "减少音符力度"
+
+#: step_entry.cc:629
+msgid "Switch to the 1st octave"
+msgstr "切换到第一个八度"
+
+#: step_entry.cc:630
+msgid "Switch to the 2nd octave"
+msgstr "切换到第二个八度"
+
+#: step_entry.cc:631
+msgid "Switch to the 3rd octave"
+msgstr "切换到第三个八度"
+
+#: step_entry.cc:632
+msgid "Switch to the 4th octave"
+msgstr "切换到第四个八度"
+
+#: step_entry.cc:633
+msgid "Switch to the 5th octave"
+msgstr "切换到第五个八度"
+
+#: step_entry.cc:634
+msgid "Switch to the 6th octave"
+msgstr "切换到第六个八度"
+
+#: step_entry.cc:635
+msgid "Switch to the 7th octave"
+msgstr "切换到第七个八度"
+
+#: step_entry.cc:636
+msgid "Switch to the 8th octave"
+msgstr "切换到第八个八度"
+
+#: step_entry.cc:637
+msgid "Switch to the 9th octave"
+msgstr "切换到第九个八度"
+
+#: step_entry.cc:638
+msgid "Switch to the 10th octave"
+msgstr "切换到第十个八度"
+
+#: step_entry.cc:639
+msgid "Switch to the 11th octave"
+msgstr "切换到第十一个八度"
+
+#: step_entry.cc:644
+msgid "Set Note Length to Whole"
+msgstr "设置为全音符"
+
+#: step_entry.cc:646
+msgid "Set Note Length to 1/2"
+msgstr "设置为二分音符"
+
+#: step_entry.cc:648
+msgid "Set Note Length to 1/3"
+msgstr "设置为三分音符"
+
+#: step_entry.cc:650
+msgid "Set Note Length to 1/4"
+msgstr "设置为四分音符"
+
+#: step_entry.cc:652
+msgid "Set Note Length to 1/8"
+msgstr "设置为八分音符"
+
+#: step_entry.cc:654
+msgid "Set Note Length to 1/16"
+msgstr "设置为十六分音符"
+
+#: step_entry.cc:656
+msgid "Set Note Length to 1/32"
+msgstr "设置为三十二分音符"
+
+#: step_entry.cc:658
+msgid "Set Note Length to 1/64"
+msgstr "设置为六十四分音符"
+
+#: step_entry.cc:663
+msgid "Set Note Velocity to Pianississimo"
+msgstr "设置音符力度为最弱音"
+
+#: step_entry.cc:665
+msgid "Set Note Velocity to Pianissimo"
+msgstr "设置音符力度为极弱音"
+
+#: step_entry.cc:667
+msgid "Set Note Velocity to Piano"
+msgstr "设置音符力度为弱音"
+
+#: step_entry.cc:669
+msgid "Set Note Velocity to Mezzo-Piano"
+msgstr "设置音符力度为中弱音"
+
+#: step_entry.cc:671
+msgid "Set Note Velocity to Mezzo-Forte"
+msgstr "设置音符力度为中强音"
+
+#: step_entry.cc:673
+msgid "Set Note Velocity to Forte"
+msgstr "设置音符力度为强音"
+
+#: step_entry.cc:675 step_entry.cc:677
+msgid "Set Note Velocity to Fortississimo"
+msgstr "设置音符力度为最强音"
+
+#: step_entry.cc:679
+msgid "Toggle Triple Notes"
+msgstr "切换三分音符"
+
+#: step_entry.cc:684
+msgid "No Dotted Notes"
+msgstr "无带点音符"
+
+#: step_entry.cc:686
+msgid "Toggled Dotted Notes"
+msgstr "切换带点音符"
+
+#: step_entry.cc:688
+msgid "Toggled Double-Dotted Notes"
+msgstr "切换带双点音符"
+
+#: step_entry.cc:690
+msgid "Toggled Triple-Dotted Notes"
+msgstr "切换带三点音符"
+
+#: step_entry.cc:693
+msgid "Toggle Chord Entry"
+msgstr "切换和弦入口"
+
+#: step_entry.cc:695
+msgid "Sustain Selected Notes by Note Length"
+msgstr "通过音符长度持续已选择的音符"
+
+#: stereo_panner.cc:133
+#, c-format
+msgid "L:%3d R:%3d Width:%d%%"
+msgstr "左:%3d 右:%3d 宽度:%d%%"
+
+#: stereo_panner_editor.cc:35
+msgid "Stereo Panner"
+msgstr "立体声面板"
+
+#: stereo_panner_editor.cc:49
+msgid "Width"
+msgstr "宽度"
+
+#: strip_silence_dialog.cc:44
+msgid "Strip Silence"
+msgstr "片段无声"
+
+#: strip_silence_dialog.cc:75
+msgid "Minimum length"
+msgstr "最小长度"
+
+#: strip_silence_dialog.cc:83
+msgid "Fade length"
+msgstr "淡化长度"
+
+#: tempo_dialog.cc:41 tempo_dialog.cc:57
+msgid "bar:"
+msgstr "小节:"
+
+#: tempo_dialog.cc:42 tempo_dialog.cc:58
+msgid "beat:"
+msgstr "拍子:"
+
+#: tempo_dialog.cc:43 tempo_dialog.cc:59
+msgid "Pulse note"
+msgstr "脉冲音符"
+
+#: tempo_dialog.cc:44 tempo_dialog.cc:60
+msgid "Tap tempo"
+msgstr "节拍节奏"
+
+#: tempo_dialog.cc:54
+msgid "Edit Tempo"
+msgstr "编辑节奏"
+
+#: tempo_dialog.cc:77 tempo_dialog.cc:78 tempo_dialog.cc:324 tempo_dialog.cc:325
+msgid "whole"
+msgstr "å…¨"
+
+#: tempo_dialog.cc:79 tempo_dialog.cc:80 tempo_dialog.cc:326 tempo_dialog.cc:327
+msgid "second"
+msgstr "二分之一"
+
+#: tempo_dialog.cc:81 tempo_dialog.cc:82 tempo_dialog.cc:328 tempo_dialog.cc:329
+msgid "third"
+msgstr "三分之一"
+
+#: tempo_dialog.cc:83 tempo_dialog.cc:84 tempo_dialog.cc:330 tempo_dialog.cc:331
+msgid "quarter"
+msgstr "四分之一"
+
+#: tempo_dialog.cc:85 tempo_dialog.cc:86 tempo_dialog.cc:332 tempo_dialog.cc:333
+msgid "eighth"
+msgstr "八分之一"
+
+#: tempo_dialog.cc:87 tempo_dialog.cc:88 tempo_dialog.cc:334 tempo_dialog.cc:335
+msgid "sixteenth"
+msgstr "十六分之一"
+
+#: tempo_dialog.cc:89 tempo_dialog.cc:90 tempo_dialog.cc:336 tempo_dialog.cc:337
+msgid "thirty-second"
+msgstr "三十二分之一"
+
+#: tempo_dialog.cc:91 tempo_dialog.cc:92 tempo_dialog.cc:338 tempo_dialog.cc:339
+msgid "sixty-fourth"
+msgstr "六十四分之一"
+
+#: tempo_dialog.cc:93 tempo_dialog.cc:94 tempo_dialog.cc:340 tempo_dialog.cc:341
+msgid "one-hundred-twenty-eighth"
+msgstr "一百二十八分之一"
+
+#: tempo_dialog.cc:121
+msgid "Beats per minute:"
+msgstr "每分钟拍子数:"
+
+#: tempo_dialog.cc:155
+msgid "Tempo begins at"
+msgstr "节奏开始位于"
+
+#: tempo_dialog.cc:251
+msgid "incomprehensible pulse note type (%1)"
+msgstr "不可理解的脉冲音符类型(%1)"
+
+#: tempo_dialog.cc:307
+msgid "Edit Meter"
+msgstr "编辑节拍"
+
+#: tempo_dialog.cc:356
+msgid "Note value:"
+msgstr "音符值:"
+
+#: tempo_dialog.cc:357
+msgid "Beats per bar:"
+msgstr "每小节拍子数:"
+
+#: tempo_dialog.cc:371
+msgid "Meter begins at bar:"
+msgstr "节拍开始位于小节:"
+
+#: tempo_dialog.cc:484
+msgid "incomprehensible meter note type (%1)"
+msgstr "不可理解的节拍音符类型(%1)"
+
+#: theme_manager.cc:65
+msgid "Dark Theme"
+msgstr "深暗主题"
+
+#: theme_manager.cc:66
+msgid "Light Theme"
+msgstr "明亮主题"
+
+#: theme_manager.cc:67
+msgid "Restore Defaults"
+msgstr "重置恢复默认值"
+
+#: theme_manager.cc:68
+msgid "Draw \"flat\" buttons"
+msgstr "描绘“降调”按钮"
+
+#: theme_manager.cc:69
+msgid "Blink Rec-Arm buttons"
+msgstr "闪光录制臂按钮"
+
+#: theme_manager.cc:70
+msgid "Color regions using their track's color"
+msgstr "使用区域的音轨颜色作为区域色"
+
+#: theme_manager.cc:71
+msgid "Show waveform clipping"
+msgstr "显示波形截波"
+
+#: theme_manager.cc:73
+msgid "Waveforms color gradient depth"
+msgstr "波形颜色梯度深度"
+
+#: theme_manager.cc:75
+msgid "Timeline item gradient depth"
+msgstr "时间线条目梯度深度"
+
+#: theme_manager.cc:76
+msgid "All floating windows are dialogs"
+msgstr "所有浮动窗口都是对话框"
+
+#: theme_manager.cc:77
+msgid "Transient windows follow front window."
+msgstr "临时窗口跟随前方窗口。"
+
+#: theme_manager.cc:78
+msgid "Icon Set"
+msgstr "图标集"
+
+#: theme_manager.cc:87
+msgid "Object"
+msgstr "对象物体"
+
+#: theme_manager.cc:163
+msgid "Items"
+msgstr "条目"
+
+#: theme_manager.cc:164
+msgid "Palette"
+msgstr "调色板"
+
+#: theme_manager.cc:165
+msgid "Transparency"
+msgstr "透明度"
+
+#: theme_manager.cc:195
+msgid ""
+"Mark all floating windows to be type \"Dialog\" rather than using \"Utility\" for "
+"some.\n"
+"This may help with some window managers. This requires a restart of %1 to take "
+"effect"
+msgstr ""
+"标记所有窗口类型为“对话框”,而不是把某些窗口标记为“工具”。\n"
+"这也许对于某些窗口管理有所帮助。这需要重新启动 %1以生效。"
+
+#: theme_manager.cc:199
+msgid ""
+"Make transient windows follow the front window when toggling between the editor "
+"and mixer.\n"
+"This requires a restart of %1 to take effect"
 msgstr ""
+"在编辑器和混音器之间切换时,让临时窗口跟随前方窗口。\n"
+"这需要重新启动 %1以生效。"
+
+#: theme_manager.cc:620
+msgid "Color Palette"
+msgstr "颜料调色板"
+
+#: time_axis_view.cc:148
+msgid "Track/Bus name (double click to edit)"
+msgstr "音轨/总线名称(双击即可编辑)"
+
+#: time_axis_view_item.cc:345
+msgid "new duration %1 frame is out of bounds for %2"
+msgid_plural "new duration of %1 frames is out of bounds for %2"
+msgstr[0] "新的音长 %1 帧超出了 %2 的边界"
+
+#: time_fx_dialog.cc:62
+msgid "Quick but Ugly"
+msgstr "快速(但不优美)"
+
+#: time_fx_dialog.cc:63
+msgid "Skip Anti-aliasing"
+msgstr "跳过自动对齐"
+
+#: time_fx_dialog.cc:64
+msgid "Contents:"
+msgstr "内容:"
+
+#: time_fx_dialog.cc:65
+msgid "Minimize time distortion"
+msgstr "减少时间扭曲"
+
+#: time_fx_dialog.cc:66
+msgid "Preserve Formants"
+msgstr "保持共振峰"
+
+#: time_fx_dialog.cc:71
+msgid "TimeFXDialog"
+msgstr "时间特效对话框"
+
+#: time_fx_dialog.cc:74
+msgid "Pitch Shift Audio"
+msgstr "音高替换音频"
+
+#: time_fx_dialog.cc:76
+msgid "Time Stretch Audio"
+msgstr "时间延伸音频"
+
+#: time_fx_dialog.cc:104 transpose_dialog.cc:41
+msgid "Octaves:"
+msgstr "八度:"
+
+#: time_fx_dialog.cc:109 transpose_dialog.cc:46
+msgid "Semitones:"
+msgstr "半音:"
+
+#: time_fx_dialog.cc:114
+msgid "Cents:"
+msgstr "音分:"
+
+#: time_fx_dialog.cc:122
+msgid "Time|Shift"
+msgstr "时间|替换"
+
+#: time_fx_dialog.cc:146 time_fx_dialog.cc:149
+msgid "TimeFXButton"
+msgstr "时间特效按钮"
+
+#: time_fx_dialog.cc:154
+msgid "Stretch/Shrink"
+msgstr "延伸/收缩"
+
+#: time_fx_dialog.cc:164
+msgid "<b>Progress</b>"
+msgstr "<b>进程</b>"
+
+#: time_info_box.cc:124
+msgid "Start recording at auto-punch start"
+msgstr "在自动切换起点开始录制"
+
+#: time_info_box.cc:125
+msgid "Stop recording at auto-punch end"
+msgstr "在自动切换终点停止录制"
+
+#: time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr "程序错误: 需要的音频范围(%1)不存在!"
+
+#: transform_dialog.cc:39
+msgid "this note's"
+msgstr "这个音符的"
+
+#: transform_dialog.cc:40
+msgid "the previous note's"
+msgstr "上一个音符的"
+
+#: transform_dialog.cc:41
+msgid "this note's index"
+msgstr "这个音符的索引"
+
+#: transform_dialog.cc:42
+msgid "the number of notes"
+msgstr "音符的数目"
+
+#: transform_dialog.cc:43
+msgid "exactly"
+msgstr "精确地"
+
+#: transform_dialog.cc:44
+msgid "a random number from"
+msgstr "一个随机数来自于"
+
+#: transform_dialog.cc:55
+msgid "equal steps from"
+msgstr "相同步长来自于"
+
+#: transform_dialog.cc:58
+msgid "note number"
+msgstr "音符编号"
+
+#: transform_dialog.cc:59
+msgid "velocity"
+msgstr "力度"
+
+#: transform_dialog.cc:60
+msgid "start time"
+msgstr "起点时间"
+
+#: transform_dialog.cc:61
+msgid "length"
+msgstr "长度"
+
+#: transform_dialog.cc:82 transform_dialog.cc:113
+msgid "Transform"
+msgstr "变换"
+
+#: transform_dialog.cc:91
+msgid "Set "
+msgstr "集"
+
+#: transpose_dialog.cc:30
+msgid "Transpose MIDI"
+msgstr "变调 MIDI"
+
+#: transpose_dialog.cc:55
+msgid "Transpose"
+msgstr "变调"
+
+#: ui_config.cc:163 ui_config.cc:300
+msgid "Loading default ui configuration file %1"
+msgstr "载入默认用户界面配置文件 %1"
+
+#: ui_config.cc:166 ui_config.cc:303
+msgid "cannot read default ui configuration file \"%1\""
+msgstr "无法读取默认用户界面配置文件 \"%1\""
+
+#: ui_config.cc:169 ui_config.cc:308
+msgid "default ui configuration file \"%1\" not loaded successfully."
+msgstr "默认用户界面配置文件 \"%1\" 载入不成功。"
+
+#: ui_config.cc:177
+msgid "Could not find default UI configuration file %1"
+msgstr "无法找到默认用户界面配置文件\"%1\""
+
+#: ui_config.cc:219
+msgid "Loading color file %1"
+msgstr "载入颜色文件 %1"
+
+#: ui_config.cc:222
+msgid "cannot read color file \"%1\""
+msgstr "无法读取颜色文件 %1"
+
+#: ui_config.cc:227
+msgid "color file \"%1\" not loaded successfully."
+msgstr "颜色文件 %1载入不成功"
+
+#: ui_config.cc:233
+msgid "Color file %1 not found"
+msgstr "找不到颜色文件 %1"
+
+#: ui_config.cc:282 ui_config.cc:361
+msgid "Color file %1 not saved"
+msgstr "尚未保存颜色文件 %1"
+
+#: ui_config.cc:317
+msgid "Loading user ui configuration file %1"
+msgstr "载入用户界面配置文件 %1"
+
+#: ui_config.cc:320
+msgid "cannot read ui configuration file \"%1\""
+msgstr "无法读取用户界面配置文件 \"%1\""
 
-#: session_state.cc:1872
-msgid "Session: cannot create Source from XML description."
-msgstr ""
+#: ui_config.cc:325
+msgid "user ui configuration file \"%1\" not loaded successfully."
+msgstr "用户的用户界面配置文件 \"%1\" 载入不成功。"
 
-#: session_state.cc:1880
-msgid ""
-"A external MIDI file is missing. %1 cannot currently recover from missing "
-"external MIDI files"
-msgstr ""
+#: ui_config.cc:333
+msgid "could not find any ui configuration file, canvas will look broken."
+msgstr "找不到任何用户界面配置文件,版面看起来将不大美观。"
 
-#: session_state.cc:1962
-msgid "Found a sound file that cannot be used by %1. Talk to the programmers."
-msgstr ""
+#: ui_config.cc:351
+msgid "Config file %1 not saved"
+msgstr "尚未保存配置文件 %1"
 
-#: session_state.cc:1979
-msgid "Could not create templates directory \"%1\" (%2)"
-msgstr ""
+#: ui_config.cc:592
+msgid "Color %1 not found"
+msgstr "找不到颜色 %1"
 
-#: session_state.cc:1992
-msgid "Template \"%1\" already exists - new version not created"
-msgstr ""
+#: ui_config.cc:662
+msgid "Unable to find UI style file %1 in search path %2. %3 will look strange"
+msgstr "在搜索路径 %2 下找不到用户界面样式文件 %1。%3 看起来将不大美观。"
 
-#: session_state.cc:1998
-msgid "Could not create directory for Session template\"%1\" (%2)"
-msgstr ""
+#: utils.cc:117 utils.cc:160
+msgid "bad XPM header %1"
+msgstr "损坏的 XPM 报头 %1"
 
-#: session_state.cc:2008
-msgid "template not saved"
-msgstr "模板没保存"
+#: utils.cc:577
+msgid "cannot find XPM file for %1"
+msgstr "找不到 XPM 文件提供给 %1"
 
-#: session_state.cc:2018
-msgid "Could not create directory for Session template plugin state\"%1\" (%2)"
-msgstr ""
+#: utils.cc:597 utils.cc:627 utils.cc:641
+msgid "default"
+msgstr "默认"
 
-#: session_state.cc:2261
-msgid "Unknown node \"%1\" found in Bundles list from session file"
-msgstr ""
+#: utils.cc:642
+msgid "icon \"%1\" not found for icon set \"%2\", fallback to default"
+msgstr "找不到图标 \"%1\" 提供给图标集 \"%2\",退回默认状态"
 
-#: session_state.cc:2834
-msgid "Session: cannot create dead file folder \"%1\" (%2)"
-msgstr ""
+#: utils.cc:649
+msgid "cannot find icon image for %1 using %2"
+msgstr "找不到图标图像提供给 %1 使用 %2"
 
-#: session_state.cc:2873
-msgid "cannot rename unused file source from %1 to %2 (%3)"
-msgstr ""
+#: utils.cc:666 utils.cc:682
+msgid "Caught exception while loading icon named %1"
+msgstr "载入命名为 %1 的图标时遇到异常"
 
-#: session_state.cc:2891
-msgid "cannot remove peakfile %1 for %2 (%3)"
-msgstr ""
+#: add_video_dialog.cc:54
+msgid "Set Video Track"
+msgstr "设置视频轨道"
 
-#: session_state.cc:3204
-msgid "could not backup old history file, current history not saved"
-msgstr ""
+#: add_video_dialog.cc:62
+msgid "Open Video Monitor Window"
+msgstr "打开视频监控窗口"
 
-#: session_state.cc:3213
-msgid "history could not be saved to %1"
-msgstr "历史无法被保存到 %1"
+#: add_video_dialog.cc:63
+msgid "Adjust Session Framerate to Match Video Framerate"
+msgstr "调整会话帧率匹配视频帧率"
 
-#: session_state.cc:3216
-msgid "Could not remove history file at path \"%1\" (%2)"
-msgstr ""
+#: add_video_dialog.cc:65
+msgid "Reload docroot"
+msgstr "重新载入文档根"
 
-#: session_state.cc:3220
-msgid "could not restore history file from backup %1 (%2)"
-msgstr ""
+#: add_video_dialog.cc:120
+msgid "Video files"
+msgstr "视频文件"
 
-#: session_state.cc:3245
-msgid "%1: no history file \"%2\" for this session."
-msgstr ""
+#: add_video_dialog.cc:149
+msgid "<b>Video Information</b>"
+msgstr "<b>视频信息</b>"
 
-#: session_state.cc:3251
-msgid "Could not understand session history file \"%1\""
-msgstr "无法理解会话历史文件 \"%1\""
+#: add_video_dialog.cc:152
+msgid "Start:"
+msgstr "起点:"
 
-#: session_state.cc:3293
-msgid "Failed to downcast MidiSource for NoteDiffCommand"
-msgstr ""
+#: add_video_dialog.cc:158
+msgid "Frame rate:"
+msgstr "帧率:"
 
-#: session_state.cc:3304
-msgid "Failed to downcast MidiSource for SysExDiffCommand"
-msgstr ""
+#: add_video_dialog.cc:161
+msgid "Aspect Ratio:"
+msgstr "长宽比:"
 
-#: session_state.cc:3315
-msgid "Failed to downcast MidiSource for PatchChangeDiffCommand"
-msgstr ""
+#: add_video_dialog.cc:244
+msgid "VideoServerIndex"
+msgstr "视频服务索引"
 
-#: session_state.cc:3323
-msgid "Couldn't figure out how to make a Command out of a %1 XMLNode."
+#: add_video_dialog.cc:675
+msgid " %1 fps"
 msgstr ""
 
-#: session_state.cc:3559
-msgid "Session: unknown diskstream type in XML"
+#: video_timeline.cc:468
+msgid ""
+"Parsing video file info failed. Is the Video Server running? Is the file readable "
+"by the Video Server? Does the docroot match? Is it a video file?"
 msgstr ""
+"解析视频文件信息失败。视频服务器是否正在运行吗?视频服务器是否可辨识该文件?文档根"
+"是否匹配?这是一个视频文件吗?"
 
-#: session_state.cc:3564
-msgid "Session: could not load diskstream via XML state"
-msgstr ""
+#: video_timeline.cc:506
+msgid ""
+"Failed to set session-framerate: '%1' does not have a corresponding option setting "
+"in %2."
+msgstr "设置会话帧率失败:'%1' 的选项设置与在 %2 里的不一致。"
 
-#: session_state.cc:3688 session_state.cc:3716 session_state.cc:3729
-#: session_state.cc:3744
-msgid "renaming %s as %2 failed (%3)"
-msgstr ""
+#: video_timeline.cc:514
+msgid ""
+"Video file's framerate is not equal to %1 session timecode's framerate: '%2' vs "
+"'%3'"
+msgstr "视频文件的帧率不等于 %1 会话时间码帧率: '%2' vs '%3'"
 
-#: session_time.cc:214
-msgid "Unknown transport state %1 in sync callback"
+#: video_timeline.cc:587
+msgid ""
+"Video-server docroot mismatch. %1: '%2', video-server: '%3'. This usually means "
+"that the video server was not started by %1 and uses a different document-root."
 msgstr ""
+"视频文件文档根不匹配。%1: '%2',视频服务器:'%3'。这通常意味着视频服务器未能通过 "
+"%1 启动,并且使用着一个不同的文档根。"
 
-#: session_transport.cc:171
-msgid "Cannot loop - no loop range defined"
+#: video_timeline.cc:724
+msgid ""
+"Video-monitor 'xjadeo' was not found. Please install http://xjadeo.sf.net/ (a "
+"custom path to xjadeo can be specified by setting the XJREMOTE environment "
+"variable. It should point to an application compatible with xjadeo's remote-"
+"control interface 'xjremote').\n"
+"\n"
+"see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
+"视频监控 'xjadeo' 未找到。请安装 http://xjadeo.sf.net/ (可以通过设置 XJREMOTE 环境"
+"变量来指定一个到 xjadeo 的定制路径。它应该指向一个兼容 xjadeo 遥控界面  'xjremote' "
+"的应用程序)。\n"
+"\n"
+"请参阅 http://manual.ardour.org/video-timeline/setup/"
+
+#: video_timeline.cc:739
+msgid "Video-monitor 'xjadeo' cannot be launched."
+msgstr "视频监控 'xjadeo' 无法启动。"
 
-#: session_transport.cc:833
+#: video_timeline.cc:766
 msgid ""
-"Seamless looping cannot be supported while %1 is using JACK transport.\n"
-"Recommend changing the configured options"
+"Video-monitor 'xjadeo' is too old. Please install xjadeo version 0.7.7 or later. "
+"http://xjadeo.sf.net/"
 msgstr ""
+"视频监控 'xjadeo' 太过老旧。请安装 xjadeo 0.7.7 或者更新的版本。 http://xjadeo.sf."
+"net/"
 
-#: session_transport.cc:915
-msgid "Locate called for negative sample position - ignored"
-msgstr ""
+#: video_monitor.cc:285
+msgid "Video Monitor: File Not Found."
+msgstr "视频监控:找不到文件。"
 
-#: session_transport.cc:1272
+#: transcode_ffmpeg.cc:56
 msgid ""
-"Global varispeed cannot be supported while %1 is connected to JACK transport "
-"control"
+"No ffprobe or ffmpeg executables could be found on this system.\n"
+"Video import and export is not possible until you install those tools.\n"
+"%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
+"\n"
+"The tools are included with the %1 releases from ardour.org and also available "
+"with the video-server at http://x42.github.com/harvid/\n"
+"\n"
+"Important: the files need to be installed in $PATH and named ffmpeg_harvid and "
+"ffprobe_harvid.\n"
+"If you already have a suitable ffmpeg installation on your system, we recommend "
+"creating symbolic links from ffmpeg to ffmpeg_harvid and from ffprobe to "
+"ffprobe_harvid.\n"
+"\n"
+"see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
+"在这个系统上没找到 ffprobe 或者 ffmpeg 可执行文件。\n"
+"视频导入和导出无法进行,除非您安装这些工具。\n"
+"%1 需要 ffmpeg 和 ffprobe,来自 ffmpeg.org 1.1 或者更新的版本。\n"
+"\n"
+"这工具包括来自 ardour.org 的 %1,并且也可用于 http://x42.github.com/harvid/  上的视"
+"频服务。\n"
+"\n"
+"注意:这些文件需要安装在 $PATH 并且命名为 ffmpeg_harvid 和 ffprobe_harvid 。\n"
+"如果您在您的系统上已经安装有一个合适的 ffmpeg,我们建议给 ffmpeg 创建符号链接为 "
+"ffmpeg_harvid,给 ffprobe 创建符号链接为  ffprobe_harvid 。\n"
+"\n"
+"请参阅 http://manual.ardour.org/video-timeline/setup/"
 
-#: smf_source.cc:344
-msgid "Unable to read event prefix, corrupt MIDI ring"
-msgstr ""
+#: transcode_video_dialog.cc:56
+msgid "Transcode/Import Video File "
+msgstr "转码/导入视频文件"
 
-#: smf_source.cc:357
-msgid "Event has time and size but no body, corrupt MIDI ring"
-msgstr ""
+#: transcode_video_dialog.cc:58
+msgid "Output File:"
+msgstr "导出文件:"
+
+#: transcode_video_dialog.cc:61 export_video_dialog.cc:85
+msgid "Abort"
+msgstr "中止"
 
-#: smf_source.cc:363
-msgid "Event time is before MIDI source position"
+#: transcode_video_dialog.cc:63
+msgid "Height = "
+msgstr "高度 = "
+
+#: transcode_video_dialog.cc:66
+msgid "Manual Override"
+msgstr "手动覆盖"
+
+#: transcode_video_dialog.cc:70 export_video_dialog.cc:103
+msgid "Debug Mode: Print ffmpeg command and output to stdout."
+msgstr "调试模式:打印 ffmpeg 命令并输出到标准输出。"
+
+#: transcode_video_dialog.cc:107
+msgid "<b>File Information</b>"
+msgstr "<b>文件信息</b>"
+
+#: transcode_video_dialog.cc:113
+msgid ""
+"No ffprobe or ffmpeg executables could be found on this system. Video Import is "
+"not possible until you install those tools. See the Log window for more "
+"information."
 msgstr ""
+"在这个系统上没找到 ffprobe 或者 ffmpeg 可执行文件。视频导入无法进行,除非您安装这些"
+"工具。更多的信息请参阅日志窗口。"
 
-#: smf_source.cc:409
+#: transcode_video_dialog.cc:120
 msgid ""
-"Skipping event with unordered beat time %1 < %2 (off by %3 beats, %4 ticks)"
+"File-info can not be read. Most likely '%1' is not a valid video-file or an "
+"unsupported video codec or format."
 msgstr ""
+"无法读取文件信息。极有可能 '‘% 1' 不是一个有效的视频文件,或者是一个不支持的视频编"
+"解码器或格式。"
 
-#: smf_source.cc:453
-msgid "Skipping event with unordered frame time %1 < %2"
+#: transcode_video_dialog.cc:134
+msgid "FPS:"
 msgstr ""
 
-#: smf_source.cc:518
-msgid "cannot open MIDI file %1 for write"
-msgstr "无法打开MIDI文件 %1 用于写入"
+#: transcode_video_dialog.cc:136
+msgid "Duration:"
+msgstr "音长:"
 
-#: sndfile_helpers.cc:34
-msgid "WAV"
-msgstr ""
+#: transcode_video_dialog.cc:138
+msgid "Codec:"
+msgstr "编码:"
 
-#: sndfile_helpers.cc:35
-msgid "AIFF"
-msgstr ""
+#: transcode_video_dialog.cc:140
+msgid "Geometry:"
+msgstr "几何形状:"
 
-#: sndfile_helpers.cc:36
-msgid "CAF"
+#: transcode_video_dialog.cc:155
+msgid "??"
 msgstr ""
 
-#: sndfile_helpers.cc:37
-msgid "W64 (64 bit WAV)"
-msgstr ""
+#: transcode_video_dialog.cc:176
+msgid "<b>Import Settings</b>"
+msgstr "<b>导入设置</b>"
 
-#: sndfile_helpers.cc:38
-msgid "FLAC"
-msgstr ""
+#: transcode_video_dialog.cc:181
+msgid "Reference From Current Location (Previously Transcoded Files Only)"
+msgstr "从当前位置引用(仅上一个已转码文件)"
 
-#: sndfile_helpers.cc:39
-msgid "Ogg/Vorbis"
-msgstr ""
+#: transcode_video_dialog.cc:183
+msgid "Import/Transcode Video to Session"
+msgstr "导入/转码视频到会话"
 
-#: sndfile_helpers.cc:40
-msgid "raw (no header)"
-msgstr ""
+#: transcode_video_dialog.cc:191
+msgid "Do Not Import Video (Audio Import Only)"
+msgstr "不要导入视频(仅导入音频)"
 
-#: sndfile_helpers.cc:45
-msgid ".wav"
-msgstr ""
+#: transcode_video_dialog.cc:200
+msgid "Scale Video: Width = "
+msgstr "缩放视频:宽度 = "
 
-#: sndfile_helpers.cc:46
-msgid ".aiff"
-msgstr ""
+#: transcode_video_dialog.cc:207
+msgid "Original Width"
+msgstr "原始宽度"
 
-#: sndfile_helpers.cc:47
-msgid ".caf"
-msgstr ""
+#: transcode_video_dialog.cc:222
+msgid "Bitrate (KBit/s):"
+msgstr "比特率(码率 KBit/s):"
 
-#: sndfile_helpers.cc:48
-msgid ".w64"
-msgstr ""
+#: transcode_video_dialog.cc:227
+msgid "Extract Audio:"
+msgstr "提取音频:"
 
-#: sndfile_helpers.cc:49
-msgid ".flac"
-msgstr ""
+#: transcode_video_dialog.cc:232
+msgid "No Audio Track Present"
+msgstr "无音频轨道呈现"
 
-#: sndfile_helpers.cc:50
-msgid ".ogg"
-msgstr ""
+#: transcode_video_dialog.cc:235
+msgid "Do Not Extract Audio"
+msgstr "无法提取音频"
 
-#: sndfile_helpers.cc:51
-msgid ".raw"
-msgstr ""
+#: transcode_video_dialog.cc:350
+msgid "Extracting Audio.."
+msgstr "音频提取中…"
 
-#: sndfile_helpers.cc:66
-msgid "Signed 16 bit PCM"
-msgstr ""
+#: transcode_video_dialog.cc:353
+msgid "Audio Extraction Failed."
+msgstr "音频提取失败。"
 
-#: sndfile_helpers.cc:67
-msgid "Signed 24 bit PCM"
-msgstr ""
+#: transcode_video_dialog.cc:379
+msgid "Transcoding Video.."
+msgstr "视频转码中…"
 
-#: sndfile_helpers.cc:68
-msgid "Signed 32 bit PCM"
-msgstr ""
+#: transcode_video_dialog.cc:413
+msgid "Transcoding Failed."
+msgstr "转码失败。"
 
-#: sndfile_helpers.cc:69
-msgid "Signed 8 bit PCM"
-msgstr ""
+#: transcode_video_dialog.cc:503
+msgid "Save Transcoded Video File"
+msgstr "保存已转码视频文件"
 
-#: sndfile_helpers.cc:70
-msgid "32 bit float"
-msgstr ""
+#: video_server_dialog.cc:52
+msgid "Launch Video Server"
+msgstr "启动视频服务器"
 
-#: sndfile_helpers.cc:83
-msgid "Little-endian (Intel)"
-msgstr ""
+#: video_server_dialog.cc:53
+msgid "Server Executable:"
+msgstr "服务器可执行:"
 
-#: sndfile_helpers.cc:84
-msgid "Big-endian (PowerPC)"
-msgstr ""
+#: video_server_dialog.cc:55
+msgid "Server Docroot:"
+msgstr "服务器文档根:"
 
-#: sndfilesource.cc:260
-msgid "SndFileSource: cannot open file \"%1\" for %2 (%3)"
-msgstr ""
+#: video_server_dialog.cc:61
+msgid "Don't show this dialog again. (Reset in Edit->Preferences)."
+msgstr "不再显示这个对话框。(可在 编辑 -> 首选项 里重置)。"
 
-#: sndfilesource.cc:268
+#: video_server_dialog.cc:97
 msgid ""
-"SndFileSource: file only contains %1 channels; %2 is invalid as a channel "
-"number"
+"The external video server 'harvid' can not be found.\n"
+"The tool is included with the %1 releases from ardour.org, alternatively you can "
+"download it from http://x42.github.com/harvid/ or acquire it from your "
+"distribution.\n"
+"\n"
+"see also http://manual.ardour.org/video-timeline/setup/"
 msgstr ""
+"找不到外部视频服务器 'harvid' 。\n"
+"这工具包括来自 ardour.org 的 %1,另外您可以从 http://x42.github.com/harvid/ 下载"
+"它,或者从您的发行版获得它。\n"
+"\n"
+"请参阅 http://manual.ardour.org/video-timeline/setup/"
 
-#: sndfilesource.cc:322 sndfilesource.cc:655
+#: video_server_dialog.cc:129
+msgid "Listen Address:"
+msgstr "试听地址:"
+
+#: video_server_dialog.cc:134
+msgid "Listen Port:"
+msgstr "试听端口:"
+
+#: video_server_dialog.cc:139
+msgid "Cache Size:"
+msgstr "缓存大小:"
+
+#: video_server_dialog.cc:145
 msgid ""
-"cannot set broadcast info for audio file %1 (%2); dropping broadcast info "
-"for this file"
+"%1 relies on an external video server for the videotimeline.\n"
+"The server configured in Edit -> Preferences -> Video is not reachable.\n"
+"Do you want %1 to launch 'harvid' on this machine?"
 msgstr ""
+"%1 依赖于外部视频服务器以获取视频时间线。\n"
+"这个已配置在 编辑 -> 首选项 -> 视频 的服务器无法访问。\n"
+"您是否要 %1 在这台机器上启动 'harvid' ?"
 
-#: sndfilesource.cc:368
-msgid "could not allocate file %1 for reading."
-msgstr "无法分配文件 %1 用于读入"
+#: video_server_dialog.cc:189
+msgid "Set Video Server Executable"
+msgstr "设置视频服务器可执行"
 
-#: sndfilesource.cc:403
-msgid "SndFileSource: could not seek to frame %1 within %2 (%3)"
-msgstr ""
+#: video_server_dialog.cc:209
+msgid "Server docroot"
+msgstr "服务器文档根"
 
-#: sndfilesource.cc:412
+#: utils_videotl.cc:60
+msgid "Destination is outside Video Server's docroot. "
+msgstr "目的地是视频服务器的文档根之外。"
+
+#: utils_videotl.cc:61
 msgid ""
-"SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5, ret was %6)"
+"The destination file path is outside of the Video Server's docroot. The file will "
+"not be readable by the Video Server. Do you still want to continue?"
 msgstr ""
+"目的地文件路径是处在视频服务器文档根之外。这个文件将无法被视频服务器读取。您是否要"
+"继续?"
 
-#: sndfilesource.cc:454 sndfilesource.cc:483
-msgid "attempt to write a non-writable audio file source (%1)"
-msgstr ""
+#: utils_videotl.cc:64
+msgid "Continue"
+msgstr "继续"
 
-#: sndfilesource.cc:459 utils.cc:579 utils.cc:603 utils.cc:617 utils.cc:636
-msgid "programming error: %1 %2"
-msgstr "程序错误: %1 %2"
+#: utils_videotl.cc:70
+msgid "Confirm Overwrite"
+msgstr "确认覆盖"
 
-#: sndfilesource.cc:586 sndfilesource.cc:604
-msgid "attempt to flush a non-writable audio file source (%1)"
-msgstr ""
+#: utils_videotl.cc:71
+msgid "A file with the same name already exists.  Do you want to overwrite it?"
+msgstr "已有相同名称的文件存在。您是否要重写覆盖它?"
 
-#: sndfilesource.cc:591
-msgid "could not allocate file %1 to write header"
-msgstr ""
+#: utils_videotl.cc:81 utils_videotl.cc:97
+msgid "Cannot create video folder \"%1\" (%2)"
+msgstr "无法创建视频文件夹 \"%1\" (%2)"
 
-#: sndfilesource.cc:609
-msgid "could not allocate file %1 to flush contents"
-msgstr ""
+#: export_video_dialog.cc:71
+msgid "Export Video File "
+msgstr "导出视频文件"
 
-#: sndfilesource.cc:621
-msgid ""
-"attempt to store broadcast info in a non-writable audio file source (%1)"
-msgstr ""
+#: export_video_dialog.cc:82
+msgid "Video:"
+msgstr "视频:"
 
-#: sndfilesource.cc:626
-msgid "attempt to set BWF info for an un-opened audio file source (%1)"
-msgstr ""
+#: export_video_dialog.cc:87
+msgid "Scale Video (W x H):"
+msgstr "缩放视频(宽 x 高):"
 
-#: sndfilesource.cc:670
-msgid "%1: cannot seek to %2 (libsndfile error: %3)"
-msgstr ""
+#: export_video_dialog.cc:88
+msgid "Retain Aspect"
+msgstr "保持长宽比"
 
-#: sndfilesource.cc:780
-msgid "SndFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"
-msgstr ""
+#: export_video_dialog.cc:93
+msgid "Set Aspect Ratio:"
+msgstr "设置长宽比:"
 
-#: sndfilesource.cc:793 sndfilesource.cc:843 sndfilesource.cc:850
-msgid "SndFileSource: \"%1\" bad write (%2)"
-msgstr ""
+#: export_video_dialog.cc:94
+msgid "Normalize Audio"
+msgstr "规范化音频"
 
-#: sndfilesource.cc:873
-msgid ""
-"Filesource: start time is already set for existing file (%1): Cannot change "
-"start time."
-msgstr ""
+#: export_video_dialog.cc:95
+msgid "2 Pass Encoding"
+msgstr "二次编码"
+
+#: export_video_dialog.cc:96
+msgid "Codec Optimizations:"
+msgstr "解码器优化:"
+
+#: export_video_dialog.cc:98
+msgid "Deinterlace"
+msgstr "反交错"
 
-#: soundcloud_upload.cc:129
+#: export_video_dialog.cc:99
+msgid "Use [2] B-frames (MPEG 2 or 4 only)"
+msgstr "使用 [2] B-帧(仅 MPEG 2 或 4)"
+
+#: export_video_dialog.cc:100
+msgid "Override FPS (Default is to retain FPS from the input video file):"
+msgstr "覆盖 FPS(默认是覆盖到从输入视频文件保留的 FPS):"
+
+#: export_video_dialog.cc:101
+msgid "Include Session Metadata"
+msgstr "包括会话元数据"
+
+#: export_video_dialog.cc:119
 msgid ""
-"Upload to Soundcloud failed.  Perhaps your email or password are incorrect?\n"
+"No ffprobe or ffmpeg executables could be found on this system. Video Export is "
+"not possible until you install those tools. See the Log window for more "
+"information."
 msgstr ""
+"在这个系统上没找到 ffprobe 或者 ffmpeg 可执行文件。视频导出无法进行,除非您安装这些"
+"工具。更多的信息请参阅日志窗口。"
 
-#: source_factory.cc:374
-msgid "Recovery attempted on a MIDI file - not implemented"
-msgstr ""
+#: export_video_dialog.cc:130
+msgid "<b>Output:</b> (file extension defines format)"
+msgstr "<b>导出:</b>(以文件扩展名决定格式)"
 
-#: speakers.cc:280
-msgid "Speaker information is missing azimuth - speaker ignored"
-msgstr ""
+#: export_video_dialog.cc:140
+msgid "<b>Input Video:</b>"
+msgstr "<b>导入视频</b>"
 
-#: speakers.cc:286
-msgid "Speaker information is missing elevation - speaker ignored"
-msgstr ""
+#: export_video_dialog.cc:151
+msgid "Audio:"
+msgstr "音频:"
 
-#: speakers.cc:292
-msgid "Speaker information is missing distance - speaker ignored"
-msgstr ""
+#: export_video_dialog.cc:153
+msgid "Master Bus"
+msgstr "主控总线"
 
-#: srcfilesource.cc:134
-msgid "SrcFileSource: %1"
-msgstr ""
+#: export_video_dialog.cc:158
+msgid "from the %1 session's start to the session's end"
+msgstr "从 %1 会话的起点到会话的终点"
 
-#: tape_file_matcher.cc:46
-msgid "Cannot compile tape track regexp for use (%1)"
-msgstr ""
+#: export_video_dialog.cc:161
+msgid "<b>Settings:</b>"
+msgstr "<b>设置</b>"
 
-#: tempo.cc:80
-msgid "TempoSection XML node has no \"start\" property"
-msgstr ""
+#: export_video_dialog.cc:169
+msgid "Range:"
+msgstr "范围:"
 
-#: tempo.cc:88
-msgid "TempoSection XML node has an illegal \"start\" value"
-msgstr ""
+#: export_video_dialog.cc:172
+msgid "Preset:"
+msgstr "预设:"
 
-#: tempo.cc:95
-msgid "TempoSection XML node has no \"beats-per-minute\" property"
-msgstr ""
+#: export_video_dialog.cc:175
+msgid "Video Codec:"
+msgstr "视频编码:"
 
-#: tempo.cc:100
-msgid "TempoSection XML node has an illegal \"beats_per_minute\" value"
-msgstr ""
+#: export_video_dialog.cc:178
+msgid "Video KBit/s:"
+msgstr "视频 KBit/s:"
 
-#: tempo.cc:109
-msgid "TempoSection XML node has an illegal \"note-type\" value"
-msgstr ""
+#: export_video_dialog.cc:181
+msgid "Audio Codec:"
+msgstr "音频编码:"
 
-#: tempo.cc:115
-msgid "TempoSection XML node has no \"movable\" property"
-msgstr ""
+#: export_video_dialog.cc:184
+msgid "Audio KBit/s:"
+msgstr "音频 KBit/s:"
 
-#: tempo.cc:125
-msgid "TempoSection XML node has an illegal \"bar-offset\" value"
-msgstr ""
+#: export_video_dialog.cc:187
+msgid "Audio Samplerate:"
+msgstr "音频采样率:"
 
-#: tempo.cc:202
-msgid "MeterSection XML node has no \"start\" property"
-msgstr ""
+#: export_video_dialog.cc:222 export_video_dialog.cc:231 export_video_dialog.cc:830
+#: export_video_dialog.cc:833
+msgid "(default for format)"
+msgstr "(默认格式)"
 
-#: tempo.cc:210
-msgid "MeterSection XML node has an illegal \"start\" value"
-msgstr ""
+#: export_video_dialog.cc:242 export_video_dialog.cc:255 export_video_dialog.cc:837
+#: export_video_dialog.cc:846
+msgid "(default)"
+msgstr "(默认)"
 
-#: tempo.cc:220
-msgid ""
-"MeterSection XML node has no \"beats-per-bar\" or \"divisions-per-bar\" "
-"property"
-msgstr ""
+#: export_video_dialog.cc:256 export_video_dialog.cc:840
+msgid "(retain)"
+msgstr "(保留)"
 
-#: tempo.cc:226
-msgid ""
-"MeterSection XML node has an illegal \"beats-per-bar\" or \"divisions-per-bar"
-"\" value"
-msgstr ""
+#: export_video_dialog.cc:348
+msgid "from 00:00:00:00 to the video's end"
+msgstr "从 00:00:00:00 到视频终点"
 
-#: tempo.cc:231
-msgid "MeterSection XML node has no \"note-type\" property"
-msgstr ""
+#: export_video_dialog.cc:350
+msgid "from the video's start to the video's end"
+msgstr "从视频起点到视频终点"
 
-#: tempo.cc:236
-msgid "MeterSection XML node has an illegal \"note-type\" value"
-msgstr ""
+#: export_video_dialog.cc:353
+msgid "Selected range"
+msgstr "已选择的范围"
 
-#: tempo.cc:241
-msgid "MeterSection XML node has no \"movable\" property"
-msgstr ""
+#: export_video_dialog.cc:589
+msgid "Normalizing audio"
+msgstr "规范化音频"
+
+#: export_video_dialog.cc:593
+msgid "Exporting audio"
+msgstr "音频导出中"
 
-#: tempo.cc:388
+#: export_video_dialog.cc:648
+msgid "Exporting Audio..."
+msgstr "音频导出中…"
+
+#: export_video_dialog.cc:705
 msgid ""
-"Meter changes can only be positioned on the first beat of a bar. Moving from "
-"%1 to %2"
-msgstr ""
+"Export Video: Cannot query duration of video-file, using duration from timeline "
+"instead."
+msgstr "导出视频:无法查询视频文件长度,视频时间线长度代替。"
 
-#: tempo.cc:650
-msgid "no tempo sections defined in tempo map - cannot change tempo @ %1"
-msgstr ""
+#: export_video_dialog.cc:735
+msgid "Export Video: export-range does not include video."
+msgstr "导出视频:导出范围无法包括视频。"
 
-#: tempo.cc:680 tempo.cc:696 tempo.cc:712 tempo.cc:728
-msgid "programming error: no tempo section in tempo map!"
-msgstr ""
+#: export_video_dialog.cc:748
+msgid "Export Video: No Master Out Ports to Connect for Audio Export"
+msgstr "导出视频:没有主控输出端口可连接给音频导出"
 
-#: tempo.cc:846 tempo.cc:1827
-msgid "programming error: unhandled MetricSection type"
-msgstr ""
+#: export_video_dialog.cc:790
+msgid "Encoding Video..."
+msgstr "视频编码中…"
 
-#: tempo.cc:1142
-msgid "tempo map asked for BBT time at frame %1\n"
-msgstr ""
+#: export_video_dialog.cc:810
+msgid "Export Video: Video input file cannot be read."
+msgstr "导出视频:无法读取视频导入文件。"
 
-#: tempo.cc:1185
-msgid "tempo map asked for frame time at bar < 1  (%1)\n"
-msgstr ""
+#: export_video_dialog.cc:916
+msgid "Encoding Video.. Pass 1/2"
+msgstr "视频编码中…通过 1/2"
 
-#: tempo.cc:1642 tempo.cc:1656
-msgid "Tempo map: could not set new state, restoring old one."
-msgstr ""
+#: export_video_dialog.cc:928
+msgid "Encoding Video.. Pass 2/2"
+msgstr "视频编码中…通过 2/2"
 
-#: tempo.cc:1677
-msgid "Multiple meter definitions found at %1"
-msgstr ""
+#: export_video_dialog.cc:1031
+msgid "Transcoding failed."
+msgstr "转码失败。"
 
-#: tempo.cc:1682
-msgid "Multiple tempo definitions found at %1"
-msgstr ""
+#: export_video_dialog.cc:1267 export_video_dialog.cc:1287
+msgid "Save Exported Video File"
+msgstr "保存已导出的视频文件"
 
-#: tempo_map_importer.cc:52
-msgid "Tempo map"
-msgstr "节奏映射"
+#: export_video_infobox.cc:33
+msgid "Video Export Info"
+msgstr "视频导出信息"
 
-#: tempo_map_importer.cc:60
-msgid "Tempo Map"
-msgstr "节奏映射"
+#: export_video_infobox.cc:34
+msgid "Do Not Show This Dialog Again (Reset in Edit > Preferences > Video)."
+msgstr "不再显示这个对话框。(可在 编辑 > 首选项 > 视频 里重置)。"
 
-#: tempo_map_importer.cc:80
-msgid "Tempo marks: "
-msgstr "节奏标签"
+#: export_video_infobox.cc:46
+msgid "<b>Video Export Info</b>"
+msgstr "<b>视频导出信息</b>"
 
-#: tempo_map_importer.cc:80
+#: export_video_infobox.cc:51
 msgid ""
+"Video encoding is a non-trivial task with many details.\n"
 "\n"
-"Meter marks: "
+"Please see the manual at %1/video-timeline/operations/#export.\n"
+"\n"
+"Open Manual in Browser? "
 msgstr ""
+"视频编码是一项带有许多细节的不简单的任务。\n"
+"\n"
+"请参阅手册,位于 %1/video-timeline/operations/#export 。\n"
 "\n"
-"Meter marks: "
+"在浏览器里打开手册?"
 
-#: tempo_map_importer.cc:89
-msgid ""
-"This will replace the current tempo map!\n"
-"Are you sure you want to do this?"
-msgstr ""
+#~ msgid "Track mode:"
+#~ msgstr "音轨模式:"
 
-#: user_bundle.cc:47
-msgid "Node for Bundle has no \"name\" property"
-msgstr "绑定的符号没有名称属性"
+#~ msgid "Theme Manager"
+#~ msgstr "主题管理"
 
-#: user_bundle.cc:59 user_bundle.cc:80
-#, c-format
-msgid "Unknown node \"%s\" in Bundle"
-msgstr ""
+#~ msgid "Errors"
+#~ msgstr "错误"
 
-#: user_bundle.cc:64
-msgid "Node for Channel has no \"name\" property"
-msgstr "声道的符号没有名称属性"
+#~ msgid "Play Selected Range"
+#~ msgstr "播放已选择的范围"
 
-#: user_bundle.cc:70
-msgid "Node for Channel has no \"type\" property"
-msgstr "声道的符号没有类型属性"
+#~ msgid "Convert to Region In-Place"
+#~ msgstr "在此转换至区域"
 
-#: user_bundle.cc:85
-msgid "Node for Port has no \"name\" property"
-msgstr "端口的符号没有名称属性"
+#~ msgid "Set Loop from Range"
+#~ msgstr "从范围设置循环"
 
-#: utils.cc:422 utils.cc:451
-msgid "Splice"
-msgstr ""
+#~ msgid "Set Punch from Range"
+#~ msgstr "从范围设置Punch"
 
-#: utils.cc:424 utils.cc:441
-msgid "Slide"
-msgstr ""
+#~ msgid "Draw/Edit MIDI Notes"
+#~ msgstr "绘画/编辑MIDI音符"
 
-#: utils.cc:426 utils.cc:447
-msgid "Ripple"
-msgstr ""
+#~ msgid "Draw Region Gain"
+#~ msgstr "绘制区域增益"
 
-#: utils.cc:428 utils.cc:444
-msgid "Lock"
-msgstr ""
+#~ msgid "Select Zoom Range"
+#~ msgstr "选择变焦范围"
 
-#: utils.cc:431
-msgid "programming error: unknown edit mode string \"%1\""
-msgstr "程序错误: 无法识别编辑模式字符串 \"%1\""
+#~ msgid "Stretch/Shrink Regions and MIDI Notes"
+#~ msgstr "伸/缩区域和MIDI音符"
 
-#: utils.cc:458 utils.cc:490
-msgid "MIDI Timecode"
-msgstr "MIDI时间码"
+#~ msgid "Listen to Specific Regions"
+#~ msgstr "听特定区域"
 
-#: utils.cc:458 utils.cc:488
-msgid "MTC"
-msgstr "MTC"
+#~ msgid "Set Punch from Edit Range"
+#~ msgstr "在编辑范围设置Punch"
 
-#: utils.cc:462 utils.cc:497
-msgid "MIDI Clock"
-msgstr "MIDI时钟"
+#~ msgid "Edit MIDI"
+#~ msgstr "编辑MIDI"
 
-#: utils.cc:466 utils.cc:484 utils.cc:504
-msgid "JACK"
-msgstr ""
+#~ msgid "Show Measures"
+#~ msgstr "显示测量"
 
-#: utils.cc:470
-msgid "programming error: unknown sync source string \"%1\""
-msgstr "程序错误: 无法识别同步源字符串 \"%1\""
+#~ msgid " range"
+#~ msgstr "范围"
 
-#: utils.cc:495
-msgid "M-Clock"
-msgstr ""
+#~ msgid "set loop range from edit range"
+#~ msgstr "从编辑范围设置循环范围"
 
-#: utils.cc:501
-msgid "LTC"
-msgstr ""
+#~ msgid "set punch range from edit range"
+#~ msgstr "从编辑范围设置punch区间"
 
-#: utils.cc:671
-msgid "programming error: unknown native header format: %1"
-msgstr ""
+#~ msgid ""
+#~ "Do you really want to remove %1 %2?\n"
+#~ "\n"
+#~ "This action cannot be undon, and the session file will be overwritten"
+#~ msgstr ""
+#~ "你确定移除 %1 %2?\n"
+#~ "\n"
+#~ "此动作不可撤销, 而且此会话文件将会被重新写入!"
+
+#~ msgid "set selected regions"
+#~ msgstr "设置所选区域"
+
+#~ msgid "select all"
+#~ msgstr "选择所有"
+
+#~ msgid "select all within"
+#~ msgstr "在内选择所有"
+
+#~ msgid "set selection from range"
+#~ msgstr "从范围设置选区"
+
+#~ msgid "select all from range"
+#~ msgstr "从范围选择所有"
+
+#~ msgid "select all from punch"
+#~ msgstr "从punch选择所有"
+
+#~ msgid "select all from loop"
+#~ msgstr "从循环选择所有"
+
+#~ msgid "select all after cursor"
+#~ msgstr "在光标后选择所有"
+
+#~ msgid "select all before cursor"
+#~ msgstr "在光标前选择所有"
+
+#~ msgid "select all after edit"
+#~ msgstr "编辑后选择所有"
+
+#~ msgid "select all before edit"
+#~ msgstr "编辑前选择所有"
+
+#~ msgid "Plugin preset %1 not found"
+#~ msgstr "未找到插件预设%1"
+
+#~ msgid "Set volume (velocity) to forteissimo"
+#~ msgstr "设置音量(力度)为极强音"
+
+#~ msgid "Set volume (velocity) to forteississimo"
+#~ msgstr "设置音量(力度)为最强音"
+
+#~ msgid "badly formatted UI definition file: %1"
+#~ msgstr "错误的用户界面格式文件 %1"
+
+#~ msgid ""
+#~ "There are insufficient JACK ports available\n"
+#~ "to create a new track or bus.\n"
+#~ "You should save %1, exit and\n"
+#~ "restart JACK with more ports."
+#~ msgstr ""
+#~ "JACK端口(port)不足\n"
+#~ "无法继续新建音轨或总线\n"
+#~ "请保存 %1,重新启动JACK带来更多的端口.\n"
+
+#~ msgid "Timecode Frames"
+#~ msgstr "时间码框架"
+
+#~ msgid "Timecode Seconds"
+#~ msgstr "时间码秒"
+
+#~ msgid "Timecode Minutes"
+#~ msgstr "时间码分"
+
+#~ msgid "Slowest"
+#~ msgstr "最慢"
+
+#~ msgid "insert dragged region"
+#~ msgstr "插入拖拽区域"
+
+#~ msgid " objects"
+#~ msgstr "对象"
+
+#~ msgid "No edit range defined"
+#~ msgstr "没有定义的编辑范围"
+
+#~ msgid ""
+#~ "the edit point is Selected Marker\n"
+#~ "but there is no selected marker."
+#~ msgstr ""
+#~ "这个编辑点是已选择的标记,\n"
+#~ "但是没有已选择的标记."
+
+#~ msgid "Position of mark on the ruler"
+#~ msgstr "标尺的标记位置"
+
+#~ msgid "Max Size"
+#~ msgstr "最大化尺寸"
+
+#~ msgid "Maximum size of the ruler"
+#~ msgstr "标尺的最大化尺寸"
+
+#~ msgid "Show Position"
+#~ msgstr "显示位置"
+
+#~ msgid "Draw current ruler position"
+#~ msgstr "绘制当前标尺位置"
+
+#~ msgid "cannot open pango.rc file %1"
+#~ msgstr "无法打开pango.rc 文件 %1"
+
+#~ msgid "Missing File!"
+#~ msgstr "找不到文件!"
+
+#~ msgid "auditioning"
+#~ msgstr "监听中"
+
+#~ msgid "mono"
+#~ msgstr "单声道"
+
+#~ msgid "Link selection of regions and tracks"
+#~ msgstr "链接所选的区域和音轨"
+
+#~ msgid "ardour"
+#~ msgstr "ardour"
+
+#~ msgid "x1"
+#~ msgstr "x1"
+
+#~ msgid "x coordinate of upper left corner of rect"
+#~ msgstr "x与矩形的左上角相关"
+
+#~ msgid "y1"
+#~ msgstr "y1"
+
+#~ msgid "y coordinate of upper left corner of rect "
+#~ msgstr "y与矩形的右下角相关"
+
+#~ msgid "x2"
+#~ msgstr "x1"
+
+#~ msgid "x coordinate of lower right corner of rect"
+#~ msgstr "x与矩形的右下角相关"
+
+#~ msgid "y coordinate of lower right corner of rect "
+#~ msgstr "y与矩形的右下角相关"
+
+#~ msgid "color rgba"
+#~ msgstr "RGBA颜色"
+
+#~ msgid "color of line"
+#~ msgstr "线条颜色"
+
+#~ msgid "outline pixels"
+#~ msgstr "轮廓像素"
+
+#~ msgid "width in pixels of outline"
+#~ msgstr "轮廓的像素宽度"
+
+#~ msgid "fill"
+#~ msgstr "å¡«å……"
+
+#~ msgid "fill rectangle"
+#~ msgstr "填充矩形"
+
+#~ msgid "draw"
+#~ msgstr "绘制"
+
+#~ msgid "draw rectangle"
+#~ msgstr "绘制矩形"
+
+#~ msgid "outline color rgba"
+#~ msgstr "RGBA轮廓颜色"
+
+#~ msgid "color of outline"
+#~ msgstr "落括的颜色"
+
+#~ msgid "fill color rgba"
+#~ msgstr "填充RGBA颜色"
+
+#~ msgid "color of fill"
+#~ msgstr "填充的颜色"
+
+#~ msgid "Auditioning of MIDI files is not yet supported"
+#~ msgstr "暂不支持监听MIDI文件"
+
+#~ msgid "Starting audio engine"
+#~ msgstr "启动音频引擎"
+
+#~ msgid "disconnected"
+#~ msgstr "取消连接"
+
+#~ msgid ""
+#~ "%1 is not connected to JACK\n"
+#~ "You cannot open or close sessions in this condition"
+#~ msgstr ""
+#~ "%1 未连接到 JACK.\n"
+#~ "再此情况下,你无法打开或关闭会话"
+
+#~ msgid ""
+#~ "The audio backend (JACK) was shutdown because:\n"
+#~ "\n"
+#~ "%1"
+#~ msgstr ""
+#~ "音频后台(JACK)关闭了,原因如下:\n"
+#~ "\n"
+#~ "%1"
+
+#~ msgid ""
+#~ "JACK has either been shutdown or it\n"
+#~ "disconnected %1 because %1\n"
+#~ "was not fast enough. Try to restart\n"
+#~ "JACK, reconnect and save the session."
+#~ msgstr ""
+#~ "JACK 被关闭了,或与 %1 失去了连接\n"
+#~ "原因是 %1 不够快.\n"
+#~ "尝试重启JACK,重新连接并且保存会话."
+
+#~ msgid "Unable to start the session running"
+#~ msgstr "无法启动会话"
+
+#~ msgid "Click the Refresh button to try again."
+#~ msgstr "单击刷新按钮,再尝试一遍"
+
+#~ msgid "Could not disconnect from JACK"
+#~ msgstr "无法断开JACK的连接"
+
+#~ msgid "Could not reconnect to JACK"
+#~ msgstr "无法重新连接到JACK"
+
+#~ msgid "JACK"
+#~ msgstr "JACK"
+
+#~ msgid "Reconnect"
+#~ msgstr "重新链接"
+
+#~ msgid "JACK Sampling Rate and Latency"
+#~ msgstr "JACK采样率和延迟"
+
+#~ msgid "Realtime"
+#~ msgstr "实时"
+
+#~ msgid "Do not lock memory"
+#~ msgstr "不锁内存"
+
+#~ msgid "Unlock memory"
+#~ msgstr "解锁内存"
+
+#~ msgid "8000Hz"
+#~ msgstr "8000 Hz"
+
+#~ msgid "22050Hz"
+#~ msgstr "22050 Hz"
+
+#~ msgid "44100Hz"
+#~ msgstr "44100 Hz"
+
+#~ msgid "48000Hz"
+#~ msgstr "48000 Hz"
+
+#~ msgid "88200Hz"
+#~ msgstr "88200 Hz"
+
+#~ msgid "96000Hz"
+#~ msgstr "96000 Hz"
+
+#~ msgid "192000Hz"
+#~ msgstr "192000 Hz"
+
+#~ msgid "Triangular"
+#~ msgstr "三角形"
+
+#~ msgid "Rectangular"
+#~ msgstr "矩形"
+
+#~ msgid "Shaped"
+#~ msgstr "形状"
+
+#~ msgid "Playback/recording on 1 device"
+#~ msgstr "在设备1 播放/录音"
+
+#~ msgid "Playback/recording on 2 devices"
+#~ msgstr "在设备2 播放/录音"
+
+#~ msgid "Playback only"
+#~ msgstr "仅播放"
+
+#~ msgid "Recording only"
+#~ msgstr "仅录音"
+
+#~ msgid "Number of buffers:"
+#~ msgstr "缓冲区数量:"
+
+#~ msgid "Approximate latency:"
+#~ msgstr "大约延迟:"
+
+#~ msgid "Audio mode:"
+#~ msgstr "音频模式:"
+
+#~ msgid "Ignore"
+#~ msgstr "忽略"
+
+#~ msgid "Client timeout"
+#~ msgstr "客户端超时"
+
+#~ msgid "Number of ports:"
+#~ msgstr "端口数量:"
+
+#~ msgid "MIDI driver:"
+#~ msgstr "MIDI驱动:"
+
+#~ msgid ""
+#~ "No JACK server found anywhere on this system. Please install JACK and restart"
+#~ msgstr ""
+#~ "No JACK server found anywhere on this system. Please install JACK and restart"
+
+#~ msgid "Server:"
+#~ msgstr "服务器:"
+
+#~ msgid "Input device:"
+#~ msgstr "输入设备:"
+
+#~ msgid "Output device:"
+#~ msgstr "输出设备:"
+
+#~ msgid "Advanced"
+#~ msgstr "高级"
+
+#~ msgid "cannot open JACK rc file %1 to store parameters"
+#~ msgstr "无法打开JACK的rc文件%1来储存参数"
+
+#~ msgid "No suitable audio devices"
+#~ msgstr "没有合适的音频设备"
+
+#~ msgid "JACK appears to be missing from the %1 bundle"
+#~ msgstr "JACK%1"
+
+#~ msgid "You need to choose an audio device first."
+#~ msgstr "你需要先选择一个音频设备"
+
+#~ msgid "Audio device \"%1\" not known on this computer."
+#~ msgstr "电脑无法识别音频设备 %1"
+
+#~ msgid "%1 could not connect to JACK."
+#~ msgstr "%1 无法连接到JACK"
+
+#~ msgid "JACK exited"
+#~ msgstr "JACK已经退出"
+
+#~ msgid ""
+#~ "JACK exited unexpectedly, and without notifying %1.\n"
+#~ "\n"
+#~ "This could be due to misconfiguration or to an error inside JACK.\n"
+#~ "\n"
+#~ "Click OK to exit %1."
+#~ msgstr ""
+#~ "JACK出乎意料地退出了, 没有任何报告 %1.\n"
+#~ "\n"
+#~ "这可能是微配置或JACK里面的错误.\n"
+#~ "\n"
+#~ "单击OK退出 %1."
+
+#~ msgid ""
+#~ "JACK exited unexpectedly, and without notifying %1.\n"
+#~ "\n"
+#~ "This is probably due to an error inside JACK. You should restart JACK\n"
+#~ "and reconnect %1 to it, or exit %1 now. You cannot save your\n"
+#~ "session at this time, because we would lose your connection information.\n"
+#~ msgstr ""
+#~ "JACK出乎意料地退出了, 没有任何报告 %1.\n"
+#~ "\n"
+#~ "这可能是JACK里面的错误. 你最好重启JACK\n"
+#~ "然后连接到%1, 或者现在退出%1.\n"
+#~ "现在你没办法保存会话, 因为你的连接信息可能会丢失.\n"
+
+#~ msgid ""
+#~ "  -c, --name <name>           Use a specific jack client name, default is "
+#~ "ardour\n"
+#~ msgstr ""
+#~ "  -c, --name <name>           用一个特殊的JACK用户名称, 默认名称是: ardour\n"
+
+#~ msgid "follows order of editor"
+#~ msgstr "编辑器的如下顺序"
+
+#~ msgid "Open an existing session"
+#~ msgstr "打开一个已存在的会话"
+
+#~ msgid "I'd like more options for this session"
+#~ msgstr "我想要关于这个会话的更多选项"
+
+#~ msgid "Audio / MIDI Setup"
+#~ msgstr "音频/MIDI设置"
 
-#: utils.cc:686
-msgid "cannot open directory %1 (%2)"
-msgstr "无法打开目录 %1 (%2)"
+#~ msgid "Use an existing session as a template:"
+#~ msgstr "使用一个存在的会话当作模板"
 
-#~ msgid "master"
-#~ msgstr "主控"
+#~ msgid "Select template"
+#~ msgstr "选择模板"
 
-#~ msgid "Could not resolve path: %1 (%2)"
-#~ msgstr "无法解决路径: %1 (%2)"
+#~ msgid "Browse:"
+#~ msgstr "浏览:"
 
-#~ msgid "LADSPA: cannot load module from \"%1\""
-#~ msgstr "LADSPA: 无法从 \"%1\" 载入模块"
+#~ msgid "Select a session"
+#~ msgstr "选择一个会话"
 
-#~ msgid "Cannot expand path %1 (%2)"
-#~ msgstr "无法扩展路径 %1 (%2)"
+#~ msgid "Advanced Session Options"
+#~ msgstr "高级会话选项"
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 46d54cd..ce34048 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -172,10 +172,10 @@ PortInsert::state (bool full)
 	node.add_property ("type", "port");
 	snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
 	node.add_property ("bitslot", buf);
-        snprintf (buf, sizeof (buf), "%" PRId64, _measured_latency);
-        node.add_property("latency", buf);
-        snprintf (buf, sizeof (buf), "%u", _session.get_block_size());
-        node.add_property("block_size", buf);
+	snprintf (buf, sizeof (buf), "%" PRId64, _measured_latency);
+	node.add_property("latency", buf);
+	snprintf (buf, sizeof (buf), "%u", _session.get_block_size());
+	node.add_property("block-size", buf);
 
 	return node;
 }
@@ -210,17 +210,17 @@ PortInsert::set_state (const XMLNode& node, int version)
 		return -1;
 	}
 
-        uint32_t blocksize = 0;
-        if ((prop = node.property ("block_size")) != 0) {
-                sscanf (prop->value().c_str(), "%u", &blocksize);
-        }
+	uint32_t blocksize = 0;
+	if ((prop = node.property ("block-size")) != 0) {
+		sscanf (prop->value().c_str(), "%u", &blocksize);
+	}
 
-        //if the jack period is the same as when the value was saved, we can recall our latency..
-        if ( (_session.get_block_size() == blocksize) && (prop = node.property ("latency")) != 0) {
-                uint32_t latency = 0;
-                sscanf (prop->value().c_str(), "%u", &latency);
-                _measured_latency = latency;
-        }
+	//if the jack period is the same as when the value was saved, we can recall our latency..
+	if ( (_session.get_block_size() == blocksize) && (prop = node.property ("latency")) != 0) {
+		uint32_t latency = 0;
+		sscanf (prop->value().c_str(), "%u", &latency);
+		_measured_latency = latency;
+	}
 
 	if (!node.property ("ignore-bitslot")) {
 		if ((prop = node.property ("bitslot")) == 0) {
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 516adb6..bd99403 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -591,6 +591,44 @@ Region::set_position (framepos_t pos)
 
 }
 
+/** A gui may need to create a region, then place it in an initial
+ *  position determined by the user.
+ *  When this takes place within one gui operation, we have to reset
+ *  _last_position to prevent an implied move.
+ */
+void
+Region::set_initial_position (framepos_t pos)
+{
+	if (!can_move()) {
+		return;
+	}
+
+	if (_position != pos) {
+		_position = pos;
+
+		/* check that the new _position wouldn't make the current
+		   length impossible - if so, change the length.
+
+		   XXX is this the right thing to do?
+		*/
+
+		if (max_framepos - _length < _position) {
+			_last_length = _length;
+			_length = max_framepos - _position;
+		}
+
+		recompute_position_from_lock_style ();
+		/* ensure that this move doesn't cause a range move */
+		_last_position = _position;
+	}
+
+
+	/* do this even if the position is the same. this helps out
+	   a GUI that has moved its representation already.
+	*/
+	send_change (Properties::position);
+}
+
 void
 Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute)
 {
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index c3b09df..cb1af7f 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -135,12 +135,15 @@ Route::init ()
 
 	_solo_control.reset (new SoloControllable (X_("solo"), shared_from_this ()));
 	_mute_control.reset (new MuteControllable (X_("mute"), shared_from_this ()));
+	_phase_control.reset (new PhaseControllable (X_("phase"), shared_from_this ()));
 
 	_solo_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle));
 	_mute_control->set_flags (Controllable::Flag (_mute_control->flags() | Controllable::Toggle));
+	_phase_control->set_flags (Controllable::Flag (_phase_control->flags() | Controllable::Toggle));
 
 	add_control (_solo_control);
 	add_control (_mute_control);
+	add_control (_phase_control);
 
 	/* panning */
 
@@ -171,6 +174,10 @@ Route::init ()
 	_amp.reset (new Amp (_session));
 	add_processor (_amp, PostFader);
 
+	if (is_monitor ()) {
+		_amp->set_display_name (_("Monitor"));
+	}
+
 	/* and input trim */
 	_trim.reset (new Amp (_session, "trim"));
 	_trim->set_display_to_user (false);
@@ -884,7 +891,6 @@ Route::set_solo (bool yn, void *src, bool group_override)
 
 	if (self_soloed() != yn) {
 		set_self_solo (yn);
-		set_mute_master_solo ();
 		solo_changed (true, src, group_override); /* EMIT SIGNAL */
 		_solo_control->Changed (); /* EMIT SIGNAL */
 	}
@@ -905,6 +911,7 @@ Route::set_self_solo (bool yn)
 {
 	DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: set SELF solo => %2\n", name(), yn));
 	_self_solo = yn;
+	set_mute_master_solo ();
 }
 
 void
@@ -1933,6 +1940,37 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err)
 		if ((*p)->can_support_io_configuration(in, out)) {
 			DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 ID=%2 in=%3 out=%4\n",(*p)->name(), (*p)->id(), in, out));
 			configuration.push_back(make_pair(in, out));
+
+			if (is_monitor()) {
+				// restriction for Monitor Section Processors
+				if (in.n_audio() != out.n_audio() || out.n_midi() > 0) {
+					/* do not allow to add/remove channels (for now)
+					 * The Monitor follows the master-bus and has no panner (unpan)
+					 * but do allow processors with midi-in to be added (e.g VSTs with control that
+					 * will remain unconnected)
+					 */
+					DEBUG_TRACE (DEBUG::Processors, "Monitor: Channel configuration not allowed.\n");
+					return list<pair<ChanCount, ChanCount> > ();
+				}
+				if (boost::dynamic_pointer_cast<InternalSend> (*p)) {
+					// internal sends make no sense, only feedback
+					DEBUG_TRACE (DEBUG::Processors, "Monitor: No Sends allowed.\n");
+					return list<pair<ChanCount, ChanCount> > ();
+				}
+				if (boost::dynamic_pointer_cast<PortInsert> (*p)) {
+					/* External Sends can be problematic. one can add/remove ports
+					 * there signal leaves the DAW to external monitors anyway, so there's
+					 * no real use for allowing them here anyway.
+					 */
+					DEBUG_TRACE (DEBUG::Processors, "Monitor: No External Sends allowed.\n");
+					return list<pair<ChanCount, ChanCount> > ();
+				}
+				if (boost::dynamic_pointer_cast<Send> (*p)) {
+					// ditto
+					DEBUG_TRACE (DEBUG::Processors, "Monitor: No Sends allowed.\n");
+					return list<pair<ChanCount, ChanCount> > ();
+				}
+			}
 			in = out;
 		} else {
 			if (err) {
@@ -2245,6 +2283,11 @@ Route::get_template()
 XMLNode&
 Route::state(bool full_state)
 {
+	if (!_session._template_state_dir.empty()) {
+		assert (!full_state); // only for templates
+		foreach_processor (sigc::bind (sigc::mem_fun (*this, &Route::set_plugin_state_dir), _session._template_state_dir));
+	}
+
 	XMLNode *node = new XMLNode("Route");
 	ProcessorList::iterator i;
 	char buf[32];
@@ -2339,6 +2382,10 @@ Route::state(bool full_state)
 		}
 	}
 
+	if (!_session._template_state_dir.empty()) {
+		foreach_processor (sigc::bind (sigc::mem_fun (*this, &Route::set_plugin_state_dir), ""));
+	}
+
 	return *node;
 }
 
@@ -2752,7 +2799,7 @@ Route::set_state_2X (const XMLNode& node, int version)
 				gain_t val;
 
 				if (sscanf (prop->value().c_str(), "%f", &val) == 1) {
-					_amp->gain_control()->set_value (val);
+					_amp->gain_control()->set_value (val, Controllable::NoGroup);
 				}
 			}
 
@@ -3833,20 +3880,92 @@ Route::set_latency_compensation (framecnt_t longest_session_latency)
 	}
 }
 
-Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
-	: AutomationControl (r->session(),
-	                     Evoral::Parameter (SoloAutomation),
-	                     ParameterDescriptor(Evoral::Parameter (SoloAutomation)),
-	                     boost::shared_ptr<AutomationList>(), name)
+void
+Route::set_control (RouteAutomationControl& control, double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
+{
+	boost::shared_ptr<RouteList> rl;
+
+	switch (control.parameter().type()) {
+	case GainAutomation:
+		/* route must mediate group control */
+		set_gain (val, this); /* any "src" argument will do other than our route group */
+		return;
+		break;
+
+	case RecEnableAutomation:
+		/* session must mediate group control */
+		rl.reset (new RouteList);
+		rl->push_back (shared_from_this());
+		_session.set_record_enabled (rl, val >= 0.5 ? true : false);
+		return;
+		break;
+
+	case SoloAutomation:
+		/* session must mediate group control */
+		rl.reset (new RouteList);
+		rl->push_back (shared_from_this());
+		if (Config->get_solo_control_is_listen_control()) {
+			_session.set_listen (rl, val >= 0.5 ? true : false);
+		} else {
+			_session.set_solo (rl, val >= 0.5 ? true : false);
+		}
+
+		return;
+		break;
+
+	case MuteAutomation:
+		/* session must mediate group control */
+		rl.reset (new RouteList);
+		rl->push_back (shared_from_this());
+		_session.set_mute (rl, !muted());
+		return;
+		break;
+
+	case PanAzimuthAutomation:
+	case PanElevationAutomation:
+	case PanWidthAutomation:
+	case PanFrontBackAutomation:
+	case PanLFEAutomation:
+		break;
+
+	default:
+		/* Not a route automation control */
+		return;
+	}
+
+	control.route_set_value (val);
+}
+
+
+Route::RouteAutomationControl::RouteAutomationControl (const std::string& name,
+                                                       AutomationType atype,
+                                                       boost::shared_ptr<AutomationList> alist,
+                                                       boost::shared_ptr<Route> r)
+	: AutomationControl (r->session(), Evoral::Parameter (atype),
+	                     ParameterDescriptor (Evoral::Parameter (atype)),
+	                     alist, name)
 	, _route (r)
 {
+}
+
+Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
+	: RouteAutomationControl (name, SoloAutomation, boost::shared_ptr<AutomationList>(), r)
+{
 	boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
 	gl->set_interpolation(Evoral::ControlList::Discrete);
 	set_list (gl);
 }
 
 void
-Route::SoloControllable::set_value (double val)
+Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+{
+	if (writable()) {
+		set_value_unchecked (val);
+	}
+}
+
+void
+Route::SoloControllable::set_value_unchecked (double val)
 {
 	const bool bval = ((val >= 0.5) ? true : false);
 
@@ -3882,11 +4001,7 @@ Route::SoloControllable::get_value () const
 }
 
 Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr<Route> r)
-	: AutomationControl (r->session(),
-	                     Evoral::Parameter (MuteAutomation),
-	                     ParameterDescriptor (Evoral::Parameter (MuteAutomation)),
-	                     boost::shared_ptr<AutomationList>(),
-	                     name)
+	: RouteAutomationControl (name, MuteAutomation, boost::shared_ptr<AutomationList>(), r)
 	, _route (r)
 {
 	boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
@@ -3900,13 +4015,34 @@ Route::MuteControllable::set_superficial_value(bool muted)
 	/* Note we can not use AutomationControl::set_value here since it will emit
 	   Changed(), but the value will not be correct to the observer. */
 
-	bool to_list = _list && ((AutomationList*)_list.get())->automation_write();
+	const bool to_list = _list && ((AutomationList*)_list.get ())->automation_write ();
+	const double where = _session.audible_frame ();
+	if (to_list) {
+		/* Note that we really need this:
+		 *  if (as == Touch && _list->in_new_write_pass ()) {
+		 *       alist->start_write_pass (_session.audible_frame ());
+		 *  }
+		 * here in the case of the user calling from a GUI or whatever.
+		 * Without the ability to distinguish between user and
+		 * automation-initiated changes, we lose the "touch mute"
+		 * behaviour we have in AutomationController::toggled ().
+		 */
+		_list->set_in_write_pass (true, false, where);
+	}
+
+	Control::set_double (muted, where, to_list);
+}
 
-	Control::set_double (muted, _session.transport_frame(), to_list);
+void
+Route::MuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /* group_override */)
+{
+	if (writable()) {
+		set_value_unchecked (val);
+	}
 }
 
 void
-Route::MuteControllable::set_value (double val)
+Route::MuteControllable::set_value_unchecked (double val)
 {
 	const bool bval = ((val >= 0.5) ? true : false);
 
@@ -3916,6 +4052,8 @@ Route::MuteControllable::set_value (double val)
 	}
 
 	if (_list && ((AutomationList*)_list.get())->automation_playback()) {
+		// Set superficial/automation value to drive controller (and possibly record)
+		set_superficial_value (bval);
 		// Playing back automation, set route mute directly
 		r->set_mute (bval, this);
 	} else {
@@ -3924,9 +4062,6 @@ Route::MuteControllable::set_value (double val)
 		rl->push_back (r);
 		_session.set_mute (rl, bval, Session::rt_cleanup);
 	}
-
-	// Set superficial/automation value to drive controller (and possibly record)
-	set_superficial_value(bval);
 }
 
 double
@@ -3942,6 +4077,46 @@ Route::MuteControllable::get_value () const
 	return (r && r->muted()) ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
 }
 
+Route::PhaseControllable::PhaseControllable (std::string name, boost::shared_ptr<Route> r)
+	: RouteAutomationControl (name, PhaseAutomation, boost::shared_ptr<AutomationList>(), r)
+{
+	boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(PhaseAutomation)));
+	gl->set_interpolation(Evoral::ControlList::Discrete);
+	set_list (gl);
+}
+
+void
+Route::PhaseControllable::set_value (double v, PBD::Controllable::GroupControlDisposition /* group_override */)
+{
+	boost::shared_ptr<Route> r = _route.lock ();
+	if (r->phase_invert().size()) {
+		if (v == 0 || (v < 1 && v > 0.9) ) {
+			r->set_phase_invert (_current_phase, false);
+		} else {
+			r->set_phase_invert (_current_phase, true);
+		}
+	}
+}
+
+double
+Route::PhaseControllable::get_value () const
+{
+	boost::shared_ptr<Route> r = _route.lock ();
+	return (double) r->phase_invert (_current_phase);
+}
+
+void
+Route::PhaseControllable::set_channel (uint32_t c)
+{
+	_current_phase = c;
+}
+
+uint32_t
+Route::PhaseControllable::channel () const
+{
+	return _current_phase;
+}
+
 void
 Route::set_block_size (pframes_t nframes)
 {
@@ -4044,17 +4219,33 @@ Route::shift (framepos_t pos, framecnt_t frames)
 	}
 }
 
+void
+Route::set_plugin_state_dir (boost::weak_ptr<Processor> p, const std::string& d)
+{
+	boost::shared_ptr<Processor> processor (p.lock ());
+	boost::shared_ptr<PluginInsert> pi  = boost::dynamic_pointer_cast<PluginInsert> (processor);
+	if (!pi) {
+		return;
+	}
+	pi->set_state_dir (d);
+}
 
 int
 Route::save_as_template (const string& path, const string& name)
 {
+	std::string state_dir = path.substr (0, path.find_last_of ('.')); // strip template_suffix
+	PBD::Unwinder<std::string> uw (_session._template_state_dir, state_dir);
+
 	XMLNode& node (state (false));
+
 	XMLTree tree;
 
 	IO::set_name_in_state (*node.children().front(), name);
 
 	tree.set_root (&node);
-	return tree.write (path.c_str());
+
+	/* return zero on success, non-zero otherwise */
+	return !tree.write (path.c_str());
 }
 
 
@@ -4095,7 +4286,7 @@ Route::set_name (const string& str)
  *  @param name New name.
  */
 void
-Route::set_name_in_state (XMLNode& node, string const & name)
+Route::set_name_in_state (XMLNode& node, string const & name, bool rename_playlist)
 {
 	node.add_property (X_("name"), name);
 
@@ -4115,7 +4306,9 @@ Route::set_name_in_state (XMLNode& node, string const & name)
 
 		} else if ((*i)->name() == X_("Diskstream")) {
 
-			(*i)->add_property (X_("playlist"), string_compose ("%1.1", name).c_str());
+			if (rename_playlist) {
+				(*i)->add_property (X_("playlist"), string_compose ("%1.1", name).c_str());
+			}
 			(*i)->add_property (X_("name"), name);
 
 		}
@@ -4639,7 +4832,7 @@ Route::setup_invisible_processors ()
 
 	if (_monitor_control && is_monitor ()) {
 		assert (!_monitor_control->display_to_user ());
-		new_processors.push_front (_monitor_control);
+		new_processors.insert (amp, _monitor_control);
 	}
 
 	/* INTERNAL RETURN */
@@ -4919,3 +5112,362 @@ Route::fill_buffers_with_input (BufferSet& bufs, boost::shared_ptr<IO> io, pfram
 		bufs.set_count (io->n_ports());
 	}
 }
+
+boost::shared_ptr<AutomationControl>
+Route::pan_azimuth_control() const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<ARDOUR::PluginInsert> plug = ch_post();
+	assert (plug);
+	const uint32_t port_channel_post_pan = 2; // gtk2_ardour/mixbus_ports.h
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (plug->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, port_channel_post_pan)));
+#else
+	if (!_pannable || !panner()) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+	return _pannable->pan_azimuth_control;
+#endif
+}
+
+boost::shared_ptr<AutomationControl>
+Route::pan_elevation_control() const
+{
+	if (Profile->get_mixbus() || !_pannable || !panner()) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	set<Evoral::Parameter> c = panner()->what_can_be_automated ();
+
+	if (c.find (PanElevationAutomation) != c.end()) {
+		return _pannable->pan_elevation_control;
+	} else {
+		return boost::shared_ptr<AutomationControl>();
+	}
+}
+boost::shared_ptr<AutomationControl>
+Route::pan_width_control() const
+{
+	if (Profile->get_mixbus() || !_pannable || !panner()) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	set<Evoral::Parameter> c = panner()->what_can_be_automated ();
+
+	if (c.find (PanWidthAutomation) != c.end()) {
+		return _pannable->pan_width_control;
+	} else {
+		return boost::shared_ptr<AutomationControl>();
+	}
+}
+boost::shared_ptr<AutomationControl>
+Route::pan_frontback_control() const
+{
+	if (Profile->get_mixbus() || !_pannable || !panner()) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	set<Evoral::Parameter> c = panner()->what_can_be_automated ();
+
+	if (c.find (PanFrontBackAutomation) != c.end()) {
+		return _pannable->pan_frontback_control;
+	} else {
+		return boost::shared_ptr<AutomationControl>();
+	}
+}
+boost::shared_ptr<AutomationControl>
+Route::pan_lfe_control() const
+{
+	if (Profile->get_mixbus() || !_pannable || !panner()) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	set<Evoral::Parameter> c = panner()->what_can_be_automated ();
+
+	if (c.find (PanLFEAutomation) != c.end()) {
+		return _pannable->pan_lfe_control;
+	} else {
+		return boost::shared_ptr<AutomationControl>();
+	}
+}
+
+uint32_t
+Route::eq_band_cnt () const
+{
+	if (Profile->get_mixbus()) {
+		return 3;
+	} else {
+		/* Ardour has no well-known EQ object */
+		return 0;
+	}
+}
+
+boost::shared_ptr<AutomationControl>
+Route::eq_gain_controllable (uint32_t band) const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> eq = ch_eq();
+
+	if (!eq) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	uint32_t port_number;
+	switch (band) {
+	case 0:
+		if (is_master() || mixbus()) {
+			port_number = 4;
+		} else {
+			port_number = 8;
+		}
+		break;
+	case 1:
+		if (is_master() || mixbus()) {
+			port_number = 3;
+		} else {
+			port_number = 6;
+		}
+		break;
+	case 2:
+		if (is_master() || mixbus()) {
+			port_number = 2;
+		} else {
+			port_number = 4;
+		}
+		break;
+	default:
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (eq->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, port_number)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+boost::shared_ptr<AutomationControl>
+Route::eq_freq_controllable (uint32_t band) const
+{
+#ifdef MIXBUS
+
+	if (mixbus() || is_master()) {
+		/* no frequency controls for mixbusses or master */
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	boost::shared_ptr<PluginInsert> eq = ch_eq();
+
+	if (!eq) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	uint32_t port_number;
+	switch (band) {
+	case 0:
+		port_number = 7;
+		break;
+	case 1:
+		port_number = 5;
+		break;
+	case 2:
+		port_number = 3;
+		break;
+	default:
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (eq->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, port_number)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+
+boost::shared_ptr<AutomationControl>
+Route::eq_q_controllable (uint32_t band) const
+{
+	return boost::shared_ptr<AutomationControl>();
+}
+
+boost::shared_ptr<AutomationControl>
+Route::eq_shape_controllable (uint32_t band) const
+{
+	return boost::shared_ptr<AutomationControl>();
+}
+
+boost::shared_ptr<AutomationControl>
+Route::eq_enable_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> eq = ch_eq();
+
+	if (!eq) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (eq->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 1)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+
+boost::shared_ptr<AutomationControl>
+Route::eq_hpf_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> eq = ch_eq();
+
+	if (!eq) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (eq->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 2)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+
+string
+Route::eq_band_name (uint32_t band) const
+{
+	if (Profile->get_mixbus()) {
+		switch (band) {
+		case 0:
+			return _("lo");
+		case 1:
+			return _("mid");
+		case 2:
+			return _("hi");
+		default:
+			return string();
+		}
+	} else {
+		return string ();
+	}
+}
+
+boost::shared_ptr<AutomationControl>
+Route::comp_enable_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> comp = ch_comp();
+
+	if (!comp) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (comp->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 1)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+boost::shared_ptr<AutomationControl>
+Route::comp_threshold_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> comp = ch_comp();
+
+	if (!comp) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (comp->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 2)));
+
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+boost::shared_ptr<AutomationControl>
+Route::comp_speed_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> comp = ch_comp();
+
+	if (!comp) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (comp->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 3)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+boost::shared_ptr<AutomationControl>
+Route::comp_mode_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> comp = ch_comp();
+
+	if (!comp) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (comp->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 4)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+boost::shared_ptr<AutomationControl>
+Route::comp_makeup_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> comp = ch_comp();
+
+	if (!comp) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (comp->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 5)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+boost::shared_ptr<AutomationControl>
+Route::comp_redux_controllable () const
+{
+#ifdef MIXBUS
+	boost::shared_ptr<PluginInsert> comp = ch_comp();
+
+	if (!comp) {
+		return boost::shared_ptr<AutomationControl>();
+	}
+
+	return boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (comp->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 6)));
+#else
+	return boost::shared_ptr<AutomationControl>();
+#endif
+}
+
+string
+Route::comp_mode_name (uint32_t mode) const
+{
+#ifdef MIXBUS
+	switch (mode) {
+	case 0:
+		return _("Leveler");
+	case 1:
+		return _("Compressor");
+	case 2:
+		return _("Limiter");
+	}
+
+	return _("???");
+#else
+	return _("???");
+#endif
+}
+
+string
+Route::comp_speed_name (uint32_t mode) const
+{
+#ifdef MIXBUS
+	switch (mode) {
+	case 0:
+		return _("Attk");
+	case 1:
+		return _("Ratio");
+	case 2:
+		return _("Rels");
+	}
+	return _("???");
+#else
+	return _("???");
+#endif
+}
diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc
index 032c85f..036aede 100644
--- a/libs/ardour/route_group.cc
+++ b/libs/ardour/route_group.cc
@@ -456,18 +456,26 @@ RouteGroup::make_subgroup (bool aux, Placement placement)
 
 	for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
 		if ((*i)->output()->n_ports().n_midi() != 0) {
-			PBD::info << _("You cannot subgroup MIDI tracks at this time") << endmsg;
+			PBD::warning << _("You cannot subgroup MIDI tracks at this time") << endmsg;
 			return;
 		}
 	}
 
 	for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
+		if (!aux && nin != 0 && nin != (*i)->output()->n_ports().n_audio()) {
+			PBD::warning << _("You cannot subgroup tracks with different number of outputs at this time.") << endmsg;
+			return;
+		}
 		nin = max (nin, (*i)->output()->n_ports().n_audio());
 	}
 
 	try {
-		/* use master bus etc. to determine default nouts */
-		rl = _session.new_audio_route (nin, 2, 0, 1);
+		/* use master bus etc. to determine default nouts.
+		 *
+		 * (since tracks can't have fewer outs than ins,
+		 * "nin" currently defines the number of outpus if nin > 2)
+		 */
+		rl = _session.new_audio_route (nin, 2 /*XXX*/, 0, 1);
 	} catch (...) {
 		return;
 	}
diff --git a/libs/ardour/run-session-tests.sh b/libs/ardour/run-session-tests.sh
deleted file mode 100755
index 034f8b5..0000000
--- a/libs/ardour/run-session-tests.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-#
-# Run simple session load tester over a corpus of sessions.
-#
-
-if [ ! -f './tempo.cc' ]; then
-    echo "This script must be run from within the libs/ardour directory";
-    exit 1;
-fi
-
-. test-env.sh
-
-f=""
-if [ "$1" == "--debug" -o "$1" == "--valgrind" ]; then
-  f=$1
-  shift 1
-fi
-
-d=$1
-if [ "$d" == "" ]; then
-  echo "Syntax: run-session-tests.sh <corpus>"
-  exit 1
-fi
-
-for s in `find $d -mindepth 1 -maxdepth 1 -type d`; do
-  n=`basename $s`
-  if [ "$f" == "--debug" ]; then
-    gdb --args ./libs/ardour/load-session $s $n
-  elif [ "$f" == "--valgrind" ]; then
-    valgrind ./libs/ardour/load-session $s $n
-  else
-    ./libs/ardour/load-session $s $n
-  fi
-done
-
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 1231212..7f467db 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -74,6 +74,7 @@
 #include "ardour/graph.h"
 #include "ardour/midiport_manager.h"
 #include "ardour/scene_changer.h"
+#include "ardour/midi_patch_manager.h"
 #include "ardour/midi_track.h"
 #include "ardour/midi_ui.h"
 #include "ardour/operations.h"
@@ -179,7 +180,7 @@ Session::Session (AudioEngine &eng,
 	, current_block_size (0)
 	, _worst_output_latency (0)
 	, _worst_input_latency (0)
- 	, _worst_track_latency (0)
+	, _worst_track_latency (0)
 	, _have_captured (false)
 	, _non_soloed_outs_muted (false)
 	, _listen_cnt (0)
@@ -316,6 +317,11 @@ Session::Session (AudioEngine &eng,
 			throw SessionException (_("Cannot connect to audio/midi engine"));
 		}
 
+		// set samplerate for plugins added early
+		// e.g from templates or MB channelstrip
+		set_block_size (_engine.samples_per_cycle());
+		set_frame_rate (_engine.sample_rate());
+
 		if (create (mix_template, bus_profile)) {
 			destroy ();
 			throw SessionException (_("Session initialization failed"));
@@ -543,6 +549,8 @@ Session::destroy ()
 
 	remove_pending_capture_state ();
 
+	Analyser::flush ();
+
 	_state_of_the_state = StateOfTheState (CannotSave|Deletion);
 
 	/* disconnect from any and all signals that we are connected to */
@@ -555,6 +563,8 @@ Session::destroy ()
 
 	ControlProtocolManager::instance().drop_protocols ();
 
+	MIDI::Name::MidiPatchManager::instance().remove_search_path(session_directory().midi_patch_path());
+
 	_engine.remove_session ();
 
 #ifdef USE_TRACKS_CODE_FEATURES
@@ -1012,6 +1022,7 @@ Session::remove_monitor_section ()
 	if (auditioner) {
 		auditioner->connect ();
 	}
+	Config->ParameterChanged ("use-monitor-bus");
 }
 
 void
@@ -1163,6 +1174,7 @@ Session::add_monitor_section ()
 	if (auditioner) {
 		auditioner->connect ();
 	}
+	Config->ParameterChanged ("use-monitor-bus");
 }
 
 void
@@ -2211,9 +2223,14 @@ Session::find_route_name (string const & base, uint32_t& id, string& name, bool
 
 	for (vector<string>::const_iterator reserved = reserved_io_names.begin(); reserved != reserved_io_names.end(); ++reserved) {
 		if (base == *reserved) {
-			definitely_add_number = true;
-			if (id < 1) {
-				id = 1;
+			/* Check if this reserved name already exists, and if
+			   so, disallow it without a numeric suffix.
+			*/
+			if (route_by_name (*reserved)) {
+				definitely_add_number = true;
+				if (id < 1) {
+					id = 1;
+				}
 			}
 			break;
 		}
@@ -3024,30 +3041,39 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
 }
 
 RouteList
-Session::new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name_base)
+Session::new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name_base, PlaylistDisposition pd)
 {
-	RouteList ret;
-	uint32_t control_id;
 	XMLTree tree;
-	uint32_t number = 0;
-	const uint32_t being_added = how_many;
 
 	if (!tree.read (template_path.c_str())) {
-		return ret;
+		return RouteList();
 	}
 
-	XMLNode* node = tree.root();
+	return new_route_from_template (how_many, *tree.root(), name_base, pd);
+}
 
+RouteList
+Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::string& name_base, PlaylistDisposition pd)
+{
+	RouteList ret;
+	uint32_t control_id;
+	uint32_t number = 0;
+	const uint32_t being_added = how_many;
+	/* This will prevent the use of any existing XML-provided PBD::ID
+	   values by Stateful.
+	*/
+	Stateful::ForceIDRegeneration force_ids;
 	IO::disable_connecting ();
 
 	control_id = next_control_id ();
 
 	while (how_many) {
 
-		XMLNode node_copy (*node);
+		/* We're going to modify the node contents a bit so take a
+		 * copy. The node may be re-used when duplicating more than once.
+		 */
 
-		/* Remove IDs of everything so that new ones are used */
-		node_copy.remove_property_recursively (X_("id"));
+		XMLNode node_copy (node);
 
 		try {
 			string name;
@@ -3076,7 +3102,18 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
 			}
 
 			/* set this name in the XML description that we are about to use */
-			Route::set_name_in_state (node_copy, name);
+
+			bool rename_playlist;
+			switch (pd) {
+			case NewPlaylist:
+				rename_playlist = true;
+				break;
+			case CopyPlaylist:
+			case SharePlaylist:
+				rename_playlist = false;
+			}
+
+			Route::set_name_in_state (node_copy, name, rename_playlist);
 
 			/* trim bitslots from listen sends so that new ones are used */
 			XMLNodeList children = node_copy.children ();
@@ -3114,6 +3151,21 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
 			route->set_remote_control_id (control_id);
 			++control_id;
 
+			boost::shared_ptr<Track> track;
+
+			if ((track = boost::dynamic_pointer_cast<Track> (route))) {
+				switch (pd) {
+				case NewPlaylist:
+					track->use_new_playlist ();
+					break;
+				case CopyPlaylist:
+					track->use_copy_playlist ();
+					break;
+				case SharePlaylist:
+					break;
+				}
+			};
+
 			ret.push_back (route);
 
 			RouteAddedOrRemoved (true); /* EMIT SIGNAL */
@@ -3285,7 +3337,7 @@ Session::globally_set_send_gains_to_zero (boost::shared_ptr<Route> dest)
 
 	for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
 		if ((s = (*i)->internal_send_for (dest)) != 0) {
-			s->amp()->gain_control()->set_value (GAIN_COEFF_ZERO);
+			s->amp()->gain_control()->set_value (GAIN_COEFF_ZERO, Controllable::NoGroup);
 		}
 	}
 }
@@ -3298,7 +3350,7 @@ Session::globally_set_send_gains_to_unity (boost::shared_ptr<Route> dest)
 
 	for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
 		if ((s = (*i)->internal_send_for (dest)) != 0) {
-			s->amp()->gain_control()->set_value (GAIN_COEFF_UNITY);
+			s->amp()->gain_control()->set_value (GAIN_COEFF_UNITY, Controllable::NoGroup);
 		}
 	}
 }
@@ -3311,7 +3363,7 @@ Session::globally_set_send_gains_from_track(boost::shared_ptr<Route> dest)
 
 	for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
 		if ((s = (*i)->internal_send_for (dest)) != 0) {
-			s->amp()->gain_control()->set_value ((*i)->gain_control()->get_value());
+			s->amp()->gain_control()->set_value ((*i)->gain_control()->get_value(), Controllable::NoGroup);
 		}
 	}
 }
@@ -3750,6 +3802,11 @@ Session::io_name_is_legal (const std::string& name)
 
 	for (vector<string>::const_iterator reserved = reserved_io_names.begin(); reserved != reserved_io_names.end(); ++reserved) {
 		if (name == *reserved) {
+			if (!route_by_name (*reserved)) {
+				/* first instance of a reserved name is allowed */
+				return true;
+			}
+			/* all other instances of a reserved name are not allowed */
 			return false;
 		}
 	}
diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc
index 5a19f1d..4cb556c 100644
--- a/libs/ardour/session_click.cc
+++ b/libs/ardour/session_click.cc
@@ -58,7 +58,7 @@ Session::click (framepos_t start, framecnt_t nframes)
 
 	click_distance = start - _clicks_cleared;
 
-	if (!clickm.locked() || _transport_speed != 1.0 || !_clicking || click_data == 0 || ((click_distance + nframes) < _worst_track_latency)) {
+	if (!clickm.locked() || !_clicking || click_data == 0 || ((click_distance + nframes) < _worst_track_latency)) {
 		_click_io->silence (nframes);
 		return;
 	}
diff --git a/libs/ardour/session_directory.cc b/libs/ardour/session_directory.cc
index aaeb599..693bee2 100644
--- a/libs/ardour/session_directory.cc
+++ b/libs/ardour/session_directory.cc
@@ -24,6 +24,7 @@
 #include "pbd/error.h"
 #include "pbd/compose.h"
 #include "pbd/file_utils.h"
+#include "pbd/openuri.h"
 
 #include "ardour/directory_names.h"
 #include "ardour/session_directory.h"
@@ -36,6 +37,10 @@ namespace ARDOUR {
 using namespace std;
 using namespace PBD::sys;
 
+
+/* keep a static cache because SessionDirectory is used in various places. */
+std::map<std::string,std::string> SessionDirectory::root_cache;
+
 SessionDirectory::SessionDirectory (const std::string& session_path)
 	: m_root_path(session_path)
 {
@@ -46,6 +51,7 @@ SessionDirectory&
 SessionDirectory::operator= (const std::string& newpath)
 {
 	m_root_path = newpath;
+	root_cache.clear ();
 	return *this;
 }
 
@@ -89,7 +95,15 @@ SessionDirectory::old_sound_path () const
 const std::string
 SessionDirectory::sources_root () const
 {
+	if (root_cache.find (m_root_path) != root_cache.end()) {
+		return root_cache[m_root_path];
+	}
+
+	root_cache.clear ();
+
 	std::string p = m_root_path;
+
+	// TODO ideally we'd use the session's name() here, and not the containing folder's name.
 	std::string filename = Glib::path_get_basename(p);
 
 	if (filename == ".") {
@@ -99,7 +113,69 @@ SessionDirectory::sources_root () const
 	const string legalized_root (legalize_for_path (Glib::path_get_basename(p)));
 
 	std::string sources_root_path = Glib::build_filename (m_root_path, interchange_dir_name);
-	return Glib::build_filename (sources_root_path, legalized_root);
+
+	/* check the interchange folder:
+	 *
+	 * 1) if a single subdir exists, use it, regardless of the name
+	 * 2) if more than one dir is in interchange: abort, blame the user
+	 * 3) if interchange does not exist or no subdir is present,
+	 *    use the session-name to create one.
+	 *
+	 *    We use the name of the containing folder, not the actual
+	 *    session name. The latter would require some API changes and
+	 *    careful libardour updates:
+	 *
+	 *    The session object is created with the "snapshot-name", only
+	 *    when loading the .ardour session file, the actual name is set.
+	 *
+	 *    SessionDirectory is created with the session itself
+	 *    and picks up the wrong inital name.
+	 *
+	 *    SessionDirectory is also used directly by the AudioRegionImporter,
+	 *    and the peak-file background thread (session.cc).
+	 *
+	 * 	  There is no actual benefit to use the session-name instead of
+	 * 	  the folder-name. Under normal circumstances they are always
+	 * 	  identical.  But it would be consistent to prefer the name.
+	 */
+	try {
+		Glib::Dir dir(sources_root_path);
+
+		std::list<std::string> entries;
+
+		for (Glib::DirIterator di = dir.begin(); di != dir.end(); di++) {
+			// ignore hidden files (eg. OS X ".DS_Store")
+			if ((*di).at(0) == '.') {
+				continue;
+			}
+			// and skip regular files (eg. Win Thumbs.db)
+			string fullpath = Glib::build_filename (sources_root_path, *di);
+			if (!Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR)) {
+				continue;
+			}
+			entries.push_back(*di);
+		}
+
+		if (entries.size() == 1) {
+			if (entries.front() != legalized_root) {
+				PBD::info << _("session-dir and session-name mismatch. Please use 'Menu > Session > Rename' in the future to rename sessions.") << endmsg;
+			}
+			root_cache[m_root_path] = Glib::build_filename (sources_root_path, entries.front());
+		}
+		else if (entries.size() > 1) {
+			PBD::open_uri (sources_root_path);
+			PBD::fatal << string_compose (_("The session's interchange dir is tainted.\nThere is more than one folder in '%1'.\nPlease remove extra subdirs to reduce possible filename ambiguties."), sources_root_path) << endmsg;
+			assert (0); // not reached
+		}
+	} catch (Glib::FileError) {
+		;
+	}
+
+	if (root_cache.find (m_root_path) == root_cache.end()) {
+		root_cache[m_root_path] = Glib::build_filename (sources_root_path, legalized_root);
+	}
+
+	return root_cache[m_root_path];
 }
 
 const std::string
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index f1faf5e..c7bced8 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -630,69 +630,61 @@ Session::start_midi_thread ()
 	return 0;
 }
 
-MIDI::Port*
+boost::shared_ptr<ARDOUR::Port>
 Session::midi_input_port () const
 {
 	return _midi_ports->midi_input_port ();
 }
-MIDI::Port*
+
+boost::shared_ptr<ARDOUR::Port>
 Session::midi_output_port () const
 {
 	return _midi_ports->midi_output_port ();
 }
-boost::shared_ptr<MidiPort>
-Session::midi_clock_output_port () const
-{
-	return _midi_ports->midi_clock_output_port ();
-}
-boost::shared_ptr<MidiPort>
-Session::midi_clock_input_port () const
-{
-	return _midi_ports->midi_clock_input_port ();
-}
-boost::shared_ptr<MidiPort>
-Session::mtc_output_port () const
-{
-	return _midi_ports->mtc_output_port ();
-}
-boost::shared_ptr<MidiPort>
-Session::mtc_input_port () const
-{
-	return _midi_ports->mtc_input_port ();
-}
 
-MIDI::Port*
+boost::shared_ptr<ARDOUR::Port>
 Session::mmc_output_port () const
 {
 	return _midi_ports->mmc_output_port ();
 }
 
-MIDI::Port*
+boost::shared_ptr<ARDOUR::Port>
 Session::mmc_input_port () const
 {
 	return _midi_ports->mmc_input_port ();
 }
 
-MIDI::Port*
+boost::shared_ptr<ARDOUR::Port>
 Session::scene_output_port () const
 {
 	return _midi_ports->scene_output_port ();
 }
 
-MIDI::Port*
+boost::shared_ptr<ARDOUR::Port>
 Session::scene_input_port () const
 {
 	return _midi_ports->scene_input_port ();
 }
 
 boost::shared_ptr<MidiPort>
-Session::scene_in () const
+Session::midi_clock_output_port () const
 {
-	return _midi_ports->scene_in ();
+	return _midi_ports->midi_clock_output_port ();
 }
 
 boost::shared_ptr<MidiPort>
-Session::scene_out () const
+Session::midi_clock_input_port () const
+{
+	return _midi_ports->midi_clock_input_port ();
+}
+boost::shared_ptr<MidiPort>
+Session::mtc_output_port () const
 {
-	return _midi_ports->scene_out ();
+	return _midi_ports->mtc_output_port ();
 }
+boost::shared_ptr<MidiPort>
+Session::mtc_input_port () const
+{
+	return _midi_ports->mtc_input_port ();
+}
+
diff --git a/libs/ardour/session_playlists.cc b/libs/ardour/session_playlists.cc
index 8fdafad..649d429 100644
--- a/libs/ardour/session_playlists.cc
+++ b/libs/ardour/session_playlists.cc
@@ -333,15 +333,39 @@ SessionPlaylists::maybe_delete_unused (boost::function<int(boost::shared_ptr<Pla
 {
 	vector<boost::shared_ptr<Playlist> > playlists_tbd;
 
+	bool delete_remaining = false;
+	bool keep_remaining = false;
+
 	for (List::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
 
+		if (keep_remaining) {
+			break;
+		}
+
+		if (delete_remaining) {
+			playlists_tbd.push_back (*x);
+			continue;
+		}
+
 		int status = ask (*x);
 
 		switch (status) {
 		case -1:
+			// abort
 			return true;
 
-		case 0:
+		case -2:
+			// keep this and all later
+			keep_remaining = true;
+			break;
+
+		case 2:
+			// delete this and all later
+			delete_remaining = true;
+			// no break;
+
+		case 1:
+			// delete this
 			playlists_tbd.push_back (*x);
 			break;
 
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index ddbe377..bde7208 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -73,6 +73,7 @@
 #include "pbd/stacktrace.h"
 #include "pbd/convert.h"
 #include "pbd/localtime_r.h"
+#include "pbd/unwind.h"
 
 #include "ardour/amp.h"
 #include "ardour/async_midi_port.h"
@@ -217,11 +218,11 @@ Session::post_engine_init ()
 	MIDISceneChanger* msc;
 
 	_scene_changer = msc = new MIDISceneChanger (*this);
-	msc->set_input_port (scene_input_port());
-	msc->set_output_port (scene_out());
+	msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
+	msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
 
 	boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
-	boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
+	boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
 
 	setup_midi_machine_control ();
 
@@ -343,7 +344,7 @@ Session::post_engine_init ()
 	send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
 	send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
 
-	MIDI::Name::MidiPatchManager::instance().set_session (this);
+	MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
 
 	ltc_tx_initialize();
 	/* initial program change will be delivered later; see ::config_changed() */
@@ -791,7 +792,14 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
 
 	SessionSaveUnderway (); /* EMIT SIGNAL */
 
+	bool mark_as_clean = true;
+
+	if (!snapshot_name.empty() && !switch_to_snapshot) {
+		mark_as_clean = false;
+	}
+
 	if (template_only) {
+		mark_as_clean = false;
 		tree.set_root (&get_template());
 	} else {
 		tree.set_root (&get_state());
@@ -800,8 +808,10 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
 	if (snapshot_name.empty()) {
 		snapshot_name = _current_snapshot_name;
 	} else if (switch_to_snapshot) {
-                _current_snapshot_name = snapshot_name;
-        }
+		set_snapshot_name (snapshot_name);
+	}
+
+	assert (!snapshot_name.empty());
 
 	if (!pending) {
 
@@ -854,12 +864,14 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
 
 		save_history (snapshot_name);
 
-		bool was_dirty = dirty();
+		if (mark_as_clean) {
+			bool was_dirty = dirty();
 
-		_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
+			_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
 
-		if (was_dirty) {
-			DirtyChanged (); /* EMIT SIGNAL */
+			if (was_dirty) {
+				DirtyChanged (); /* EMIT SIGNAL */
+			}
 		}
 
 		StateSaved (snapshot_name); /* EMIT SIGNAL */
@@ -971,6 +983,8 @@ Session::load_state (string snapshot_name)
 		}
 	}
 
+	save_snapshot_name (snapshot_name);
+
 	return 0;
 }
 
@@ -1448,6 +1462,7 @@ Session::set_state (const XMLNode& node, int version)
 	update_route_record_state ();
 
 	/* here beginneth the second phase ... */
+	set_snapshot_name (_current_snapshot_name);
 
 	StateReady (); /* EMIT SIGNAL */
 
@@ -2091,7 +2106,7 @@ Session::XMLSourceFactory (const XMLNode& node)
 }
 
 int
-Session::save_template (string template_name)
+Session::save_template (string template_name, bool replace_existing)
 {
 	if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
 		return -1;
@@ -2117,10 +2132,10 @@ Session::save_template (string template_name)
 	}
 
 	if (!ARDOUR::Profile->get_trx()) {
-		if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
+		if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
 			warning << string_compose(_("Template \"%1\" already exists - new version not created"),
 									  template_dir_path) << endmsg;
-			return -1;
+			return -2;
 		}
 
 		if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
@@ -2147,25 +2162,16 @@ Session::save_template (string template_name)
 
 	XMLTree tree;
 
-	tree.set_root (&get_template());
+	{
+		PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
+		tree.set_root (&get_template());
+	}
+
 	if (!tree.write (template_file_path)) {
 		error << _("template not saved") << endmsg;
 		return -1;
 	}
 
-	if (!ARDOUR::Profile->get_trx()) {
-		/* copy plugin state directory */
-
-		std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
-
-		if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
-			error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
-									template_plugin_state_path, g_strerror (errno)) << endmsg;
-			return -1;
-		}
-		copy_files (plugins_dir(), template_plugin_state_path);
-	}
-
 	store_recent_templates (template_file_path);
 
 	return 0;
@@ -3861,7 +3867,20 @@ void
 Session::setup_midi_machine_control ()
 {
 	_mmc = new MIDI::MachineControl;
-	_mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
+
+	boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
+	boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
+
+	if (!async_out || !async_out) {
+		return;
+	}
+
+	/* XXXX argh, passing raw pointers back into libmidi++ */
+
+	MIDI::Port* mmc_in = async_in.get();
+	MIDI::Port* mmc_out = async_out.get();
+
+	_mmc->set_ports (mmc_in, mmc_out);
 
 	_mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
 	_mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
@@ -3899,6 +3918,27 @@ Session::solo_cut_control() const
         return _solo_cut_control;
 }
 
+void
+Session::save_snapshot_name (const std::string & n)
+{
+	/* assure Stateful::_instant_xml is loaded
+	 * add_instant_xml() only adds to existing data and defaults
+	 * to use an empty Tree otherwise
+	 */
+	instant_xml ("LastUsedSnapshot");
+
+	XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
+	last_used_snapshot->add_property ("name", string(n));
+	add_instant_xml (*last_used_snapshot, false);
+}
+
+void
+Session::set_snapshot_name (const std::string & n)
+{
+	_current_snapshot_name = n;
+	save_snapshot_name (n);
+}
+
 int
 Session::rename (const std::string& new_name)
 {
@@ -4100,7 +4140,7 @@ Session::rename (const std::string& new_name)
 		}
 	}
 
-	_current_snapshot_name = new_name;
+	set_snapshot_name (new_name);
 	_name = new_name;
 
 	set_dirty ();
@@ -4181,6 +4221,29 @@ Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFo
 	return !(found_sr && found_data_format); // zero if they are both found
 }
 
+std::string
+Session::get_snapshot_from_instant (const std::string& session_dir)
+{
+	std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
+
+	if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
+		return "";
+	}
+
+	XMLTree tree;
+	if (!tree.read (instant_xml_path)) {
+		return "";
+	}
+
+	const XMLProperty* prop;
+	XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
+	if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
+		return prop->value();
+	}
+
+	return "";
+}
+
 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
 
@@ -4596,7 +4659,7 @@ Session::save_as (SaveAs& saveas)
 
 
 		_path = to_dir;
-		_current_snapshot_name = saveas.new_name;
+		set_snapshot_name (saveas.new_name);
 		_name = saveas.new_name;
 
 		if (saveas.include_media && !saveas.copy_media) {
@@ -4639,7 +4702,7 @@ Session::save_as (SaveAs& saveas)
 
 			_path = old_path;
 			_name = old_name;
-			_current_snapshot_name = old_snapshot;
+			set_snapshot_name (old_snapshot);
 
 			(*_session_dir) = old_sd;
 
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index e2d64dd..f1486ad 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -109,7 +109,7 @@ void
 Session::request_transport_speed (double speed, bool as_default)
 {
 	SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
-	ev->third_yes_or_no = true; // as_default
+	ev->third_yes_or_no = as_default; // as_default
 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
 	queue_event (ev);
 }
@@ -163,6 +163,12 @@ Session::force_locate (framepos_t target_frame, bool with_roll)
 void
 Session::request_play_loop (bool yn, bool change_transport_roll)
 {
+	if (_slave && yn) {
+		// don't attempt to loop when not using Internal Transport
+		// see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
+		return;
+	}
+
 	SessionEvent* ev;
 	Location *location = _locations->auto_loop_location();
 	double target_speed;
@@ -618,7 +624,7 @@ Session::select_playhead_priority_target (framepos_t& jump_to)
 bool
 Session::select_playhead_priority_target (framepos_t& jump_to)
 {
-	if (!config.get_auto_return()) {
+	if (config.get_external_sync() || !config.get_auto_return()) {
 		return false;
 	}
 
@@ -1342,7 +1348,9 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
 		}
 
 	} else if (transport_stopped() && speed == 1.0) {
-
+		if (as_default) {
+			_default_transport_speed = speed;
+		}
 		/* we are stopped and we want to start rolling at speed 1 */
 
 		if (Config->get_loop_is_mode() && play_loop) {
diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc
index 9bf2847..2aed71a 100644
--- a/libs/ardour/session_vst.cc
+++ b/libs/ardour/session_vst.cc
@@ -86,7 +86,7 @@ intptr_t Session::vst_callback (
 		SHOW_CALLBACK ("audioMasterAutomate");
 		// index, value, returns 0
 		if (plug) {
-			plug->set_parameter_automated (index, opt);
+			plug->parameter_changed_externally (index, opt);
 		}
 		return 0;
 
@@ -318,7 +318,9 @@ intptr_t Session::vst_callback (
 
 	case audioMasterSizeWindow:
 		SHOW_CALLBACK ("audioMasterSizeWindow");
-		// index: width, value: height
+		plug->state()->width = index;
+		plug->state()->height = value;
+		plug->state()->want_resize = 1;
 		return 0;
 
 	case audioMasterGetSampleRate:
diff --git a/libs/ardour/sndfile_helpers.cc b/libs/ardour/sndfile_helpers.cc
index 08c57bf..1b69ca2 100644
--- a/libs/ardour/sndfile_helpers.cc
+++ b/libs/ardour/sndfile_helpers.cc
@@ -34,7 +34,7 @@ const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
 	N_("WAV"),
 	N_("AIFF"),
 	N_("CAF"),
-	N_("W64 (64 bit WAV)"),
+	N_("W64 (64-bit WAV)"),
 	N_("FLAC"),
 	N_("Ogg/Vorbis"),
 	N_("raw (no header)"),
@@ -63,11 +63,11 @@ int sndfile_header_formats[SNDFILE_HEADER_FORMATS] = {
 };
 
 const char * const sndfile_bitdepth_formats_strings[SNDFILE_BITDEPTH_FORMATS+1] = {
-	N_("Signed 16 bit PCM"),
-	N_("Signed 24 bit PCM"),
-	N_("Signed 32 bit PCM"),
-	N_("Signed 8 bit PCM"),
-	N_("32 bit float"),
+	N_("Signed 16-bit PCM"),
+	N_("Signed 24-bit PCM"),
+	N_("Signed 32-bit PCM"),
+	N_("Signed 8-bit PCM"),
+	N_("32-bit float"),
 	0
 };
 
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index eedb563..73361c3 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -255,6 +255,7 @@ SndFileSource::close ()
 	if (_sndfile) {
 		sf_close (_sndfile);
 		_sndfile = 0;
+		file_closed ();
 	}
 }
 
@@ -316,7 +317,7 @@ SndFileSource::open ()
 #ifdef HAVE_RF64_RIFF
 	if (_file_is_new && _length == 0 && writable()) {
 		if (_flags & RF64_RIFF) {
-			if (sf_command (_sndfile, SFC_AUTO_DOWNGRADE_RF64, 0, 0) != SF_TRUE) {
+			if (sf_command (_sndfile, SFC_RF64_AUTO_DOWNGRADE, 0, 0) != SF_TRUE) {
 				char errbuf[256];
 				sf_error_str (_sndfile, errbuf, sizeof (errbuf) - 1);
 				error << string_compose (_("Cannot mark RF64 audio file for automatic downgrade to WAV: %1"), errbuf)
diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc
index 2909303..aaa50ff 100644
--- a/libs/ardour/source.cc
+++ b/libs/ardour/source.cc
@@ -178,7 +178,7 @@ Source::set_been_analysed (bool yn)
 			yn = false;
 		}
 	}
-	if (yn != _analysed); {
+	if (yn != _analysed) {
 		Glib::Threads::Mutex::Lock lm (_analysis_lock);
 		_analysed = yn;
 	}
diff --git a/libs/ardour/test/load_save_session.cc b/libs/ardour/test/load_save_session.cc
new file mode 100644
index 0000000..ab4573c
--- /dev/null
+++ b/libs/ardour/test/load_save_session.cc
@@ -0,0 +1,121 @@
+#include "test_util.h"
+
+#include <iostream>
+#include <cstdlib>
+
+#include <glib.h>
+
+#include "pbd/failed_constructor.h"
+#include "pbd/timing.h"
+
+#include "ardour/ardour.h"
+#include "ardour/audioengine.h"
+#include "ardour/session.h"
+
+#include "test_ui.h"
+
+using namespace std;
+using namespace ARDOUR;
+
+static const char* localedir = LOCALEDIR;
+
+static const int sleep_seconds = 2;
+
+static
+void
+pause_for_effect()
+{
+	// It may be useful to pause to make it easier to see what is happening in a
+	// visual tool like massif visualizer
+
+	std::cerr << "pausing for " << sleep_seconds << " seconds" << std::endl;
+
+	g_usleep(sleep_seconds*1000000);
+}
+
+int main (int argc, char* argv[])
+{
+	if (argc != 3) {
+		cerr << "Syntax: " << argv[0] << " <dir> <snapshot-name>\n";
+		exit (EXIT_FAILURE);
+	}
+
+	std::cerr << "ARDOUR::init" << std::endl;
+
+	PBD::Timing ardour_init_timing;
+
+	ARDOUR::init (false, true, localedir);
+	ardour_init_timing.update();
+
+	TestUI* test_ui = new TestUI();
+
+	std::cerr << "ARDOUR::init time : " << ardour_init_timing.elapsed()
+	          << " usecs" << std::endl;
+
+	std::cerr << "Creating Dummy backend" << std::endl;
+
+	create_and_start_dummy_backend ();
+
+	std::cerr << "Loading session: " << argv[2] << std::endl;
+
+	PBD::Timing load_session_timing;
+
+	Session* s = 0;
+
+	try {
+		s = load_session (argv[1], argv[2]);
+	} catch (failed_constructor& e) {
+		cerr << "failed_constructor: " << e.what() << "\n";
+		exit (EXIT_FAILURE);
+	} catch (AudioEngine::PortRegistrationFailure& e) {
+		cerr << "PortRegistrationFailure: " << e.what() << "\n";
+		exit (EXIT_FAILURE);
+	} catch (exception& e) {
+		cerr << "exception: " << e.what() << "\n";
+		exit (EXIT_FAILURE);
+	} catch (...) {
+		cerr << "unknown exception.\n";
+		exit (EXIT_FAILURE);
+	}
+
+	load_session_timing.update();
+
+	std::cerr << "Loading session time : " << load_session_timing.elapsed()
+	          << " usecs" << std::endl;
+
+	PBD::Timing save_session_timing;
+
+	pause_for_effect ();
+
+	std::cerr << "Saving session: " << argv[2] << std::endl;
+
+	s->save_state("");
+
+	save_session_timing.update();
+
+	std::cerr << "Saving session time : " << save_session_timing.elapsed()
+	          << " usecs" << std::endl;
+
+	std::cerr << "AudioEngine::remove_session" << std::endl;
+
+	AudioEngine::instance()->remove_session ();
+
+	PBD::Timing destroy_session_timing;
+
+	delete s;
+
+	destroy_session_timing.update();
+
+	std::cerr << "Destroy session time : " << destroy_session_timing.elapsed()
+	          << " usecs" << std::endl;
+
+	AudioEngine::instance()->stop ();
+
+	AudioEngine::destroy ();
+
+	delete test_ui;
+
+	ARDOUR::cleanup ();
+
+	return 0;
+}
diff --git a/libs/ardour/test/load_session.cc b/libs/ardour/test/load_session.cc
deleted file mode 100644
index 41dc48e..0000000
--- a/libs/ardour/test/load_session.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "test_util.h"
-#include "pbd/failed_constructor.h"
-#include "ardour/ardour.h"
-#include "ardour/audioengine.h"
-#include "ardour/session.h"
-#include <iostream>
-#include <cstdlib>
-
-using namespace std;
-using namespace ARDOUR;
-
-static const char* localedir = LOCALEDIR;
-
-int main (int argc, char* argv[])
-{
-	if (argc != 3) {
-		cerr << "Syntax: " << argv[0] << " <dir> <snapshot-name>\n";
-		exit (EXIT_FAILURE);
-	}
-
-	ARDOUR::init (false, true, localedir);
-
-	Session* s = 0;
-
-	try {
-		s = load_session (argv[1], argv[2]);
-	} catch (failed_constructor& e) {
-		cerr << "failed_constructor: " << e.what() << "\n";
-		exit (EXIT_FAILURE);
-	} catch (AudioEngine::PortRegistrationFailure& e) {
-		cerr << "PortRegistrationFailure: " << e.what() << "\n";
-		exit (EXIT_FAILURE);
-	} catch (exception& e) {
-		cerr << "exception: " << e.what() << "\n";
-		exit (EXIT_FAILURE);
-	} catch (...) {
-		cerr << "unknown exception.\n";
-		exit (EXIT_FAILURE);
-	}
-
-	AudioEngine::instance()->remove_session ();
-	delete s;
-	AudioEngine::instance()->stop ();
-
-	AudioEngine::destroy ();
-
-	return 0;
-}
diff --git a/libs/ardour/test/profiling/lots_of_regions.cc b/libs/ardour/test/profiling/lots_of_regions.cc
index 3a45d77..4467822 100644
--- a/libs/ardour/test/profiling/lots_of_regions.cc
+++ b/libs/ardour/test/profiling/lots_of_regions.cc
@@ -35,7 +35,7 @@ main (int argc, char* argv[])
 	/* Duplicate it a lot */
 	session->begin_reversible_command ("foo");
 	playlist->clear_changes ();
-	playlist->duplicate (region, region->last_frame(), 1000);
+	playlist->duplicate (region, region->last_frame() + 1, 1000);
 	session->add_command (new StatefulDiffCommand (playlist));
 	session->commit_reversible_command ();
 
@@ -45,7 +45,7 @@ main (int argc, char* argv[])
 	/* And do it again */
 	session->begin_reversible_command ("foo");
 	playlist->clear_changes ();
-	playlist->duplicate (region, region->last_frame(), 1000);
+	playlist->duplicate (region, region->last_frame() + 1, 1000);
 	session->add_command (new StatefulDiffCommand (playlist));
 	session->commit_reversible_command ();
 }
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index e99d07f..21256b0 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -190,7 +190,15 @@ Track::RecEnableControl::RecEnableControl (boost::shared_ptr<Track> t)
 }
 
 void
-Track::RecEnableControl::set_value (double val)
+Track::RecEnableControl::set_value (double val, Controllable::GroupControlDisposition /* group_override */)
+{
+	if (writable()) {
+		set_value_unchecked (val);
+	}
+}
+
+void
+Track::RecEnableControl::set_value_unchecked (double val)
 {
 	boost::shared_ptr<Track> t = track.lock ();
 	if (!t) {
diff --git a/libs/ardour/ardour/lxvst_plugin.h b/libs/ardour/transpose.cc
similarity index 51%
copy from libs/ardour/ardour/lxvst_plugin.h
copy to libs/ardour/transpose.cc
index cc6f507..ca0b7ab 100644
--- a/libs/ardour/ardour/lxvst_plugin.h
+++ b/libs/ardour/transpose.cc
@@ -1,5 +1,6 @@
 /*
-    Copyright (C) 2004 Paul Davis
+    Copyright (C) 2015 Paul Davis
+    Author: André Nusser
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -14,41 +15,35 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
 */
 
-#ifndef __ardour_lxvst_plugin_h__
-#define __ardour_lxvst_plugin_h__
-
-#include "ardour/vst_plugin.h"
-
-struct _VSTHandle;
-typedef struct _VSTHandle VSTHandle;
+#include "ardour/transpose.h"
 
 namespace ARDOUR {
 
-class AudioEngine;
-class Session;
+Transpose::Transpose(int semitones)
+	: _semitones(semitones)
+{}
 
-class LIBARDOUR_API LXVSTPlugin : public VSTPlugin
+Command*
+Transpose::operator()(boost::shared_ptr<MidiModel> model,
+                      Evoral::Beats                position,
+                      std::vector<Notes>&          seqs)
 {
-  public:
-	LXVSTPlugin (AudioEngine &, Session &, VSTHandle *, int unique_id);
-	LXVSTPlugin (const LXVSTPlugin &);
-	~LXVSTPlugin ();
+	typedef MidiModel::NoteDiffCommand Command;
 
-	std::string state_node_name () const { return "lxvst"; }
-};
+	Command* cmd = new Command(model, name());
 
-class LIBARDOUR_API LXVSTPluginInfo : public PluginInfo
-{
-  public:
-	LXVSTPluginInfo ();
-	~LXVSTPluginInfo () {}
+	for (std::vector<Notes>::iterator s = seqs.begin(); s != seqs.end(); ++s) {
+		for (Notes::const_iterator i = (*s).begin(); i != (*s).end(); ++i) {
+
+			const NotePtr note = *i;
 
-	PluginPtr load (Session& session);
-};
+			model->transpose (cmd, *i, _semitones);
+		}
+	}
 
-} // namespace ARDOUR
+	return cmd;
+}
 
-#endif /* __ardour_lxvst_plugin_h__ */
+}  // namespace ARDOUR
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index 08db7de..f04aa2b 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -117,12 +117,6 @@ VSTPlugin::set_parameter (uint32_t which, float newval)
 	}
 }
 
-void
-VSTPlugin::set_parameter_automated (uint32_t which, float newval)
-{
-	Plugin::set_parameter_automated (which, newval);
-}
-
 uint32_t
 VSTPlugin::nth_parameter (uint32_t n, bool& ok) const
 {
@@ -685,7 +679,7 @@ VSTPlugin::find_presets ()
 
 	int const vst_version = _plugin->dispatcher (_plugin, effGetVstVersion, 0, 0, NULL, 0);
 	for (int i = 0; i < _plugin->numPrograms; ++i) {
-		PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id (), i), "", -1, false);
+		PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id (), i), "", false);
 
 		if (vst_version >= 2) {
 			char buf[256];
@@ -715,7 +709,7 @@ VSTPlugin::find_presets ()
 			assert (uri);
 			assert (label);
 
-			PresetRecord r (uri->value(), label->value(), -1, true);
+			PresetRecord r (uri->value(), label->value(), true);
 			_presets.insert (make_pair (r.uri, r));
 		}
 	}
diff --git a/libs/ardour/windows_vst_plugin.cc b/libs/ardour/windows_vst_plugin.cc
index abca611..a480642 100644
--- a/libs/ardour/windows_vst_plugin.cc
+++ b/libs/ardour/windows_vst_plugin.cc
@@ -19,6 +19,10 @@
 
 #include "fst.h"
 
+#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+
+#include "ardour/filesystem_paths.h"
 #include "ardour/windows_vst_plugin.h"
 #include "ardour/session.h"
 
@@ -90,6 +94,39 @@ WindowsVSTPluginInfo::load (Session& session)
 	}
 }
 
+std::vector<Plugin::PresetRecord>
+WindowsVSTPluginInfo::get_presets (bool user_only) const
+{
+	std::vector<Plugin::PresetRecord> p;
+#ifndef NO_PLUGIN_STATE
+	if (!Config->get_use_lxvst()) {
+		return p;
+	}
+
+	if (!user_only) {
+		// TODO cache and load factory-preset names
+	}
+
+	/* user presets */
+	XMLTree* t = new XMLTree;
+	std::string pf = Glib::build_filename (ARDOUR::user_config_directory (), "presets", string_compose ("vst-%1", unique_id));
+	if (Glib::file_test (pf, Glib::FILE_TEST_EXISTS)) {
+		t->set_filename (pf);
+		if (t->read ()) {
+			XMLNode* root = t->root ();
+			for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
+				XMLProperty* uri = (*i)->property (X_("uri"));
+				XMLProperty* label = (*i)->property (X_("label"));
+				p.push_back (Plugin::PresetRecord (uri->value(), label->value(), true));
+			}
+		}
+	}
+	delete t;
+#endif
+
+	return p;
+}
+
 WindowsVSTPluginInfo::WindowsVSTPluginInfo()
 {
        type = ARDOUR::Windows_VST;
diff --git a/libs/ardour/worker.cc b/libs/ardour/worker.cc
index aea1c6f..ce71c92 100644
--- a/libs/ardour/worker.cc
+++ b/libs/ardour/worker.cc
@@ -32,7 +32,7 @@ Worker::Worker(Workee* workee, uint32_t ring_size)
 	, _requests(new RingBuffer<uint8_t>(ring_size))
 	, _responses(new RingBuffer<uint8_t>(ring_size))
 	, _response((uint8_t*)malloc(ring_size))
-	, _sem(0)
+	, _sem ("worker_semaphore", 0)
 	, _exit(false)
 	, _thread (Glib::Threads::Thread::create(sigc::mem_fun(*this, &Worker::run)))
 {}
@@ -40,7 +40,7 @@ Worker::Worker(Workee* workee, uint32_t ring_size)
 Worker::~Worker()
 {
 	_exit = true;
-	_sem.post();
+	_sem.signal();
 	_thread->join();
 }
 
@@ -56,7 +56,7 @@ Worker::schedule(uint32_t size, const void* data)
 	if (_requests->write((const uint8_t*)data, size) != size) {
 		return false;
 	}
-	_sem.post();
+	_sem.signal();
 	return true;
 }
 
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index af5b266..c5cd783 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -65,6 +65,7 @@ libardour_sources = [
         'delivery.cc',
         'directory_names.cc',
         'diskstream.cc',
+        'ebur128_analysis.cc',
         'element_import_handler.cc',
         'element_importer.cc',
         'engine_slave.cc',
@@ -216,6 +217,7 @@ libardour_sources = [
         'track.cc',
         'transient_detector.cc',
         'transform.cc',
+        'transpose.cc',
         'unknown_processor.cc',
         'user_bundle.cc',
         'utils.cc',
@@ -333,10 +335,11 @@ def build(bld):
     # micro increment <=> no interface changes
     LIBARDOUR_LIB_VERSION = "3.0.0"
 
-    sources = libardour_sources
+    # operate on copy to avoid adding sources twice
+    sources = list(libardour_sources)
     if bld.is_tracks_build():
         sources += [ 'engine_state_controller.cc' ]
-    
+
     # Library
     if bld.is_defined ('INTERNAL_SHARED_LIBS'):
         obj              = bld.shlib(features = 'c cxx cshlib cxxshlib', source=sources)
@@ -421,12 +424,12 @@ def build(bld):
         elif bld.env['build_target'] == 'mingw':
                 # usability of the 64 bit windows assembler depends on the compiler target,
                 # not the build host, which in turn can only be inferred from the name
-                # of the compiler. 
+                # of the compiler.
                 if re.search ('x86_64-w64', str(bld.env['CC'])):
                         obj.source += [ 'sse_functions_xmm.cc' ]
                         obj.source += [ 'sse_functions_64bit_win.s',  'sse_avx_functions_64bit_win.s' ]
                         avx_sources = [ 'sse_functions_avx.cc' ]
-        
+
         if avx_sources:
             # as long as we want to use AVX intrinsics in this file,
             # compile it with -mavx flag - append avx flag to the existing
@@ -439,9 +442,9 @@ def build(bld):
                 includes = [ '.' ],
                 use = [ 'libtimecode', 'libpbd', 'libevoral', ],
                 target   = 'sse_avx_functions')
-            
+
             obj.use += ['sse_avx_functions' ]
-        
+
     # i18n
     if bld.is_defined('ENABLE_NLS'):
         mo_files = bld.path.ant_glob('po/*.mo')
@@ -524,23 +527,24 @@ def build(bld):
 
         create_ardour_test_program(bld, obj.includes, 'libardour-tests', 'run-tests', test_sources)
 
-        # Tester to just load a session
-        session_load_tester = bld(features = 'cxx cxxprogram')
-        session_load_tester.source = '''
+        # Utility to load and save a session
+        load_save_session = bld(features = 'cxx cxxprogram')
+        load_save_session.source = '''
                     test/test_util.cc
-                    test/load_session.cc
+                    test/test_ui.cc
+                    test/load_save_session.cc
                     test/dummy_lxvst.cc
             '''.split()
 
-        session_load_tester.includes  = obj.includes
-        session_load_tester.includes.append ('test')
-        session_load_tester.uselib    = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
+        load_save_session.includes  = obj.includes
+        load_save_session.includes.append ('test')
+        load_save_session.uselib    = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
                              'SAMPLERATE','XML','LRDF','COREAUDIO']
-        session_load_tester.use       = ['libpbd','libmidipp','libardour']
-        session_load_tester.name      = 'libardour-session-load-tester'
-        session_load_tester.target    = 'load-session'
-        session_load_tester.install_path = ''
-        session_load_tester.defines      = [
+        load_save_session.use       = ['libpbd','libmidipp','libardour']
+        load_save_session.name      = 'libardour-load-save-session'
+        load_save_session.target    = 'load-save-session'
+        load_save_session.install_path = ''
+        load_save_session.defines      = [
             'PACKAGE="libardour' + str(bld.env['MAJOR']) + 'profile"',
             'DATA_DIR="' + os.path.normpath(bld.env['DATADIR']) + '"',
             'CONFIG_DIR="' + os.path.normpath(bld.env['SYSCONFDIR']) + '"',
diff --git a/libs/backends/MSVCbackends/portaudio_audiobackend.vcproj b/libs/backends/MSVCbackends/portaudio_audiobackend.vcproj
index 87d8750..7869a70 100644
--- a/libs/backends/MSVCbackends/portaudio_audiobackend.vcproj
+++ b/libs/backends/MSVCbackends/portaudio_audiobackend.vcproj
@@ -42,7 +42,7 @@
 				AdditionalOptions="/FI$(TargetSxsFolder)\targetsxs.h"
 				Optimization="0"
 				AdditionalIncludeDirectories="..;..\portaudio;..\..\ardour;..\..\pbd;..\..\timecode;..\..\evoral;"..\..\midi++2";"$(GenericIncludeFolder)\ardourext";"$(GenericLibraryFolder)\glib-2.0\include";"$(GenericIncludeFolder)\libsndfile";"$(GenericIncludeFolder)\gtk-2.0";"$(GenericIncludeFolder)\cairo";"$(GenericIncludeFolder)\freetype2";"$(GenericIncludeFolder)\pango-1.0";"$(GenericIncludeFolder)\gtk-2.0\gdk";"$(GenericIncludeFolder)\atk-2.0";"$(GenericIncludeFolder)\lrdf";"$(GenericIncludeFolder)\raptor";"$(GenericIncludeFolder)\boost";..\..;..\..\..\..\support\MB3Portaudio\include"
-				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;BUILDING_PORTAUDIO_BACKEND;WITH_ASIO;ARDOURBACKEND_DLL_EXPORTS;RUBBERBAND_IS_IN_WIN_STATIC_LIB;USE_CAIRO_IMAGE_SURFACE;NOMINMAX;NO_POSIX_MEMALIGN;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;GNU_WIN32;WIN32;_WIN32;_WINDOWS;_DEBUG;DEBUG="Debug";ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PROGRAM_NAME="\"Mixbus3\"";PACKAGE="\"libardour_portaudio\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_PORTAUDIO=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
+				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;BUILDING_PORTAUDIO_BACKEND;BACKEND_NAME="\"PortAudio\x0020(default)\"";WITH_ASIO;ARDOURBACKEND_DLL_EXPORTS;RUBBERBAND_IS_IN_WIN_STATIC_LIB;USE_CAIRO_IMAGE_SURFACE;NOMINMAX;NO_POSIX_MEMALIGN;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;GNU_WIN32;WIN32;_WIN32;_WINDOWS;_DEBUG;DEBUG="Debug";ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PROGRAM_NAME="\"Mixbus3\"";PACKAGE="\"libardour_portaudio\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_PORTAUDIO=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
 				MinimalRebuild="true"
 				RuntimeLibrary="3"
 				WarningLevel="3"
@@ -124,7 +124,7 @@
 				Optimization="2"
 				InlineFunctionExpansion="1"
 				AdditionalIncludeDirectories="..;..\portaudio;..\..\ardour;..\..\pbd;..\..\timecode;..\..\evoral;"..\..\midi++2";"$(GenericIncludeFolder)\ardourext";"$(GenericLibraryFolder)\glib-2.0\include";"$(GenericIncludeFolder)\libsndfile";"$(GenericIncludeFolder)\gtk-2.0";"$(GenericIncludeFolder)\cairo";"$(GenericIncludeFolder)\freetype2";"$(GenericIncludeFolder)\pango-1.0";"$(GenericIncludeFolder)\gtk-2.0\gdk";"$(GenericIncludeFolder)\atk-2.0";"$(GenericIncludeFolder)\lrdf";"$(GenericIncludeFolder)\raptor";"$(GenericIncludeFolder)\boost";..\..;..\..\..\..\support\MB3Portaudio\include"
-				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;_SECURE_SCL=0;BUILDING_PORTAUDIO_BACKEND;WITH_ASIO;ARDOURBACKEND_DLL_EXPORTS;RUBBERBAND_IS_IN_WIN_STATIC_LIB;USE_CAIRO_IMAGE_SURFACE;NOMINMAX;NO_POSIX_MEMALIGN;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;GNU_WIN32;WIN32;_WIN32;_WINDOWS;NDEBUG;ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PROGRAM_NAME="\"Mixbus3\"";PACKAGE="\"libardour_portaudio\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_PORTAUDIO=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
+				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;_SECURE_SCL=0;BUILDING_PORTAUDIO_BACKEND;BACKEND_NAME="\"PortAudio\x0020(default)\"";WITH_ASIO;ARDOURBACKEND_DLL_EXPORTS;RUBBERBAND_IS_IN_WIN_STATIC_LIB;USE_CAIRO_IMAGE_SURFACE;NOMINMAX;NO_POSIX_MEMALIGN;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;GNU_WIN32;WIN32;_WIN32;_WINDOWS;NDEBUG;ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PROGRAM_NAME="\"Mixbus3\"";PACKAGE="\"libardour_portaudio\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_PORTAUDIO=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
 				StringPooling="false"
 				RuntimeLibrary="2"
 				EnableEnhancedInstructionSet="1"
@@ -206,7 +206,7 @@
 				AdditionalOptions="/FI$(TargetSxsFolder)\targetsxs.h"
 				Optimization="0"
 				AdditionalIncludeDirectories="..;..\portaudio;..\..\ardour;..\..\pbd;..\..\timecode;..\..\evoral;"..\..\midi++2";"$(GenericIncludeFolder)\ardourext";"$(GenericLibraryFolder)\glib-2.0\include";"$(GenericIncludeFolder)\libsndfile";"$(GenericIncludeFolder)\gtk-2.0";"$(GenericIncludeFolder)\cairo";"$(GenericIncludeFolder)\freetype2";"$(GenericIncludeFolder)\pango-1.0";"$(GenericIncludeFolder)\gtk-2.0\gdk";"$(GenericIncludeFolder)\atk-2.0";"$(GenericIncludeFolder)\lrdf";"$(GenericIncludeFolder)\raptor";"$(GenericIncludeFolder)\boost";..\..;..\..\..\..\support\MB3Portaudio\include"
-				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;_SECURE_SCL=0;BUILDING_PORTAUDIO_BACKEND;WITH_ASIO;ARDOURBACKEND_DLL_EXPORTS;RUBBERBAND_IS_IN_WIN_STATIC_LIB;USE_CAIRO_IMAGE_SURFACE;NOMINMAX;NO_POSIX_MEMALIGN;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;GNU_WIN32;WIN32;_WIN32;_WINDOWS;ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PROGRAM_NAME="\"Mixbus3\"";PACKAGE="\"libardour_portaudio\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_PORTAUDIO=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
+				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;_SECURE_SCL=0;BUILDING_PORTAUDIO_BACKEND;BACKEND_NAME="\"PortAudio\x0020(default)\"";WITH_ASIO;ARDOURBACKEND_DLL_EXPORTS;RUBBERBAND_IS_IN_WIN_STATIC_LIB;USE_CAIRO_IMAGE_SURFACE;NOMINMAX;NO_POSIX_MEMALIGN;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;GNU_WIN32;WIN32;_WIN32;_WINDOWS;ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PROGRAM_NAME="\"Mixbus3\"";PACKAGE="\"libardour_portaudio\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_PORTAUDIO=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
 				StringPooling="false"
 				RuntimeLibrary="2"
 				EnableEnhancedInstructionSet="1"
diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc
index b0997a6..3658aa3 100644
--- a/libs/backends/alsa/alsa_audiobackend.cc
+++ b/libs/backends/alsa/alsa_audiobackend.cc
@@ -69,6 +69,8 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
 	, _systemic_audio_output_latency (0)
 	, _dsp_load (0)
 	, _processed_samples (0)
+	, _midi_ins (0)
+	, _midi_outs (0)
 	, _port_change_flag (false)
 {
 	_instance_name = s_instance_name;
@@ -330,6 +332,15 @@ AlsaAudioBackend::available_output_channel_count (const std::string& device) con
 	return 128;
 }
 
+std::vector<uint32_t>
+AlsaAudioBackend::available_period_sizes (const std::string& driver) const
+{
+	std::vector<uint32_t> ps;
+	ps.push_back (2);
+	ps.push_back (3);
+	return ps;
+}
+
 bool
 AlsaAudioBackend::can_change_sample_rate_when_running () const
 {
@@ -423,6 +434,19 @@ AlsaAudioBackend::set_sample_rate (float sr)
 }
 
 int
+AlsaAudioBackend::set_peridod_size (uint32_t n)
+{
+	if (n == 0 || n > 3) {
+		return -1;
+	}
+	if (_run) {
+		return -1;
+	}
+	_periods_per_cycle = n;
+	return 0;
+}
+
+int
 AlsaAudioBackend::set_buffer_size (uint32_t bs)
 {
 	if (bs <= 0 || bs >= _max_buffer_size) {
@@ -461,6 +485,9 @@ int
 AlsaAudioBackend::set_systemic_input_latency (uint32_t sl)
 {
 	_systemic_audio_input_latency = sl;
+	if (_run) {
+		update_systemic_audio_latencies();
+	}
 	return 0;
 }
 
@@ -468,6 +495,9 @@ int
 AlsaAudioBackend::set_systemic_output_latency (uint32_t sl)
 {
 	_systemic_audio_output_latency = sl;
+	if (_run) {
+		update_systemic_audio_latencies();
+	}
 	return 0;
 }
 
@@ -477,6 +507,9 @@ AlsaAudioBackend::set_systemic_midi_input_latency (std::string const device, uin
 	struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
 	if (!nfo) return -1;
 	nfo->systemic_input_latency = sl;
+	if (_run && nfo->enabled) {
+		update_systemic_midi_latencies ();
+	}
 	return 0;
 }
 
@@ -486,9 +519,57 @@ AlsaAudioBackend::set_systemic_midi_output_latency (std::string const device, ui
 	struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
 	if (!nfo) return -1;
 	nfo->systemic_output_latency = sl;
+	if (_run && nfo->enabled) {
+		update_systemic_midi_latencies ();
+	}
 	return 0;
 }
 
+void
+AlsaAudioBackend::update_systemic_audio_latencies ()
+{
+	const uint32_t lcpp = (_periods_per_cycle - 2) * _samples_per_period;
+	LatencyRange lr;
+
+	lr.min = lr.max = lcpp + (_measure_latency ? 0 : _systemic_audio_input_latency);
+	for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
+		set_latency_range (*it, true, lr);
+	}
+
+	lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency);
+	for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
+		set_latency_range (*it, false, lr);
+	}
+	update_latencies ();
+}
+
+void
+AlsaAudioBackend::update_systemic_midi_latencies ()
+{
+	uint32_t i = 0;
+	for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
+		assert (_rmidi_out.size() > i);
+		AlsaMidiOut *rm = _rmidi_out.at(i);
+		struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
+		assert (nfo);
+		LatencyRange lr;
+		lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency);
+		set_latency_range (*it, false, lr);
+	}
+
+	i = 0;
+	for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
+		assert (_rmidi_in.size() > i);
+		AlsaMidiIO *rm = _rmidi_in.at(i);
+		struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
+		assert (nfo);
+		LatencyRange lr;
+		lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_input_latency);
+		set_latency_range (*it, true, lr);
+	}
+	update_latencies ();
+}
+
 /* Retrieving parameters */
 std::string
 AlsaAudioBackend::device_name () const
@@ -526,6 +607,12 @@ AlsaAudioBackend::buffer_size () const
 	return _samples_per_period;
 }
 
+uint32_t
+AlsaAudioBackend::period_size () const
+{
+	return _periods_per_cycle;
+}
+
 bool
 AlsaAudioBackend::interleaved () const
 {
@@ -635,6 +722,9 @@ AlsaAudioBackend::set_midi_option (const std::string& opt)
 	if (opt != get_standard_device_name(DeviceNone) && opt != _("ALSA raw devices") && opt != _("ALSA sequencer")) {
 		return -1;
 	}
+	if (_run && _midi_driver_option != opt) {
+		return -1;
+	}
 	_midi_driver_option = opt;
 	return 0;
 }
@@ -650,7 +740,41 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable
 {
 	struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
 	if (!nfo) return -1;
+	const bool prev_enabled = nfo->enabled;
 	nfo->enabled = enable;
+
+	if (_run && prev_enabled != enable) {
+		if (enable) {
+			// add ports for the given device
+			register_system_midi_ports(device);
+		} else {
+			// remove all ports provided by the given device
+			uint32_t i = 0;
+			for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end ();) {
+				assert (_rmidi_out.size() > i);
+				AlsaMidiOut *rm = _rmidi_out.at(i);
+				if (rm->name () != device) { ++it; ++i; continue; }
+				it = _system_midi_out.erase (it);
+				unregister_port (*it);
+				rm->stop();
+				_rmidi_out.erase (_rmidi_out.begin() + i);
+				delete rm;
+			}
+
+			i = 0;
+			for (std::vector<AlsaPort*>::iterator it = _system_midi_in.begin (); it != _system_midi_in.end ();) {
+				assert (_rmidi_in.size() > i);
+				AlsaMidiIn *rm = _rmidi_in.at(i);
+				if (rm->name () != device) { ++it; ++i; continue; }
+				it = _system_midi_in.erase (it);
+				unregister_port (*it);
+				rm->stop();
+				_rmidi_in.erase (_rmidi_in.begin() + i);
+				delete rm;
+			}
+		}
+		update_systemic_midi_latencies ();
+	}
 	return 0;
 }
 
@@ -751,7 +875,10 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
 	_pcmi = new Alsa_pcmi (
 			(duplex & 2) ? alsa_device.c_str() : NULL,
 			(duplex & 1) ? alsa_device.c_str() : NULL,
-			0, _samplerate, _samples_per_period, _periods_per_cycle, 0);
+			/* ctrl name */ 0,
+			_samplerate, _samples_per_period,
+			_periods_per_cycle, /* _periods_per_cycle */ 2,
+			/* debug */ 0);
 
 	AudioBackend::ErrorCode error_code = NoError;
 	switch (_pcmi->state()) {
@@ -831,6 +958,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
 
 	_measure_latency = for_latency_measurement;
 
+	_midi_ins = _midi_outs = 0;
 	register_system_midi_ports();
 
 	if (register_system_audio_ports()) {
@@ -912,6 +1040,7 @@ AlsaAudioBackend::stop ()
 
 	unregister_ports();
 	delete _pcmi; _pcmi = 0;
+	_midi_ins = _midi_outs = 0;
 	release_device();
 
 	return (_active == false) ? 0 : -1;
@@ -1091,12 +1220,29 @@ std::string
 AlsaAudioBackend::get_port_name (PortEngine::PortHandle port) const
 {
 	if (!valid_port (port)) {
-		PBD::error << _("AlsaBackend::get_port_name: Invalid Port(s)") << endmsg;
+		PBD::warning << _("AlsaBackend::get_port_name: Invalid Port(s)") << endmsg;
 		return std::string ();
 	}
 	return static_cast<AlsaPort*>(port)->name ();
 }
 
+int
+AlsaAudioBackend::get_port_property (PortHandle port, const std::string& key, std::string& value, std::string& type) const
+{
+	if (!valid_port (port)) {
+		PBD::warning << _("AlsaBackend::get_port_property: Invalid Port(s)") << endmsg;
+		return -1;
+	}
+	if (key == "http://jackaudio.org/metadata/pretty-name") {
+		type = "";
+		value = static_cast<AlsaPort*>(port)->pretty_name ();
+		if (!value.empty()) {
+			return 0;
+		}
+	}
+	return -1;
+}
+
 PortEngine::PortHandle
 AlsaAudioBackend::get_port_by_name (const std::string& name) const
 {
@@ -1208,6 +1354,8 @@ AlsaAudioBackend::register_system_audio_ports()
 	const int a_ins = _n_inputs;
 	const int a_out = _n_outputs;
 
+	const uint32_t lcpp = (_periods_per_cycle - 2) * _samples_per_period;
+
 	/* audio ports */
 	lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_input_latency);
 	for (int i = 1; i <= a_ins; ++i) {
@@ -1216,27 +1364,31 @@ AlsaAudioBackend::register_system_audio_ports()
 		PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
 		if (!p) return -1;
 		set_latency_range (p, false, lr);
-		_system_inputs.push_back(static_cast<AlsaPort*>(p));
+		AlsaPort *ap = static_cast<AlsaPort*>(p);
+		//ap->set_pretty_name ("")
+		_system_inputs.push_back (ap);
 	}
 
-	lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency);
+	lr.min = lr.max = lcpp + (_measure_latency ? 0 : _systemic_audio_output_latency);
 	for (int i = 1; i <= a_out; ++i) {
 		char tmp[64];
 		snprintf(tmp, sizeof(tmp), "system:playback_%d", i);
 		PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
 		if (!p) return -1;
 		set_latency_range (p, true, lr);
-		_system_outputs.push_back(static_cast<AlsaPort*>(p));
+		AlsaPort *ap = static_cast<AlsaPort*>(p);
+		//ap->set_pretty_name ("")
+		_system_outputs.push_back (ap);
 	}
 	return 0;
 }
 
 int
-AlsaAudioBackend::register_system_midi_ports()
+AlsaAudioBackend::register_system_midi_ports(const std::string device)
 {
 	std::map<std::string, std::string> devices;
-	int midi_ins = 0;
-	int midi_outs = 0;
+
+	// TODO use consistent numbering when re-adding devices: _midi_ins, _midi_outs
 
 	if (_midi_driver_option == get_standard_device_name(DeviceNone)) {
 		return 0;
@@ -1247,15 +1399,18 @@ AlsaAudioBackend::register_system_midi_ports()
 	}
 
 	for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+		if (!device.empty() && device != i->first) {
+			continue;
+		}
 		struct AlsaMidiDeviceInfo * nfo = midi_device_info(i->first);
 		if (!nfo) continue;
 		if (!nfo->enabled) continue;
 
 		AlsaMidiOut *mout;
 		if (_midi_driver_option == _("ALSA raw devices")) {
-			mout = new AlsaRawMidiOut (i->second.c_str());
+			mout = new AlsaRawMidiOut (i->first, i->second.c_str());
 		} else {
-			mout = new AlsaSeqMidiOut (i->second.c_str());
+			mout = new AlsaSeqMidiOut (i->first, i->second.c_str());
 		}
 
 		if (mout->state ()) {
@@ -1273,7 +1428,7 @@ AlsaAudioBackend::register_system_midi_ports()
 				delete mout;
 			} else {
 				char tmp[64];
-				snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++midi_ins);
+				snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++_midi_ins);
 				PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
 				if (!p) {
 					mout->stop();
@@ -1281,18 +1436,20 @@ AlsaAudioBackend::register_system_midi_ports()
 				}
 				LatencyRange lr;
 				lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency);
-				set_latency_range (p, false, lr);
-				static_cast<AlsaMidiPort*>(p)->set_n_periods(2);
-				_system_midi_out.push_back(static_cast<AlsaPort*>(p));
+				set_latency_range (p, true, lr);
+				static_cast<AlsaMidiPort*>(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment
+				AlsaPort *ap = static_cast<AlsaPort*>(p);
+				ap->set_pretty_name (i->first);
+				_system_midi_out.push_back (ap);
 				_rmidi_out.push_back (mout);
 			}
 		}
 
 		AlsaMidiIn *midin;
 		if (_midi_driver_option == _("ALSA raw devices")) {
-			midin = new AlsaRawMidiIn (i->second.c_str());
+			midin = new AlsaRawMidiIn (i->first, i->second.c_str());
 		} else {
-			midin = new AlsaSeqMidiIn (i->second.c_str());
+			midin = new AlsaSeqMidiIn (i->first, i->second.c_str());
 		}
 
 		if (midin->state ()) {
@@ -1310,7 +1467,7 @@ AlsaAudioBackend::register_system_midi_ports()
 				delete midin;
 			} else {
 				char tmp[64];
-				snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++midi_outs);
+				snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++_midi_outs);
 				PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
 				if (!p) {
 					midin->stop();
@@ -1320,7 +1477,9 @@ AlsaAudioBackend::register_system_midi_ports()
 				LatencyRange lr;
 				lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_input_latency);
 				set_latency_range (p, false, lr);
-				_system_midi_in.push_back(static_cast<AlsaPort*>(p));
+				AlsaPort *ap = static_cast<AlsaPort*>(p);
+				ap->set_pretty_name (i->first);
+				_system_midi_in.push_back (ap);
 				_rmidi_in.push_back (midin);
 			}
 		}
diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h
index c95593c..01f7579 100644
--- a/libs/backends/alsa/alsa_audiobackend.h
+++ b/libs/backends/alsa/alsa_audiobackend.h
@@ -70,9 +70,11 @@ class AlsaPort {
 		virtual ~AlsaPort ();
 
 		const std::string& name () const { return _name; }
+		const std::string& pretty_name () const { return _pretty_name; }
 		PortFlags flags () const { return _flags; }
 
 		int set_name (const std::string &name) { _name = name; return 0; }
+		int set_pretty_name (const std::string &name) { _pretty_name = name; return 0; }
 
 		virtual DataType type () const = 0;
 
@@ -112,6 +114,7 @@ class AlsaPort {
 	private:
 		AlsaAudioBackend &_alsa_backend;
 		std::string _name;
+		std::string _pretty_name;
 		const PortFlags _flags;
 		LatencyRange _capture_latency_range;
 		LatencyRange _playback_latency_range;
@@ -148,10 +151,10 @@ class AlsaMidiPort : public AlsaPort {
 		const AlsaMidiBuffer * const_buffer () const { return & _buffer[_bufperiod]; }
 
 		void next_period() { if (_n_periods > 1) { get_buffer(0); _bufperiod = (_bufperiod + 1) % _n_periods; } }
-		void set_n_periods(int n) { if (n > 0 && n < 3) { _n_periods = n; } }
+		void set_n_periods(int n) { if (n > 0 && n < 4) { _n_periods = n; } }
 
 	private:
-		AlsaMidiBuffer _buffer[2];
+		AlsaMidiBuffer _buffer[3];
 		int _n_periods;
 		int _bufperiod;
 }; // class AlsaMidiPort
@@ -168,6 +171,8 @@ class AlsaAudioBackend : public AudioBackend {
 		bool is_realtime () const;
 
 		bool use_separate_input_and_output_devices () const { return true; }
+		bool can_set_period_size () const { return true; }
+
 		std::vector<DeviceStatus> enumerate_devices () const;
 		std::vector<DeviceStatus> enumerate_input_devices () const;
 		std::vector<DeviceStatus> enumerate_output_devices () const;
@@ -175,17 +180,21 @@ class AlsaAudioBackend : public AudioBackend {
 		std::vector<float> available_sample_rates2 (const std::string&, const std::string&) const;
 		std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
 		std::vector<uint32_t> available_buffer_sizes2 (const std::string&, const std::string&) const;
+		std::vector<uint32_t> available_period_sizes (const std::string& driver) const;
 		uint32_t available_input_channel_count (const std::string& device) const;
 		uint32_t available_output_channel_count (const std::string& device) const;
 
 		bool can_change_sample_rate_when_running () const;
 		bool can_change_buffer_size_when_running () const;
 
+		bool can_change_systemic_latency_when_running () const { return true; }
+
 		int set_device_name (const std::string&);
 		int set_input_device_name (const std::string&);
 		int set_output_device_name (const std::string&);
 		int set_sample_rate (float);
 		int set_buffer_size (uint32_t);
+		int set_peridod_size (uint32_t);
 		int set_interleaved (bool yn);
 		int set_input_channels (uint32_t);
 		int set_output_channels (uint32_t);
@@ -202,6 +211,7 @@ class AlsaAudioBackend : public AudioBackend {
 		std::string  output_device_name () const;
 		float        sample_rate () const;
 		uint32_t     buffer_size () const;
+		uint32_t     period_size () const;
 		bool         interleaved () const;
 		uint32_t     input_channels () const;
 		uint32_t     output_channels () const;
@@ -256,6 +266,7 @@ class AlsaAudioBackend : public AudioBackend {
 		int         set_port_name (PortHandle, const std::string&);
 		std::string get_port_name (PortHandle) const;
 		PortHandle  get_port_by_name (const std::string&) const;
+		int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const;
 
 		int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
 
@@ -388,7 +399,7 @@ class AlsaAudioBackend : public AudioBackend {
 		/* port engine */
 		PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
 		int register_system_audio_ports ();
-		int register_system_midi_ports ();
+		int register_system_midi_ports (const std::string device = "");
 		void unregister_ports (bool system_only = false);
 
 		std::vector<AlsaPort *> _ports;
@@ -400,6 +411,9 @@ class AlsaAudioBackend : public AudioBackend {
 		std::vector<AlsaMidiOut *> _rmidi_out;
 		std::vector<AlsaMidiIn  *> _rmidi_in;
 
+		unsigned _midi_ins;
+		unsigned _midi_outs;
+
 		struct PortConnectData {
 			std::string a;
 			std::string b;
@@ -438,6 +452,9 @@ class AlsaAudioBackend : public AudioBackend {
 			return NULL;
 		}
 
+		void update_systemic_audio_latencies ();
+		void update_systemic_midi_latencies ();
+
 }; // class AlsaAudioBackend
 
 } // namespace
diff --git a/libs/backends/alsa/alsa_midi.h b/libs/backends/alsa/alsa_midi.h
index 7da991d..2548355 100644
--- a/libs/backends/alsa/alsa_midi.h
+++ b/libs/backends/alsa/alsa_midi.h
@@ -42,6 +42,8 @@ public:
 
 	virtual void* main_process_thread () = 0;
 
+	const std::string & name () const { return _name; }
+
 protected:
 	pthread_t _main_thread;
 	pthread_mutex_t _notify_mutex;
@@ -68,7 +70,8 @@ protected:
 
 	RingBuffer<uint8_t>* _rb;
 
-protected:
+	std::string _name;
+
 	virtual void init (const char *device_name, const bool input) = 0;
 
 };
diff --git a/libs/backends/alsa/alsa_rawmidi.cc b/libs/backends/alsa/alsa_rawmidi.cc
index e4678ba..303649b 100644
--- a/libs/backends/alsa/alsa_rawmidi.cc
+++ b/libs/backends/alsa/alsa_rawmidi.cc
@@ -38,10 +38,11 @@ using namespace ARDOUR;
 #define _DEBUGPRINT(STR) ;
 #endif
 
-AlsaRawMidiIO::AlsaRawMidiIO (const char *device, const bool input)
+AlsaRawMidiIO::AlsaRawMidiIO (const std::string &name, const char *device, const bool input)
 	: AlsaMidiIO()
 	, _device (0)
 {
+	_name = name;
 	init (device, input);
 }
 
@@ -107,8 +108,8 @@ initerr:
 
 ///////////////////////////////////////////////////////////////////////////////
 
-AlsaRawMidiOut::AlsaRawMidiOut (const char *device)
-		: AlsaRawMidiIO (device, false)
+AlsaRawMidiOut::AlsaRawMidiOut (const std::string &name, const char *device)
+		: AlsaRawMidiIO (name, device, false)
 		, AlsaMidiOut ()
 {
 }
@@ -223,8 +224,8 @@ retry:
 
 ///////////////////////////////////////////////////////////////////////////////
 
-AlsaRawMidiIn::AlsaRawMidiIn (const char *device)
-		: AlsaRawMidiIO (device, true)
+AlsaRawMidiIn::AlsaRawMidiIn (const std::string &name, const char *device)
+		: AlsaRawMidiIO (name, device, true)
 		, AlsaMidiIn ()
 		, _event(0,0)
 		, _first_time(true)
diff --git a/libs/backends/alsa/alsa_rawmidi.h b/libs/backends/alsa/alsa_rawmidi.h
index 5d9a86c..654f084 100644
--- a/libs/backends/alsa/alsa_rawmidi.h
+++ b/libs/backends/alsa/alsa_rawmidi.h
@@ -33,7 +33,7 @@ namespace ARDOUR {
 
 class AlsaRawMidiIO : virtual public AlsaMidiIO {
 public:
-	AlsaRawMidiIO (const char *device, const bool input);
+	AlsaRawMidiIO (const std::string &name, const char *device, const bool input);
 	virtual ~AlsaRawMidiIO ();
 
 protected:
@@ -46,14 +46,14 @@ private:
 class AlsaRawMidiOut : public AlsaRawMidiIO, public AlsaMidiOut
 {
 public:
-	AlsaRawMidiOut (const char *device);
+	AlsaRawMidiOut (const std::string &name, const char *device);
 	void* main_process_thread ();
 };
 
 class AlsaRawMidiIn : public AlsaRawMidiIO, public AlsaMidiIn
 {
 public:
-	AlsaRawMidiIn (const char *device);
+	AlsaRawMidiIn (const std::string &name, const char *device);
 
 	void* main_process_thread ();
 
diff --git a/libs/backends/alsa/alsa_sequencer.cc b/libs/backends/alsa/alsa_sequencer.cc
index aa0aac0..cb77c3c 100644
--- a/libs/backends/alsa/alsa_sequencer.cc
+++ b/libs/backends/alsa/alsa_sequencer.cc
@@ -37,10 +37,11 @@ using namespace ARDOUR;
 #define _DEBUGPRINT(STR) ;
 #endif
 
-AlsaSeqMidiIO::AlsaSeqMidiIO (const char *device, const bool input)
+AlsaSeqMidiIO::AlsaSeqMidiIO (const std::string &name, const char *device, const bool input)
 	: AlsaMidiIO()
 	, _seq (0)
 {
+	_name = name;
 	init (device, input);
 }
 
@@ -117,8 +118,8 @@ initerr:
 
 ///////////////////////////////////////////////////////////////////////////////
 
-AlsaSeqMidiOut::AlsaSeqMidiOut (const char *device)
-		: AlsaSeqMidiIO (device, false)
+AlsaSeqMidiOut::AlsaSeqMidiOut (const std::string &name, const char *device)
+		: AlsaSeqMidiIO (name, device, false)
 		, AlsaMidiOut ()
 {
 }
@@ -227,8 +228,8 @@ retry:
 
 ///////////////////////////////////////////////////////////////////////////////
 
-AlsaSeqMidiIn::AlsaSeqMidiIn (const char *device)
-		: AlsaSeqMidiIO (device, true)
+AlsaSeqMidiIn::AlsaSeqMidiIn (const std::string &name, const char *device)
+		: AlsaSeqMidiIO (name, device, true)
 		, AlsaMidiIn ()
 {
 }
diff --git a/libs/backends/alsa/alsa_sequencer.h b/libs/backends/alsa/alsa_sequencer.h
index bc00751..2c27778 100644
--- a/libs/backends/alsa/alsa_sequencer.h
+++ b/libs/backends/alsa/alsa_sequencer.h
@@ -33,7 +33,7 @@ namespace ARDOUR {
 
 class AlsaSeqMidiIO : virtual public AlsaMidiIO {
 public:
-	AlsaSeqMidiIO (const char *port_name, const bool input);
+	AlsaSeqMidiIO (const std::string &name, const char *port_name, const bool input);
 	virtual ~AlsaSeqMidiIO ();
 
 protected:
@@ -47,14 +47,14 @@ private:
 class AlsaSeqMidiOut : public AlsaSeqMidiIO, public AlsaMidiOut
 {
 public:
-	AlsaSeqMidiOut (const char *port_name);
+	AlsaSeqMidiOut (const std::string &name, const char *port_name);
 	void* main_process_thread ();
 };
 
 class AlsaSeqMidiIn : public AlsaSeqMidiIO, public AlsaMidiIn
 {
 public:
-	AlsaSeqMidiIn (const char *port_name);
+	AlsaSeqMidiIn (const std::string &name, const char *port_name);
 
 	void* main_process_thread ();
 };
diff --git a/libs/backends/alsa/zita-alsa-pcmi.cc b/libs/backends/alsa/zita-alsa-pcmi.cc
index d3be95e..c5480fd 100644
--- a/libs/backends/alsa/zita-alsa-pcmi.cc
+++ b/libs/backends/alsa/zita-alsa-pcmi.cc
@@ -44,11 +44,13 @@ Alsa_pcmi::Alsa_pcmi (
 		const char        *ctrl_name,
 		unsigned int       fsamp,
 		unsigned int       fsize,
-		unsigned int       nfrag,
+		unsigned int       play_nfrag,
+		unsigned int       capt_nfrag,
 		unsigned int       debug)
 	: _fsamp (fsamp)
 	, _fsize (fsize)
-	, _nfrag (nfrag)
+	, _play_nfrag (play_nfrag)
+	, _capt_nfrag (capt_nfrag)
 	, _debug (debug)
 	, _state (-1)
 	, _play_handle (0)
@@ -95,12 +97,12 @@ int Alsa_pcmi::pcm_start (void)
 	if (_play_handle)
 	{
 		n = snd_pcm_avail_update (_play_handle);
-		if (n != _fsize * _nfrag)
+		if (n != _fsize * _play_nfrag)
 		{
 			if (_debug & DEBUG_STAT) fprintf  (stderr, "Alsa_pcmi: full buffer not available at start.\n");
 			return -1;
 		}
-		for (i = 0; i < _nfrag; i++)
+		for (i = 0; i < _play_nfrag; i++)
 		{
 			play_init (_fsize);
 			for (j = 0; j < _play_nchan; j++) clear_chan (j, _fsize);
@@ -353,7 +355,7 @@ void Alsa_pcmi::printinfo (void)
 		fprintf (stdout, "\n  nchan  : %d\n", _play_nchan);
 		fprintf (stdout, "  fsamp  : %d\n", _fsamp);
 		fprintf (stdout, "  fsize  : %ld\n", _fsize);
-		fprintf (stdout, "  nfrag  : %d\n", _nfrag);
+		fprintf (stdout, "  nfrag  : %d\n", _play_nfrag);
 		fprintf (stdout, "  format : %s\n", snd_pcm_format_name (_play_format));
 	}
 	else fprintf (stdout, " not enabled\n");
@@ -363,7 +365,7 @@ void Alsa_pcmi::printinfo (void)
 		fprintf (stdout, "\n  nchan  : %d\n", _capt_nchan);
 		fprintf (stdout, "  fsamp  : %d\n", _fsamp);
 		fprintf (stdout, "  fsize  : %ld\n", _fsize);
-		fprintf (stdout, "  nfrag  : %d\n", _nfrag);
+		fprintf (stdout, "  nfrag  : %d\n", _capt_nfrag);
 		fprintf (stdout, "  format : %s\n", snd_pcm_format_name (_capt_format));
 		if (_play_handle) fprintf (stdout, "%s\n", _synced ? "synced" : "not synced");
 	}
@@ -436,7 +438,7 @@ void Alsa_pcmi::initialise (const char *play_name, const char *capt_name, const
 			if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't allocate playback sw params\n");
 			return;
 		}
-		if (set_hwpar (_play_handle, _play_hwpar, "playback", &_play_nchan) < 0) return;
+		if (set_hwpar (_play_handle, _play_hwpar, "playback", _play_nfrag, &_play_nchan) < 0) return;
 		if (set_swpar (_play_handle, _play_swpar, "playback") < 0) return;
 	}
 
@@ -452,7 +454,7 @@ void Alsa_pcmi::initialise (const char *play_name, const char *capt_name, const
 			if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't allocate capture sw params\n");
 			return;
 		}
-		if (set_hwpar (_capt_handle, _capt_hwpar, "capture", &_capt_nchan) < 0) return;
+		if (set_hwpar (_capt_handle, _capt_hwpar, "capture", _capt_nfrag, &_capt_nchan) < 0) return;
 		if (set_swpar (_capt_handle, _capt_swpar, "capture") < 0) return;
 	}
 
@@ -470,7 +472,7 @@ void Alsa_pcmi::initialise (const char *play_name, const char *capt_name, const
 			_state = -4;
 			return;
 		}
-		if (snd_pcm_hw_params_get_periods (_play_hwpar, &nfrag, &dir) || (nfrag != _nfrag) || dir)
+		if (snd_pcm_hw_params_get_periods (_play_hwpar, &nfrag, &dir) || (nfrag != _play_nfrag) || dir)
 		{
 			if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested number of periods for playback.\n");
 			_state = -5;
@@ -582,7 +584,7 @@ void Alsa_pcmi::initialise (const char *play_name, const char *capt_name, const
 			_state = -4;
 			return;
 		}
-		if (snd_pcm_hw_params_get_periods (_capt_hwpar, &nfrag, &dir) || (nfrag != _nfrag) || dir)
+		if (snd_pcm_hw_params_get_periods (_capt_hwpar, &nfrag, &dir) || (nfrag != _capt_nfrag) || dir)
 		{
 			if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't get requested number of periods for capture.\n");
 			_state = -5;
@@ -679,7 +681,7 @@ void Alsa_pcmi::initialise (const char *play_name, const char *capt_name, const
 }
 
 
-int Alsa_pcmi::set_hwpar (snd_pcm_t *handle,  snd_pcm_hw_params_t *hwpar, const char *sname, unsigned int *nchan)
+int Alsa_pcmi::set_hwpar (snd_pcm_t *handle,  snd_pcm_hw_params_t *hwpar, const char *sname, unsigned int nfrag, unsigned int *nchan)
 {
 	bool err;
 
@@ -760,16 +762,16 @@ int Alsa_pcmi::set_hwpar (snd_pcm_t *handle,  snd_pcm_hw_params_t *hwpar, const
 				sname, _fsize);
 		return -4;
 	}
-	if (snd_pcm_hw_params_set_periods (handle, hwpar, _nfrag, 0) < 0)
+	if (snd_pcm_hw_params_set_periods (handle, hwpar, nfrag, 0) < 0)
 	{
 		if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s periods to %u.\n",
-				sname, _nfrag);
+				sname, nfrag);
 		return -5;
 	}
-	if (snd_pcm_hw_params_set_buffer_size (handle, hwpar, _fsize * _nfrag) < 0)
+	if (snd_pcm_hw_params_set_buffer_size (handle, hwpar, _fsize * nfrag) < 0)
 	{
 		if (_debug & DEBUG_INIT) fprintf (stderr, "Alsa_pcmi: can't set %s buffer length to %lu.\n",
-				sname, _fsize * _nfrag);
+				sname, _fsize * nfrag);
 		return -4;
 	}
 	if (snd_pcm_hw_params (handle, hwpar) < 0)
diff --git a/libs/backends/alsa/zita-alsa-pcmi.h b/libs/backends/alsa/zita-alsa-pcmi.h
index 5f7377d..27af022 100644
--- a/libs/backends/alsa/zita-alsa-pcmi.h
+++ b/libs/backends/alsa/zita-alsa-pcmi.h
@@ -46,7 +46,8 @@ public:
 			const char   *ctrl_name,
 			unsigned int  rate,
 			unsigned int  frsize,
-			unsigned int  nfrags,
+			unsigned int  play_nfrags,
+			unsigned int  capt_nfrags,
 			unsigned int  debug = 0);
 
 	~Alsa_pcmi (void);
@@ -108,7 +109,8 @@ public:
 	int      state (void) const { return _state; }
 	size_t   fsize (void) const { return _fsize; }
 	uint32_t fsamp (void) const { return _fsamp; }
-	uint32_t nfrag (void) const { return _nfrag; }
+	uint32_t play_nfrag (void) const { return _play_nfrag; }
+	uint32_t capt_nfrag (void) const { return _capt_nfrag; }
 	uint32_t nplay (void) const { return _play_nchan; }
 	uint32_t ncapt (void) const { return _capt_nchan; }
 	snd_pcm_t *play_handle (void) const { return _play_handle; }
@@ -124,7 +126,7 @@ private:
 	enum { MAXPFD = 16, MAXCHAN = 64 };
 
 	void initialise (const char *play_name, const char *capt_name, const char *ctrl_name);
-	int set_hwpar (snd_pcm_t *handle, snd_pcm_hw_params_t *hwpar, const char *sname, unsigned int *nchan);
+	int set_hwpar (snd_pcm_t *handle, snd_pcm_hw_params_t *hwpar, const char *sname, unsigned int nfrag, unsigned int *nchan);
 	int set_swpar (snd_pcm_t *handle, snd_pcm_sw_params_t *swpar, const char *sname);
 	int recover (void);
 	float xruncheck (snd_pcm_status_t *stat);
@@ -151,7 +153,8 @@ private:
 
 	unsigned int           _fsamp;
 	snd_pcm_uframes_t      _fsize;
-	unsigned int           _nfrag;
+	unsigned int           _play_nfrag;
+	unsigned int           _capt_nfrag;
 	unsigned int           _debug;
 	int                    _state;
 	snd_pcm_t             *_play_handle;
diff --git a/libs/backends/coreaudio/coreaudio_backend.cc b/libs/backends/coreaudio/coreaudio_backend.cc
index c08dacd..a620bf0 100644
--- a/libs/backends/coreaudio/coreaudio_backend.cc
+++ b/libs/backends/coreaudio/coreaudio_backend.cc
@@ -17,21 +17,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-
-/* use an additional midi message parser
- *
- * coreaudio does packetize midi. every packet includes a timestamp.
- * With any real midi-device with a phyical layer
- * 1 packet = 1 event (no concurrent events are possible on a cable)
- *
- * Howver, some USB-midi keyboards manage to send concurrent events
- * which end up in the same packet (eg. 6 byte message: 2 note-on).
- *
- * An additional parser is needed to separate them
- */
-#define USE_MIDI_PARSER
-
-
 #include <regex.h>
 #include <sys/mman.h>
 #include <sys/time.h>
@@ -119,13 +104,6 @@ CoreAudioBackend::CoreAudioBackend (AudioEngine& e, AudioBackendInfo& info)
 	, _dsp_load (0)
 	, _processed_samples (0)
 	, _port_change_flag (false)
-#ifdef USE_MIDI_PARSER
-	, _unbuffered_bytes(0)
-	, _total_bytes(0)
-	, _expected_bytes(0)
-	, _status_byte(0)
-	, _parser_bytes(0)
-#endif
 {
 	_instance_name = s_instance_name;
 	pthread_mutex_init (&_port_callback_mutex, 0);
@@ -547,60 +525,60 @@ CoreAudioBackend::_start (bool for_latency_measurement)
 	printf("STATE: %d\n", _pcmio->state ());
 #endif
 	switch (_pcmio->state ()) {
-		case 0: /* OK */
-			break;
-		case -1:
-			PBD::error << _("CoreAudioBackend: Invalid Device ID.") << endmsg;
-			error_code = AudioDeviceInvalidError;
-			break;
-		case -2:
-			PBD::error << _("CoreAudioBackend: Failed to resolve Device-Component by ID.") << endmsg;
-			error_code = AudioDeviceNotAvailableError;
-			break;
-		case -3:
-			PBD::error << _("CoreAudioBackend: failed to open device.") << endmsg;
-			error_code = AudioDeviceOpenError;
-			break;
-		case -4:
-			PBD::error << _("CoreAudioBackend: cannot set requested sample rate.") << endmsg;
-			error_code = SampleRateNotSupportedError;
-			break;
-		case -5:
-			PBD::error << _("CoreAudioBackend: cannot configure requested buffer size.") << endmsg;
-			error_code = PeriodSizeNotSupportedError;
-			break;
-		case -6:
-			PBD::error << _("CoreAudioBackend: unsupported sample format.") << endmsg;
-			error_code = SampleFormatNotSupportedError;
-			break;
-		case -7:
-			PBD::error << _("CoreAudioBackend: Failed to enable Device.") << endmsg;
-			error_code = BackendInitializationError; // XXX
-			break;
-		case -8:
-			PBD::error << _("CoreAudioBackend: Cannot allocate buffers, out-of-memory.") << endmsg;
-			error_code = OutOfMemoryError;
-			break;
-		case -9:
-			PBD::error << _("CoreAudioBackend: Failed to set device-property listeners.") << endmsg;
-			error_code = BackendInitializationError; // XXX
-			break;
-		case -10:
-			PBD::error << _("CoreAudioBackend: Setting Process Callback failed.") << endmsg;
-			error_code = AudioDeviceIOError;
-			break;
-		case -11:
-			PBD::error << _("CoreAudioBackend: cannot use requested period size.") << endmsg;
-			error_code = PeriodSizeNotSupportedError;
-			break;
-		case -12:
-			PBD::error << _("CoreAudioBackend: cannot create aggregate device.") << endmsg;
-			error_code = DeviceConfigurationNotSupportedError;
-			break;
-		default:
-			PBD::error << _("CoreAudioBackend: initialization failure.") << endmsg;
-			error_code = BackendInitializationError;
-			break;
+	case 0: /* OK */
+		break;
+	case -1:
+		PBD::error << _("CoreAudioBackend: Invalid Device ID.") << endmsg;
+		error_code = AudioDeviceInvalidError;
+		break;
+	case -2:
+		PBD::error << _("CoreAudioBackend: Failed to resolve Device-Component by ID.") << endmsg;
+		error_code = AudioDeviceNotAvailableError;
+		break;
+	case -3:
+		PBD::error << _("CoreAudioBackend: failed to open device.") << endmsg;
+		error_code = AudioDeviceOpenError;
+		break;
+	case -4:
+		PBD::error << _("CoreAudioBackend: cannot set requested sample rate.") << endmsg;
+		error_code = SampleRateNotSupportedError;
+		break;
+	case -5:
+		PBD::error << _("CoreAudioBackend: cannot configure requested buffer size.") << endmsg;
+		error_code = PeriodSizeNotSupportedError;
+		break;
+	case -6:
+		PBD::error << _("CoreAudioBackend: unsupported sample format.") << endmsg;
+		error_code = SampleFormatNotSupportedError;
+		break;
+	case -7:
+		PBD::error << _("CoreAudioBackend: Failed to enable Device.") << endmsg;
+		error_code = BackendInitializationError; // XXX
+		break;
+	case -8:
+		PBD::error << _("CoreAudioBackend: Cannot allocate buffers, out-of-memory.") << endmsg;
+		error_code = OutOfMemoryError;
+		break;
+	case -9:
+		PBD::error << _("CoreAudioBackend: Failed to set device-property listeners.") << endmsg;
+		error_code = BackendInitializationError; // XXX
+		break;
+	case -10:
+		PBD::error << _("CoreAudioBackend: Setting Process Callback failed.") << endmsg;
+		error_code = AudioDeviceIOError;
+		break;
+	case -11:
+		PBD::error << _("CoreAudioBackend: cannot use requested period size.") << endmsg;
+		error_code = PeriodSizeNotSupportedError;
+		break;
+	case -12:
+		PBD::error << _("CoreAudioBackend: cannot create aggregate device.") << endmsg;
+		error_code = DeviceConfigurationNotSupportedError;
+		break;
+	default:
+		PBD::error << _("CoreAudioBackend: initialization failure.") << endmsg;
+		error_code = BackendInitializationError;
+		break;
 	}
 	if (_pcmio->state ()) {
 		return error_code;
@@ -608,18 +586,18 @@ CoreAudioBackend::_start (bool for_latency_measurement)
 
 	if (_n_outputs != _pcmio->n_playback_channels ()) {
 		if (_n_outputs == 0) {
-		 _n_outputs = _pcmio->n_playback_channels ();
+			_n_outputs = _pcmio->n_playback_channels ();
 		} else {
-		 _n_outputs = std::min (_n_outputs, _pcmio->n_playback_channels ());
+			_n_outputs = std::min (_n_outputs, _pcmio->n_playback_channels ());
 		}
 		PBD::info << _("CoreAudioBackend: adjusted output channel count to match device.") << endmsg;
 	}
 
 	if (_n_inputs != _pcmio->n_capture_channels ()) {
 		if (_n_inputs == 0) {
-		 _n_inputs = _pcmio->n_capture_channels ();
+			_n_inputs = _pcmio->n_capture_channels ();
 		} else {
-		 _n_inputs = std::min (_n_inputs, _pcmio->n_capture_channels ());
+			_n_inputs = std::min (_n_inputs, _pcmio->n_capture_channels ());
 		}
 		PBD::info << _("CoreAudioBackend: adjusted input channel count to match device.") << endmsg;
 	}
@@ -762,10 +740,10 @@ size_t
 CoreAudioBackend::raw_buffer_size (DataType t)
 {
 	switch (t) {
-		case DataType::AUDIO:
-			return _samples_per_period * sizeof(Sample);
-		case DataType::MIDI:
-			return _max_buffer_size; // XXX not really limited
+	case DataType::AUDIO:
+		return _samples_per_period * sizeof(Sample);
+	case DataType::MIDI:
+		return _max_buffer_size; // XXX not really limited
 	}
 	return 0;
 }
@@ -833,7 +811,7 @@ CoreAudioBackend::create_process_thread (boost::function<void()> func)
 	ThreadData* td = new ThreadData (this, func, stacksize);
 
 	if (_realtime_pthread_create (SCHED_FIFO, -21, stacksize,
-				&thread_id, coreaudio_process_thread, td)) {
+	                              &thread_id, coreaudio_process_thread, td)) {
 		pthread_attr_init (&attr);
 		pthread_attr_setstacksize (&attr, stacksize);
 		if (pthread_create (&thread_id, &attr, coreaudio_process_thread, td)) {
@@ -944,7 +922,7 @@ int
 CoreAudioBackend::get_port_property (PortHandle port, const std::string& key, std::string& value, std::string& type) const
 {
 	if (!valid_port (port)) {
-		PBD::warning << _("CoreAudioBackend::get_port_name: Invalid Port(s)") << endmsg;
+		PBD::warning << _("CoreAudioBackend::get_port_property: Invalid Port(s)") << endmsg;
 		return -1;
 	}
 	if (key == "http://jackaudio.org/metadata/pretty-name") {
@@ -966,9 +944,9 @@ CoreAudioBackend::get_port_by_name (const std::string& name) const
 
 int
 CoreAudioBackend::get_ports (
-		const std::string& port_name_pattern,
-		DataType type, PortFlags flags,
-		std::vector<std::string>& port_names) const
+	const std::string& port_name_pattern,
+	DataType type, PortFlags flags,
+	std::vector<std::string>& port_names) const
 {
 	int rv = 0;
 	regex_t port_regex;
@@ -1004,9 +982,9 @@ CoreAudioBackend::port_data_type (PortEngine::PortHandle port) const
 
 PortEngine::PortHandle
 CoreAudioBackend::register_port (
-		const std::string& name,
-		ARDOUR::DataType type,
-		ARDOUR::PortFlags flags)
+	const std::string& name,
+	ARDOUR::DataType type,
+	ARDOUR::PortFlags flags)
 {
 	if (name.size () == 0) { return 0; }
 	if (flags & IsPhysical) { return 0; }
@@ -1015,27 +993,27 @@ CoreAudioBackend::register_port (
 
 PortEngine::PortHandle
 CoreAudioBackend::add_port (
-		const std::string& name,
-		ARDOUR::DataType type,
-		ARDOUR::PortFlags flags)
+	const std::string& name,
+	ARDOUR::DataType type,
+	ARDOUR::PortFlags flags)
 {
 	assert(name.size ());
 	if (find_port (name)) {
 		PBD::warning << _("CoreAudioBackend::register_port: Port already exists:")
-				<< " (" << name << ")" << endmsg;
+		             << " (" << name << ")" << endmsg;
 		return 0;
 	}
 	CoreBackendPort* port = NULL;
 	switch (type) {
-		case DataType::AUDIO:
-			port = new CoreAudioPort (*this, name, flags);
-			break;
-		case DataType::MIDI:
-			port = new CoreMidiPort (*this, name, flags);
-			break;
-		default:
-			PBD::error << _("CoreAudioBackend::register_port: Invalid Data Type.") << endmsg;
-			return 0;
+	case DataType::AUDIO:
+		port = new CoreAudioPort (*this, name, flags);
+		break;
+	case DataType::MIDI:
+		port = new CoreMidiPort (*this, name, flags);
+		break;
+	default:
+		PBD::error << _("CoreAudioBackend::register_port: Invalid Data Type.") << endmsg;
+		return 0;
 	}
 
 	_ports.push_back (port);
@@ -1073,8 +1051,8 @@ CoreAudioBackend::register_system_audio_ports()
 
 #ifndef NDEBUG
 	printf("COREAUDIO LATENCY: i:%d, o:%d\n",
-			coreaudio_reported_input_latency,
-			coreaudio_reported_output_latency);
+	       coreaudio_reported_input_latency,
+	       coreaudio_reported_output_latency);
 #endif
 
 	/* audio ports */
@@ -1233,12 +1211,12 @@ CoreAudioBackend::connect (const std::string& src, const std::string& dst)
 
 	if (!src_port) {
 		PBD::warning << _("CoreAudioBackend::connect: Invalid Source port:")
-				<< " (" << src <<")" << endmsg;
+		             << " (" << src <<")" << endmsg;
 		return -1;
 	}
 	if (!dst_port) {
 		PBD::warning << _("CoreAudioBackend::connect: Invalid Destination port:")
-			<< " (" << dst <<")" << endmsg;
+		             << " (" << dst <<")" << endmsg;
 		return -1;
 	}
 	return src_port->connect (dst_port);
@@ -1267,7 +1245,7 @@ CoreAudioBackend::connect (PortEngine::PortHandle src, const std::string& dst)
 	}
 	if (!dst_port) {
 		PBD::warning << _("CoreAudioBackend::connect: Invalid Destination Port")
-			<< " (" << dst << ")" << endmsg;
+		             << " (" << dst << ")" << endmsg;
 		return -1;
 	}
 	return static_cast<CoreBackendPort*>(src)->connect (dst_port);
@@ -1348,9 +1326,9 @@ CoreAudioBackend::get_connections (PortEngine::PortHandle port, std::vector<std:
 /* MIDI */
 int
 CoreAudioBackend::midi_event_get (
-		pframes_t& timestamp,
-		size_t& size, uint8_t** buf, void* port_buffer,
-		uint32_t event_index)
+	pframes_t& timestamp,
+	size_t& size, uint8_t** buf, void* port_buffer,
+	uint32_t event_index)
 {
 	if (!buf || !port_buffer) return -1;
 	CoreMidiBuffer& source = * static_cast<CoreMidiBuffer*>(port_buffer);
@@ -1366,10 +1344,10 @@ CoreAudioBackend::midi_event_get (
 }
 
 int
-CoreAudioBackend::midi_event_put (
-		void* port_buffer,
-		pframes_t timestamp,
-		const uint8_t* buffer, size_t size)
+CoreAudioBackend::_midi_event_put (
+	void* port_buffer,
+	pframes_t timestamp,
+	const uint8_t* buffer, size_t size)
 {
 	if (!buffer || !port_buffer) return -1;
 	CoreMidiBuffer& dst = * static_cast<CoreMidiBuffer*>(port_buffer);
@@ -1377,13 +1355,14 @@ CoreAudioBackend::midi_event_put (
 #ifndef NDEBUG
 		// nevermind, ::get_buffer() sorts events
 		fprintf (stderr, "CoreMidiBuffer: unordered event: %d > %d\n",
-				(pframes_t)dst.back ()->timestamp (), timestamp);
+		         (pframes_t)dst.back ()->timestamp (), timestamp);
 #endif
 	}
 	dst.push_back (boost::shared_ptr<CoreMidiEvent>(new CoreMidiEvent (timestamp, buffer, size)));
 	return 0;
 }
 
+
 uint32_t
 CoreAudioBackend::get_midi_event_count (void* port_buffer)
 {
@@ -1508,9 +1487,9 @@ CoreAudioBackend::n_physical_outputs () const
 		CoreBackendPort* port = _ports[i];
 		if (port->is_output () && port->is_physical ()) {
 			switch (port->type ()) {
-				case DataType::AUDIO: ++n_audio; break;
-				case DataType::MIDI: ++n_midi; break;
-				default: break;
+			case DataType::AUDIO: ++n_audio; break;
+			case DataType::MIDI: ++n_midi; break;
+			default: break;
 			}
 		}
 	}
@@ -1529,9 +1508,9 @@ CoreAudioBackend::n_physical_inputs () const
 		CoreBackendPort* port = _ports[i];
 		if (port->is_input () && port->is_physical ()) {
 			switch (port->type ()) {
-				case DataType::AUDIO: ++n_audio; break;
-				case DataType::MIDI: ++n_midi; break;
-				default: break;
+			case DataType::AUDIO: ++n_audio; break;
+			case DataType::MIDI: ++n_midi; break;
+			default: break;
 			}
 		}
 	}
@@ -1583,6 +1562,17 @@ CoreAudioBackend::pre_process ()
 	}
 }
 
+void
+CoreAudioBackend::reset_midi_parsers ()
+{
+	for (std::vector<CoreBackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
+		CoreMidiPort* port = dynamic_cast<CoreMidiPort*>(*it);
+		if (port) {
+			port->reset_parser ();
+		}
+	}
+}
+
 void *
 CoreAudioBackend::freewheel_thread ()
 {
@@ -1608,6 +1598,7 @@ CoreAudioBackend::freewheel_thread ()
 				_freewheel = false; // first mark as disabled
 				_reinit_thread_callback = true; // hand over _main_thread
 				_freewheel_ack = false; // prepare next handshake
+				reset_midi_parsers ();
 				_midiio->set_enabled(true);
 				engine.freewheel_callback (_freewheeling);
 			} else {
@@ -1635,6 +1626,7 @@ CoreAudioBackend::freewheel_thread ()
 			_main_thread = pthread_self();
 			AudioEngine::thread_init_callback (this);
 			_midiio->set_enabled(false);
+			reset_midi_parsers ();
 		}
 
 		// process port updates first in every cycle.
@@ -1674,101 +1666,6 @@ CoreAudioBackend::freewheel_thread ()
 	}
 	return 0;
 }
-
-#ifdef USE_MIDI_PARSER
-bool
-CoreAudioBackend::midi_process_byte (const uint8_t byte)
-{
-	if (byte >= 0xf8) {
-		// Realtime
-		if (byte == 0xfd) {
-			// undefined
-			return false;
-		}
-		midi_prepare_byte_event (byte);
-		return true;
-	}
-	if (byte == 0xf7) {
-		// Sysex end
-		if (_status_byte == 0xf0) {
-			midi_record_byte (byte);
-			return midi_prepare_buffered_event ();
-		}
-		_total_bytes = 0;
-		_unbuffered_bytes = 0;
-		_expected_bytes = 0;
-		_status_byte = 0;
-		return false;
-	}
-	if (byte >= 0x80) {
-		// Non-realtime status byte
-		if (_total_bytes) {
-			_total_bytes = 0;
-			_unbuffered_bytes = 0;
-		}
-		_status_byte = byte;
-		switch (byte & 0xf0) {
-			case 0x80:
-			case 0x90:
-			case 0xa0:
-			case 0xb0:
-			case 0xe0:
-				// Note On, Note Off, Aftertouch, Control Change, Pitch Wheel
-				_expected_bytes = 3;
-				break;
-			case 0xc0:
-			case 0xd0:
-				// Program Change, Channel Pressure
-				_expected_bytes = 2;
-				break;
-			case 0xf0:
-				switch (byte) {
-					case 0xf0:
-						// Sysex
-						_expected_bytes = 0;
-						break;
-					case 0xf1:
-					case 0xf3:
-						// MTC Quarter Frame, Song Select
-						_expected_bytes = 2;
-						break;
-					case 0xf2:
-						// Song Position
-						_expected_bytes = 3;
-						break;
-					case 0xf4:
-					case 0xf5:
-						// Undefined
-						_expected_bytes = 0;
-						_status_byte = 0;
-						return false;
-					case 0xf6:
-						// Tune Request
-						midi_prepare_byte_event (byte);
-						_expected_bytes = 0;
-						_status_byte = 0;
-						return true;
-				}
-		}
-		midi_record_byte (byte);
-		return false;
-	}
-	// Data byte
-	if (! _status_byte) {
-		// Data bytes without a status will be discarded.
-		_total_bytes++;
-		_unbuffered_bytes++;
-		return false;
-	}
-	if (! _total_bytes) {
-		midi_record_byte (_status_byte);
-	}
-	midi_record_byte(byte);
-	return (_total_bytes == _expected_bytes) ? midi_prepare_buffered_event() : false;
-}
-#endif
-
-
 int
 CoreAudioBackend::process_callback (const uint32_t n_samples, const uint64_t host_time)
 {
@@ -1816,38 +1713,21 @@ CoreAudioBackend::process_callback (const uint32_t n_samples, const uint64_t hos
 	/* get midi */
 	i=0;
 	for (std::vector<CoreBackendPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
-		CoreMidiBuffer* mbuf = static_cast<CoreMidiBuffer*>((*it)->get_buffer(0));
-		mbuf->clear();
+		CoreMidiPort* port = dynamic_cast<CoreMidiPort*> (*it);
+		if (!port) {
+			continue;
+		}
 		uint64_t time_ns;
 		uint8_t data[128]; // matches CoreMidi's MIDIPacket
 		size_t size = sizeof(data);
+
+		port->clear_events ();
+
 		while (_midiio->recv_event (i, nominal_time, time_ns, data, size)) {
 			pframes_t time = floor((float) time_ns * _samplerate * 1e-9);
 			assert (time < n_samples);
-#ifndef USE_MIDI_PARSER
-			midi_event_put((void*)mbuf, time, data, size);
-#else
-			assert (size < 128);// coremidi limit per packet
-			bool first_time = true; // this would need to be rememberd per port.
-			for (size_t mb = 0; mb < size; ++mb) {
-				if (first_time && !(data[mb] & 0x80)) {
-					/* expect a status byte at the beginning or every Packet.
-					 *
-					 * This parser drops messages spanning multiple packets
-					 * (sysex > 127 bytes).
-					 * see also libs/backends/alsa/alsa_rawmidi.cc
-					 * which implements a complete parser per port without this limit.
-					 */
-					continue;
-				}
-				first_time = false;
-
-				if (midi_process_byte (data[mb])) {
-					midi_event_put ((void*)mbuf, time, _parser_buffer, _parser_bytes);
-				}
-			}
-#endif
-			size = sizeof(data);
+			port->parse_events (time, data, size);
+			size = sizeof(data); /* prepare for next call to recv_event */
 		}
 	}
 
@@ -2069,8 +1949,8 @@ int CoreBackendPort::connect (CoreBackendPort *port)
 	if (is_connected (port)) {
 #if 0 // don't bother to warn about this for now. just ignore it
 		PBD::info << _("CoreBackendPort::connect (): ports are already connected:")
-			<< " (" << name () << ") -> (" << port->name () << ")"
-			<< endmsg;
+		          << " (" << name () << ") -> (" << port->name () << ")"
+		          << endmsg;
 #endif
 		return -1;
 	}
@@ -2098,8 +1978,8 @@ int CoreBackendPort::disconnect (CoreBackendPort *port)
 
 	if (!is_connected (port)) {
 		PBD::warning << _("CoreBackendPort::disconnect (): ports are not connected:")
-			<< " (" << name () << ") -> (" << port->name () << ")"
-			<< endmsg;
+		             << " (" << name () << ") -> (" << port->name () << ")"
+		             << endmsg;
 		return -1;
 	}
 	_disconnect (port, true);
@@ -2186,6 +2066,13 @@ CoreMidiPort::CoreMidiPort (CoreAudioBackend &b, const std::string& name, PortFl
 	: CoreBackendPort (b, name, flags)
 	, _n_periods (1)
 	, _bufperiod (0)
+	, _event (0, 0)
+	, _first_time(true)
+	, _unbuffered_bytes(0)
+	, _total_bytes(0)
+	, _expected_bytes(0)
+	, _status_byte(0)
+
 {
 	_buffer[0].clear ();
 	_buffer[1].clear ();
@@ -2204,8 +2091,8 @@ void* CoreMidiPort::get_buffer (pframes_t /* nframes */)
 	if (is_input ()) {
 		(_buffer[_bufperiod]).clear ();
 		for (std::vector<CoreBackendPort*>::const_iterator i = get_connections ().begin ();
-				i != get_connections ().end ();
-				++i) {
+		     i != get_connections ().end ();
+		     ++i) {
 			const CoreMidiBuffer * src = static_cast<const CoreMidiPort*>(*i)->const_buffer ();
 			for (CoreMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
 				(_buffer[_bufperiod]).push_back (boost::shared_ptr<CoreMidiEvent>(new CoreMidiEvent (**it)));
@@ -2213,9 +2100,167 @@ void* CoreMidiPort::get_buffer (pframes_t /* nframes */)
 		}
 		std::sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter());
 	}
+
 	return &(_buffer[_bufperiod]);
 }
 
+int
+CoreMidiPort::queue_event (
+	void* port_buffer,
+	pframes_t timestamp,
+	const uint8_t* buffer, size_t size)
+{
+	const int ret = CoreAudioBackend::_midi_event_put (port_buffer, timestamp, buffer, size);
+        if (!ret) { /* success */
+                _event._pending = false;
+        }
+        return ret;
+}
+
+void
+CoreMidiPort::reset_parser ()
+{
+	_event._pending = false;
+	_first_time = true;
+	_unbuffered_bytes = 0;
+	_total_bytes = 0;
+	_expected_bytes = 0;
+	_status_byte = 0;
+}
+
+void
+CoreMidiPort::clear_events ()
+{
+	CoreMidiBuffer* mbuf = static_cast<CoreMidiBuffer*>(get_buffer(0));
+	mbuf->clear();
+}
+
+void
+CoreMidiPort::parse_events (const uint64_t time, const uint8_t *data, const size_t size)
+{
+	CoreMidiBuffer* mbuf = static_cast<CoreMidiBuffer*>(get_buffer(0));
+
+	if (_event._pending) {
+		if (queue_event (mbuf, _event._time, _parser_buffer, _event._size)) {
+			return;
+		}
+	}
+
+	for (size_t i = 0; i < size; ++i) {
+		if (_first_time && !(data[i] & 0x80)) {
+			continue;
+		}
+
+		_first_time = false;
+
+		if (process_byte(time, data[i])) {
+			if (queue_event (mbuf, _event._time, _parser_buffer, _event._size)) {
+				return;
+			}
+		}
+	}
+}
+
+// based on JackMidiRawInputWriteQueue by Devin Anderson //
+bool
+CoreMidiPort::process_byte(const uint64_t time, const uint8_t byte)
+{
+	if (byte >= 0xf8) {
+		// Realtime
+		if (byte == 0xfd) {
+			return false;
+		}
+		_parser_buffer[0] = byte;
+		prepare_byte_event(time, byte);
+		return true;
+	}
+	if (byte == 0xf7) {
+		// Sysex end
+		if (_status_byte == 0xf0) {
+			record_byte(byte);
+			return prepare_buffered_event(time);
+		}
+		_total_bytes = 0;
+		_unbuffered_bytes = 0;
+		_expected_bytes = 0;
+		_status_byte = 0;
+		return false;
+	}
+	if (byte >= 0x80) {
+		// Non-realtime status byte
+		if (_total_bytes) {
+			printf ("CoreMidiPort: discarded bogus midi message\n");
+#if 0
+			for (size_t i=0; i < _total_bytes; ++i) {
+				printf("%02x ", _parser_buffer[i]);
+			}
+			printf("\n");
+#endif
+			_total_bytes = 0;
+			_unbuffered_bytes = 0;
+		}
+		_status_byte = byte;
+		switch (byte & 0xf0) {
+		case 0x80:
+		case 0x90:
+		case 0xa0:
+		case 0xb0:
+		case 0xe0:
+			// Note On, Note Off, Aftertouch, Control Change, Pitch Wheel
+			_expected_bytes = 3;
+			break;
+		case 0xc0:
+		case 0xd0:
+			// Program Change, Channel Pressure
+			_expected_bytes = 2;
+			break;
+		case 0xf0:
+			switch (byte) {
+			case 0xf0:
+				// Sysex
+				_expected_bytes = 0;
+				break;
+			case 0xf1:
+			case 0xf3:
+				// MTC Quarter Frame, Song Select
+				_expected_bytes = 2;
+				break;
+			case 0xf2:
+				// Song Position
+				_expected_bytes = 3;
+				break;
+			case 0xf4:
+			case 0xf5:
+				// Undefined
+				_expected_bytes = 0;
+				_status_byte = 0;
+				return false;
+			case 0xf6:
+				// Tune Request
+				prepare_byte_event(time, byte);
+				_expected_bytes = 0;
+				_status_byte = 0;
+				return true;
+			}
+		}
+		record_byte(byte);
+		return false;
+	}
+	// Data byte
+	if (! _status_byte) {
+		// Data bytes without a status will be discarded.
+		_total_bytes++;
+		_unbuffered_bytes++;
+		return false;
+	}
+	if (! _total_bytes) {
+		record_byte(_status_byte);
+	}
+	record_byte(byte);
+	return (_total_bytes == _expected_bytes) ? prepare_buffered_event(time) : false;
+}
+
+
 CoreMidiEvent::CoreMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
 	: _size (size)
 	, _timestamp (timestamp)
diff --git a/libs/backends/coreaudio/coreaudio_backend.h b/libs/backends/coreaudio/coreaudio_backend.h
index c4cbed9..e36e936 100644
--- a/libs/backends/coreaudio/coreaudio_backend.h
+++ b/libs/backends/coreaudio/coreaudio_backend.h
@@ -42,452 +42,478 @@ namespace ARDOUR {
 class CoreAudioBackend;
 
 class CoreMidiEvent {
-	public:
-		CoreMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size);
-		CoreMidiEvent (const CoreMidiEvent& other);
-		~CoreMidiEvent ();
-		size_t size () const { return _size; };
-		pframes_t timestamp () const { return _timestamp; };
-		const unsigned char* const_data () const { return _data; };
-		unsigned char* data () { return _data; };
-		bool operator< (const CoreMidiEvent &other) const { return timestamp () < other.timestamp (); };
-	private:
-		size_t _size;
-		pframes_t _timestamp;
-		uint8_t *_data;
+  public:
+	CoreMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size);
+	CoreMidiEvent (const CoreMidiEvent& other);
+	~CoreMidiEvent ();
+	size_t size () const { return _size; };
+	pframes_t timestamp () const { return _timestamp; };
+	const unsigned char* const_data () const { return _data; };
+	unsigned char* data () { return _data; };
+	bool operator< (const CoreMidiEvent &other) const { return timestamp () < other.timestamp (); };
+  private:
+	size_t _size;
+	pframes_t _timestamp;
+	uint8_t *_data;
 };
 
 typedef std::vector<boost::shared_ptr<CoreMidiEvent> > CoreMidiBuffer;
 
 class CoreBackendPort {
-	protected:
-		CoreBackendPort (CoreAudioBackend &b, const std::string&, PortFlags);
-	public:
-		virtual ~CoreBackendPort ();
+  protected:
+	CoreBackendPort (CoreAudioBackend &b, const std::string&, PortFlags);
+  public:
+	virtual ~CoreBackendPort ();
+
+	const std::string& name () const { return _name; }
+	const std::string& pretty_name () const { return _pretty_name; }
+	PortFlags flags () const { return _flags; }
 
-		const std::string& name () const { return _name; }
-		const std::string& pretty_name () const { return _pretty_name; }
-		PortFlags flags () const { return _flags; }
+	int set_name (const std::string &name) { _name = name; return 0; }
+	int set_pretty_name (const std::string &name) { _pretty_name = name; return 0; }
 
-		int set_name (const std::string &name) { _name = name; return 0; }
-		int set_pretty_name (const std::string &name) { _pretty_name = name; return 0; }
+	virtual DataType type () const = 0;
 
-		virtual DataType type () const = 0;
+	bool is_input ()     const { return flags () & IsInput; }
+	bool is_output ()    const { return flags () & IsOutput; }
+	bool is_physical ()  const { return flags () & IsPhysical; }
+	bool is_terminal ()  const { return flags () & IsTerminal; }
+	bool is_connected () const { return _connections.size () != 0; }
+	bool is_connected (const CoreBackendPort *port) const;
+	bool is_physically_connected () const;
 
-		bool is_input ()     const { return flags () & IsInput; }
-		bool is_output ()    const { return flags () & IsOutput; }
-		bool is_physical ()  const { return flags () & IsPhysical; }
-		bool is_terminal ()  const { return flags () & IsTerminal; }
-		bool is_connected () const { return _connections.size () != 0; }
-		bool is_connected (const CoreBackendPort *port) const;
-		bool is_physically_connected () const;
+	const std::vector<CoreBackendPort *>& get_connections () const { return _connections; }
 
-		const std::vector<CoreBackendPort *>& get_connections () const { return _connections; }
+	int connect (CoreBackendPort *port);
+	int disconnect (CoreBackendPort *port);
+	void disconnect_all ();
 
-		int connect (CoreBackendPort *port);
-		int disconnect (CoreBackendPort *port);
-		void disconnect_all ();
+	virtual void* get_buffer (pframes_t nframes) = 0;
 
-		virtual void* get_buffer (pframes_t nframes) = 0;
+	const LatencyRange latency_range (bool for_playback) const
+	{
+		return for_playback ? _playback_latency_range : _capture_latency_range;
+	}
 
-		const LatencyRange latency_range (bool for_playback) const
+	void set_latency_range (const LatencyRange &latency_range, bool for_playback)
+	{
+		if (for_playback)
 		{
-			return for_playback ? _playback_latency_range : _capture_latency_range;
+			_playback_latency_range = latency_range;
 		}
-
-		void set_latency_range (const LatencyRange &latency_range, bool for_playback)
+		else
 		{
-			if (for_playback)
-			{
-				_playback_latency_range = latency_range;
-			}
-			else
-			{
-				_capture_latency_range = latency_range;
-			}
+			_capture_latency_range = latency_range;
 		}
+	}
 
-	private:
-		CoreAudioBackend &_osx_backend;
-		std::string _name;
-		std::string _pretty_name;
-		const PortFlags _flags;
-		LatencyRange _capture_latency_range;
-		LatencyRange _playback_latency_range;
-		std::vector<CoreBackendPort*> _connections;
+  private:
+	CoreAudioBackend &_osx_backend;
+	std::string _name;
+	std::string _pretty_name;
+	const PortFlags _flags;
+	LatencyRange _capture_latency_range;
+	LatencyRange _playback_latency_range;
+	std::vector<CoreBackendPort*> _connections;
 
-		void _connect (CoreBackendPort* , bool);
-		void _disconnect (CoreBackendPort* , bool);
+	void _connect (CoreBackendPort* , bool);
+	void _disconnect (CoreBackendPort* , bool);
 
 }; // class CoreBackendPort
 
 class CoreAudioPort : public CoreBackendPort {
-	public:
-		CoreAudioPort (CoreAudioBackend &b, const std::string&, PortFlags);
-		~CoreAudioPort ();
+  public:
+	CoreAudioPort (CoreAudioBackend &b, const std::string&, PortFlags);
+	~CoreAudioPort ();
 
-		DataType type () const { return DataType::AUDIO; };
+	DataType type () const { return DataType::AUDIO; };
 
-		Sample* buffer () { return _buffer; }
-		const Sample* const_buffer () const { return _buffer; }
-		void* get_buffer (pframes_t nframes);
+	Sample* buffer () { return _buffer; }
+	const Sample* const_buffer () const { return _buffer; }
+	void* get_buffer (pframes_t nframes);
 
-	private:
-		Sample _buffer[8192];
+  private:
+	Sample _buffer[8192];
 }; // class CoreAudioPort
 
 class CoreMidiPort : public CoreBackendPort {
-	public:
-		CoreMidiPort (CoreAudioBackend &b, const std::string&, PortFlags);
-		~CoreMidiPort ();
+  public:
+	CoreMidiPort (CoreAudioBackend &b, const std::string&, PortFlags);
+	~CoreMidiPort ();
 
-		DataType type () const { return DataType::MIDI; };
+	DataType type () const { return DataType::MIDI; };
 
-		void* get_buffer (pframes_t nframes);
-		const CoreMidiBuffer * const_buffer () const { return & _buffer[_bufperiod]; }
+	void* get_buffer (pframes_t nframes);
+	const CoreMidiBuffer * const_buffer () const { return & _buffer[_bufperiod]; }
 
-		void next_period() { if (_n_periods > 1) { get_buffer(0); _bufperiod = (_bufperiod + 1) % _n_periods; } }
-		void set_n_periods(int n) { if (n > 0 && n < 3) { _n_periods = n; } }
+	void next_period() { if (_n_periods > 1) { get_buffer(0); _bufperiod = (_bufperiod + 1) % _n_periods; } }
+	void set_n_periods(int n) { if (n > 0 && n < 3) { _n_periods = n; } }
 
-	private:
-		CoreMidiBuffer _buffer[2];
-		int _n_periods;
-		int _bufperiod;
-}; // class CoreMidiPort
+	void parse_events (const uint64_t time, const uint8_t *data, const size_t size);
+	void clear_events ();
+	void reset_parser ();
 
-class CoreAudioBackend : public AudioBackend {
-	friend class CoreBackendPort;
-	public:
-		CoreAudioBackend (AudioEngine& e, AudioBackendInfo& info);
-		~CoreAudioBackend ();
-
-		/* AUDIOBACKEND API */
-
-		std::string name () const;
-		bool is_realtime () const;
-
-		bool use_separate_input_and_output_devices () const { return true; }
-		std::vector<DeviceStatus> enumerate_devices () const;
-		std::vector<DeviceStatus> enumerate_input_devices () const;
-		std::vector<DeviceStatus> enumerate_output_devices () const;
-
-		std::vector<float> available_sample_rates (const std::string& device) const;
-		std::vector<float> available_sample_rates2 (const std::string&, const std::string&) const;
-		std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
-		std::vector<uint32_t> available_buffer_sizes2 (const std::string&, const std::string&) const;
-		uint32_t available_input_channel_count (const std::string& device) const;
-		uint32_t available_output_channel_count (const std::string& device) const;
-
-		bool can_change_sample_rate_when_running () const;
-		bool can_change_buffer_size_when_running () const;
-
-		int set_device_name (const std::string&);
-		int set_input_device_name (const std::string&);
-		int set_output_device_name (const std::string&);
-		int set_sample_rate (float);
-		int set_buffer_size (uint32_t);
-		int set_interleaved (bool yn);
-		int set_input_channels (uint32_t);
-		int set_output_channels (uint32_t);
-		int set_systemic_input_latency (uint32_t);
-		int set_systemic_output_latency (uint32_t);
-		int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
-		int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
-
-		int reset_device () { return 0; };
-
-		/* Retrieving parameters */
-		std::string  device_name () const;
-		std::string  input_device_name () const;
-		std::string  output_device_name () const;
-		float        sample_rate () const;
-		uint32_t     buffer_size () const;
-		bool         interleaved () const;
-		uint32_t     input_channels () const;
-		uint32_t     output_channels () const;
-		uint32_t     systemic_input_latency () const;
-		uint32_t     systemic_output_latency () const;
-		uint32_t     systemic_midi_input_latency (std::string const) const { return 0; }
-		uint32_t     systemic_midi_output_latency (std::string const) const { return 0; }
-
-		bool can_set_systemic_midi_latencies () const { return false; /* XXX */}
-
-		/* External control app */
-		std::string control_app_name () const { return std::string ("Apple"); }
-		void launch_control_app ();
-
-		/* MIDI */
-		std::vector<std::string> enumerate_midi_options () const;
-		int set_midi_option (const std::string&);
-		std::string midi_option () const;
-
-		std::vector<DeviceStatus> enumerate_midi_devices () const {
-			return std::vector<AudioBackend::DeviceStatus> ();
+  private:
+	CoreMidiBuffer _buffer[2];
+	int _n_periods;
+	int _bufperiod;
+
+	int queue_event (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
+	bool process_byte (const uint64_t, const uint8_t);
+
+	void record_byte(uint8_t byte) {
+		if (_total_bytes < sizeof(_parser_buffer)) {
+			_parser_buffer[_total_bytes] = byte;
+		} else {
+			++_unbuffered_bytes;
 		}
-		int set_midi_device_enabled (std::string const, bool) {
-			return true;
+		++_total_bytes;
+	}
+
+	void prepare_byte_event(const uint64_t time, const uint8_t byte) {
+		_parser_buffer[0] = byte;
+		_event.prepare(time, 1);
+	}
+
+	bool prepare_buffered_event(const uint64_t time) {
+		const bool result = _unbuffered_bytes == 0;
+		if (result) {
+			_event.prepare(time, _total_bytes);
 		}
-		bool midi_device_enabled (std::string const) const {
-			return false;
+		_total_bytes = 0;
+		_unbuffered_bytes = 0;
+		if (_status_byte >= 0xf0) {
+			_expected_bytes = 0;
+			_status_byte = 0;
 		}
+		return result;
+	}
 
-		// really private, but needing static access:
-		int process_callback(uint32_t, uint64_t);
-		void error_callback();
-		void xrun_callback();
-		void buffer_size_callback();
-		void sample_rate_callback();
-		void hw_changed_callback();
-
-	protected:
-		/* State Control */
-		int _start (bool for_latency_measurement);
-	public:
-		int stop ();
-		int freewheel (bool);
-		float dsp_load () const;
-		size_t raw_buffer_size (DataType t);
-
-		/* Process time */
-		framepos_t sample_time ();
-		framepos_t sample_time_at_cycle_start ();
-		pframes_t samples_since_cycle_start ();
-
-		int create_process_thread (boost::function<void()> func);
-		int join_process_threads ();
-		bool in_process_thread ();
-		uint32_t process_thread_count ();
-
-		void update_latencies ();
-
-		/* PORTENGINE API */
-
-		void* private_handle () const;
-		const std::string& my_name () const;
-		bool available () const;
-		uint32_t port_name_size () const;
-
-		int         set_port_name (PortHandle, const std::string&);
-		std::string get_port_name (PortHandle) const;
-		PortHandle  get_port_by_name (const std::string&) const;
-		int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const;
-
-		int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
-
-		DataType port_data_type (PortHandle) const;
-
-		PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
-		void unregister_port (PortHandle);
-
-		int  connect (const std::string& src, const std::string& dst);
-		int  disconnect (const std::string& src, const std::string& dst);
-		int  connect (PortHandle, const std::string&);
-		int  disconnect (PortHandle, const std::string&);
-		int  disconnect_all (PortHandle);
-
-		bool connected (PortHandle, bool process_callback_safe);
-		bool connected_to (PortHandle, const std::string&, bool process_callback_safe);
-		bool physically_connected (PortHandle, bool process_callback_safe);
-		int  get_connections (PortHandle, std::vector<std::string>&, bool process_callback_safe);
-
-		/* MIDI */
-		int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
-		int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
-		uint32_t get_midi_event_count (void* port_buffer);
-		void     midi_clear (void* port_buffer);
-
-		/* Monitoring */
-
-		bool can_monitor_input () const;
-		int  request_input_monitoring (PortHandle, bool);
-		int  ensure_input_monitoring (PortHandle, bool);
-		bool monitoring_input (PortHandle);
-
-		/* Latency management */
-
-		void         set_latency_range (PortHandle, bool for_playback, LatencyRange);
-		LatencyRange get_latency_range (PortHandle, bool for_playback);
-
-		/* Discovering physical ports */
-
-		bool      port_is_physical (PortHandle) const;
-		void      get_physical_outputs (DataType type, std::vector<std::string>&);
-		void      get_physical_inputs (DataType type, std::vector<std::string>&);
-		ChanCount n_physical_outputs () const;
-		ChanCount n_physical_inputs () const;
-
-		/* Getting access to the data buffer for a port */
-
-		void* get_buffer (PortHandle, pframes_t);
-
-		void* freewheel_thread ();
-		void pre_process ();
-		void coremidi_rediscover ();
-
-	private:
-		std::string _instance_name;
-		CoreAudioPCM *_pcmio;
-		CoreMidiIo *_midiio;
-
-		bool  _run; /* keep going or stop, ardour thread */
-		bool  _active_ca; /* is running, process thread */
-		bool  _active_fw; /* is running, process thread */
-		bool  _preinit;
-		bool  _freewheeling;
-		bool  _freewheel;
-		bool  _freewheel_ack;
-		bool  _reinit_thread_callback;
-		bool  _measure_latency;
-
-		uint64_t _last_process_start;
-
-		pthread_mutex_t _process_callback_mutex;
-
-		pthread_mutex_t _freewheel_mutex;
-		pthread_cond_t  _freewheel_signal;
-
-		static std::vector<std::string> _midi_options;
-		static std::vector<AudioBackend::DeviceStatus> _input_audio_device_status;
-		static std::vector<AudioBackend::DeviceStatus> _output_audio_device_status;
-		static std::vector<AudioBackend::DeviceStatus> _duplex_audio_device_status;
-		static std::vector<AudioBackend::DeviceStatus> _midi_device_status;
+	struct ParserEvent {
+		uint64_t _time;
+		size_t _size;
+		bool _pending;
+		ParserEvent (const uint64_t time, const size_t size)
+			: _time(time)
+			, _size(size)
+			, _pending(false) {}
+
+		void prepare(const uint64_t time, const size_t size) {
+			_time = time;
+			_size = size;
+			_pending = true;
+		}
+	} _event;
 
-		mutable std::string _input_audio_device;
-		mutable std::string _output_audio_device;
-		std::string _midi_driver_option;
+	bool    _first_time;
+	size_t  _unbuffered_bytes;
+	size_t  _total_bytes;
+	size_t  _expected_bytes;
+	uint8_t _status_byte;
+	uint8_t _parser_buffer[1024];
 
-		/* audio settings */
-		float  _samplerate;
-		size_t _samples_per_period;
-		static size_t _max_buffer_size;
+}; // class CoreMidiPort
 
-		uint32_t _n_inputs;
-		uint32_t _n_outputs;
-
-		uint32_t _systemic_audio_input_latency;
-		uint32_t _systemic_audio_output_latency;
+class CoreAudioBackend : public AudioBackend {
+	friend class CoreBackendPort;
+  public:
+	CoreAudioBackend (AudioEngine& e, AudioBackendInfo& info);
+	~CoreAudioBackend ();
+
+	/* AUDIOBACKEND API */
+
+	std::string name () const;
+	bool is_realtime () const;
+
+	bool use_separate_input_and_output_devices () const { return true; }
+	std::vector<DeviceStatus> enumerate_devices () const;
+	std::vector<DeviceStatus> enumerate_input_devices () const;
+	std::vector<DeviceStatus> enumerate_output_devices () const;
+
+	std::vector<float> available_sample_rates (const std::string& device) const;
+	std::vector<float> available_sample_rates2 (const std::string&, const std::string&) const;
+	std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
+	std::vector<uint32_t> available_buffer_sizes2 (const std::string&, const std::string&) const;
+	uint32_t available_input_channel_count (const std::string& device) const;
+	uint32_t available_output_channel_count (const std::string& device) const;
+
+	bool can_change_sample_rate_when_running () const;
+	bool can_change_buffer_size_when_running () const;
+
+	int set_device_name (const std::string&);
+	int set_input_device_name (const std::string&);
+	int set_output_device_name (const std::string&);
+	int set_sample_rate (float);
+	int set_buffer_size (uint32_t);
+	int set_interleaved (bool yn);
+	int set_input_channels (uint32_t);
+	int set_output_channels (uint32_t);
+	int set_systemic_input_latency (uint32_t);
+	int set_systemic_output_latency (uint32_t);
+	int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
+	int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
+
+	int reset_device () { return 0; };
+
+	/* Retrieving parameters */
+	std::string  device_name () const;
+	std::string  input_device_name () const;
+	std::string  output_device_name () const;
+	float        sample_rate () const;
+	uint32_t     buffer_size () const;
+	bool         interleaved () const;
+	uint32_t     input_channels () const;
+	uint32_t     output_channels () const;
+	uint32_t     systemic_input_latency () const;
+	uint32_t     systemic_output_latency () const;
+	uint32_t     systemic_midi_input_latency (std::string const) const { return 0; }
+	uint32_t     systemic_midi_output_latency (std::string const) const { return 0; }
+
+	bool can_set_systemic_midi_latencies () const { return false; /* XXX */}
+
+	/* External control app */
+	std::string control_app_name () const { return std::string ("Apple"); }
+	void launch_control_app ();
+
+	/* MIDI */
+	std::vector<std::string> enumerate_midi_options () const;
+	int set_midi_option (const std::string&);
+	std::string midi_option () const;
+
+	std::vector<DeviceStatus> enumerate_midi_devices () const {
+		return std::vector<AudioBackend::DeviceStatus> ();
+	}
+	int set_midi_device_enabled (std::string const, bool) {
+		return true;
+	}
+	bool midi_device_enabled (std::string const) const {
+		return false;
+	}
+
+	// really private, but needing static access:
+	int process_callback(uint32_t, uint64_t);
+	void error_callback();
+	void xrun_callback();
+	void buffer_size_callback();
+	void sample_rate_callback();
+	void hw_changed_callback();
+
+  protected:
+	/* State Control */
+	int _start (bool for_latency_measurement);
+  public:
+	int stop ();
+	int freewheel (bool);
+	float dsp_load () const;
+	size_t raw_buffer_size (DataType t);
+
+	/* Process time */
+	framepos_t sample_time ();
+	framepos_t sample_time_at_cycle_start ();
+	pframes_t samples_since_cycle_start ();
+
+	int create_process_thread (boost::function<void()> func);
+	int join_process_threads ();
+	bool in_process_thread ();
+	uint32_t process_thread_count ();
+
+	void update_latencies ();
+
+	/* PORTENGINE API */
+
+	void* private_handle () const;
+	const std::string& my_name () const;
+	bool available () const;
+	uint32_t port_name_size () const;
+
+	int         set_port_name (PortHandle, const std::string&);
+	std::string get_port_name (PortHandle) const;
+	PortHandle  get_port_by_name (const std::string&) const;
+	int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const;
+
+	int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
+
+	DataType port_data_type (PortHandle) const;
+
+	PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
+	void unregister_port (PortHandle);
+
+	int  connect (const std::string& src, const std::string& dst);
+	int  disconnect (const std::string& src, const std::string& dst);
+	int  connect (PortHandle, const std::string&);
+	int  disconnect (PortHandle, const std::string&);
+	int  disconnect_all (PortHandle);
+
+	bool connected (PortHandle, bool process_callback_safe);
+	bool connected_to (PortHandle, const std::string&, bool process_callback_safe);
+	bool physically_connected (PortHandle, bool process_callback_safe);
+	int  get_connections (PortHandle, std::vector<std::string>&, bool process_callback_safe);
+
+	/* MIDI */
+	int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
+	int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size) {
+		return _midi_event_put (port_buffer, timestamp, buffer, size);
+	}
+
+	uint32_t get_midi_event_count (void* port_buffer);
+	void     midi_clear (void* port_buffer);
+
+	/* Monitoring */
+
+	bool can_monitor_input () const;
+	int  request_input_monitoring (PortHandle, bool);
+	int  ensure_input_monitoring (PortHandle, bool);
+	bool monitoring_input (PortHandle);
+
+	/* Latency management */
+
+	void         set_latency_range (PortHandle, bool for_playback, LatencyRange);
+	LatencyRange get_latency_range (PortHandle, bool for_playback);
+
+	/* Discovering physical ports */
+
+	bool      port_is_physical (PortHandle) const;
+	void      get_physical_outputs (DataType type, std::vector<std::string>&);
+	void      get_physical_inputs (DataType type, std::vector<std::string>&);
+	ChanCount n_physical_outputs () const;
+	ChanCount n_physical_inputs () const;
+
+	/* Getting access to the data buffer for a port */
+
+	void* get_buffer (PortHandle, pframes_t);
+
+	void* freewheel_thread ();
+	void pre_process ();
+	void coremidi_rediscover ();
+
+	static int _midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
+
+  private:
+	std::string _instance_name;
+	CoreAudioPCM *_pcmio;
+	CoreMidiIo *_midiio;
+
+	bool  _run; /* keep going or stop, ardour thread */
+	bool  _active_ca; /* is running, process thread */
+	bool  _active_fw; /* is running, process thread */
+	bool  _preinit;
+	bool  _freewheeling;
+	bool  _freewheel;
+	bool  _freewheel_ack;
+	bool  _reinit_thread_callback;
+	bool  _measure_latency;
+
+	uint64_t _last_process_start;
 
-		/* coreaudio specific  */
-		uint32_t name_to_id(std::string) const;
+	pthread_mutex_t _process_callback_mutex;
 
-		/* processing */
-		float  _dsp_load;
-		ARDOUR::DSPLoadCalculator  _dsp_load_calc;
-		uint64_t _processed_samples;
-
-		pthread_t _main_thread;
-		pthread_t _freeewheel_thread;
-
-		/* process threads */
-		static void* coreaudio_process_thread (void *);
-		std::vector<pthread_t> _threads;
-
-		struct ThreadData {
-			CoreAudioBackend* engine;
-			boost::function<void ()> f;
-			size_t stacksize;
-
-			ThreadData (CoreAudioBackend* e, boost::function<void ()> fp, size_t stacksz)
-				: engine (e) , f (fp) , stacksize (stacksz) {}
-		};
-
-		/* port engine */
-		PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
-		int register_system_audio_ports ();
-		void unregister_ports (bool system_only = false);
+	pthread_mutex_t _freewheel_mutex;
+	pthread_cond_t  _freewheel_signal;
 
-		std::vector<CoreBackendPort *> _ports;
-		std::vector<CoreBackendPort *> _system_inputs;
-		std::vector<CoreBackendPort *> _system_outputs;
-		std::vector<CoreBackendPort *> _system_midi_in;
-		std::vector<CoreBackendPort *> _system_midi_out;
+	static std::vector<std::string> _midi_options;
+	static std::vector<AudioBackend::DeviceStatus> _input_audio_device_status;
+	static std::vector<AudioBackend::DeviceStatus> _output_audio_device_status;
+	static std::vector<AudioBackend::DeviceStatus> _duplex_audio_device_status;
+	static std::vector<AudioBackend::DeviceStatus> _midi_device_status;
 
-		struct PortConnectData {
-			std::string a;
-			std::string b;
-			bool c;
-
-			PortConnectData (const std::string& a, const std::string& b, bool c)
-				: a (a) , b (b) , c (c) {}
-		};
-
-		std::vector<PortConnectData *> _port_connection_queue;
-		pthread_mutex_t _port_callback_mutex;
-		bool _port_change_flag;
-
-		void port_connect_callback (const std::string& a, const std::string& b, bool conn) {
-			pthread_mutex_lock (&_port_callback_mutex);
-			_port_connection_queue.push_back(new PortConnectData(a, b, conn));
-			pthread_mutex_unlock (&_port_callback_mutex);
-		}
+	mutable std::string _input_audio_device;
+	mutable std::string _output_audio_device;
+	std::string _midi_driver_option;
+
+	/* audio settings */
+	float  _samplerate;
+	size_t _samples_per_period;
+	static size_t _max_buffer_size;
 
-		void port_connect_add_remove_callback () {
-			pthread_mutex_lock (&_port_callback_mutex);
-			_port_change_flag = true;
-			pthread_mutex_unlock (&_port_callback_mutex);
-		}
+	uint32_t _n_inputs;
+	uint32_t _n_outputs;
+
+	uint32_t _systemic_audio_input_latency;
+	uint32_t _systemic_audio_output_latency;
 
-		bool valid_port (PortHandle port) const {
-			return std::find (_ports.begin (), _ports.end (), (CoreBackendPort*)port) != _ports.end ();
-		}
+	/* coreaudio specific  */
+	uint32_t name_to_id(std::string) const;
+
+	/* processing */
+	float  _dsp_load;
+	ARDOUR::DSPLoadCalculator  _dsp_load_calc;
+	uint64_t _processed_samples;
+
+	pthread_t _main_thread;
+	pthread_t _freeewheel_thread;
+
+	/* process threads */
+	static void* coreaudio_process_thread (void *);
+	std::vector<pthread_t> _threads;
+
+	struct ThreadData {
+		CoreAudioBackend* engine;
+		boost::function<void ()> f;
+		size_t stacksize;
+
+		ThreadData (CoreAudioBackend* e, boost::function<void ()> fp, size_t stacksz)
+			: engine (e) , f (fp) , stacksize (stacksz) {}
+	};
 
-		CoreBackendPort * find_port (const std::string& port_name) const {
-			for (std::vector<CoreBackendPort*>::const_iterator it = _ports.begin (); it != _ports.end (); ++it) {
-				if ((*it)->name () == port_name) {
-					return *it;
-				}
+	/* port engine */
+	PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
+	int register_system_audio_ports ();
+	void unregister_ports (bool system_only = false);
+
+	std::vector<CoreBackendPort *> _ports;
+	std::vector<CoreBackendPort *> _system_inputs;
+	std::vector<CoreBackendPort *> _system_outputs;
+	std::vector<CoreBackendPort *> _system_midi_in;
+	std::vector<CoreBackendPort *> _system_midi_out;
+
+	struct PortConnectData {
+		std::string a;
+		std::string b;
+		bool c;
+
+		PortConnectData (const std::string& a, const std::string& b, bool c)
+			: a (a) , b (b) , c (c) {}
+	};
+
+	std::vector<PortConnectData *> _port_connection_queue;
+	pthread_mutex_t _port_callback_mutex;
+	bool _port_change_flag;
+
+	void port_connect_callback (const std::string& a, const std::string& b, bool conn) {
+		pthread_mutex_lock (&_port_callback_mutex);
+		_port_connection_queue.push_back(new PortConnectData(a, b, conn));
+		pthread_mutex_unlock (&_port_callback_mutex);
+	}
+
+	void port_connect_add_remove_callback () {
+		pthread_mutex_lock (&_port_callback_mutex);
+		_port_change_flag = true;
+		pthread_mutex_unlock (&_port_callback_mutex);
+	}
+
+	bool valid_port (PortHandle port) const {
+		return std::find (_ports.begin (), _ports.end (), (CoreBackendPort*)port) != _ports.end ();
+	}
+
+	CoreBackendPort * find_port (const std::string& port_name) const {
+		for (std::vector<CoreBackendPort*>::const_iterator it = _ports.begin (); it != _ports.end (); ++it) {
+			if ((*it)->name () == port_name) {
+				return *it;
 			}
-			return NULL;
 		}
+		return NULL;
+	}
 
-		CoreBackendPort * find_port_in (std::vector<CoreBackendPort *> plist, const std::string& port_name) const {
-			for (std::vector<CoreBackendPort*>::const_iterator it = plist.begin (); it != plist.end (); ++it) {
-				if ((*it)->name () == port_name) {
-					return *it;
-				}
-			}
-			return NULL;
-		}
-
-#ifdef USE_MIDI_PARSER
-
-		bool midi_process_byte (const uint8_t);
-
-		void midi_record_byte (uint8_t byte) {
-			if (_total_bytes < sizeof (_parser_buffer)) {
-				_parser_buffer[_total_bytes] = byte;
-			} else {
-				++_unbuffered_bytes;
-			}
-			++_total_bytes;
-		}
-
-		void midi_prepare_byte_event (const uint8_t byte) {
-			_parser_buffer[0] = byte;
-			_parser_bytes = 1;
-		}
-
-		bool midi_prepare_buffered_event () {
-			const bool result = _unbuffered_bytes == 0;
-			if (result) {
-				_parser_bytes = _total_bytes;
-			}
-			_total_bytes = 0;
-			_unbuffered_bytes = 0;
-			if (_status_byte >= 0xf0) {
-				_expected_bytes = 0;
-				_status_byte = 0;
+	CoreBackendPort * find_port_in (std::vector<CoreBackendPort *> plist, const std::string& port_name) const {
+		for (std::vector<CoreBackendPort*>::const_iterator it = plist.begin (); it != plist.end (); ++it) {
+			if ((*it)->name () == port_name) {
+				return *it;
 			}
-			return result;
 		}
+		return NULL;
+	}
 
-		size_t  _unbuffered_bytes;
-		size_t  _total_bytes;
-		size_t  _expected_bytes;
-		uint8_t _status_byte;
-		uint8_t _parser_buffer[128];
-		uint8_t _parser_bytes;
-#endif
+	void reset_midi_parsers ();
 
 }; // class CoreAudioBackend
 
diff --git a/libs/backends/coreaudio/coremidi_io.cc b/libs/backends/coreaudio/coremidi_io.cc
index a64fade..caf8010 100644
--- a/libs/backends/coreaudio/coremidi_io.cc
+++ b/libs/backends/coreaudio/coremidi_io.cc
@@ -28,6 +28,26 @@ using namespace ARDOUR;
 static int _debug_mode = 0;
 #endif
 
+
+/** 
+ * MIDI Data flow
+ * 
+ * (A) INPUT (incoming from outside the application)
+ * 
+ *    - midiInputCallback (in its own thread, async WRT process callback):
+ *       takes OS X MIDIPacket, copies into lock-free ringbuffer
+ *
+ *    - processCallback (in its own thread):
+ *
+ *   (1) loop on all input ports:
+ *       1A) call recv_event() to read from ringbuffer into stack buffer, also assign-timestamp, 
+ *       1B) call parse_events() using stack buffer, when appropriate
+ *          pushes CoreMidiEvent into std::vector<CoreMidiEvent>
+ *
+ *   (2) in MidiPort::cycle_start() (also part of the process callback call tree), MidiPort::get_midi_buffer()
+ *       calls CoreAudioBackend::midi_event_get () returns a pointer to the  data of the specified CoreMidiEvent
+ */
+
 static void notifyProc (const MIDINotification *message, void *refCon) {
 	CoreMidiIo *self = static_cast<CoreMidiIo*>(refCon);
 	self->notify_proc(message);
diff --git a/libs/backends/dummy/dummy_audiobackend.cc b/libs/backends/dummy/dummy_audiobackend.cc
index a59d7e3..130a92d 100644
--- a/libs/backends/dummy/dummy_audiobackend.cc
+++ b/libs/backends/dummy/dummy_audiobackend.cc
@@ -1028,9 +1028,16 @@ DummyAudioBackend::midi_event_put (
 	DummyMidiBuffer& dst = * static_cast<DummyMidiBuffer*>(port_buffer);
 	if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) {
 		// nevermind, ::get_buffer() sorts events, but always print warning
-		fprintf (stderr, "DummyMidiBuffer: it's too late for this event.\n");
+		fprintf (stderr, "DummyMidiBuffer: it's too late for this event %d > %d.\n", (pframes_t)dst.back ()->timestamp (), timestamp);
 	}
 	dst.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (timestamp, buffer, size)));
+#if 0 // DEBUG MIDI EVENTS
+	printf("DummyAudioBackend::midi_event_put %d, %zu: ", timestamp, size);
+	for (size_t xx = 0; xx < size; ++xx) {
+		printf(" %02x", buffer[xx]);
+	}
+	printf("\n");
+#endif
 	return 0;
 }
 
@@ -1525,6 +1532,7 @@ void DummyPort::setup_random_number_generator ()
 	_rseed = g_get_monotonic_time() % UINT_MAX;
 	}
 	_rseed = (_rseed + (uint64_t)this) % UINT_MAX;
+	if (_rseed == 0) _rseed = 1;
 }
 
 inline uint32_t
diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc
index 944fa41..32c9f20 100644
--- a/libs/backends/jack/jack_audiobackend.cc
+++ b/libs/backends/jack/jack_audiobackend.cc
@@ -54,6 +54,7 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, AudioBackendInfo& info, boos
 	, _freewheeling (false)
 	, _target_sample_rate (48000)
 	, _target_buffer_size (1024)
+	, _target_num_periods (2)
 	, _target_interleaved (false)
 	, _target_input_channels (0)
 	, _target_output_channels (0)
@@ -203,6 +204,17 @@ JACKAudioBackend::available_buffer_sizes (const string& device) const
 	return s;
 }
 
+std::vector<uint32_t>
+JACKAudioBackend::available_period_sizes (const std::string& driver) const
+{
+	vector<uint32_t> s;
+	if (ARDOUR::get_jack_audio_driver_supports_setting_period_count (driver)) {
+		s.push_back (2);
+		s.push_back (3);
+	}
+	return s;
+}
+
 uint32_t
 JACKAudioBackend::available_input_channel_count (const string& /*device*/) const
 {
@@ -247,6 +259,16 @@ JACKAudioBackend::set_sample_rate (float sr)
 }
 
 int
+JACKAudioBackend::set_peridod_size (uint32_t nperiods)
+{
+	if (!available()) {
+		_target_num_periods = nperiods;
+		return 0;
+	}
+	return -1;
+}
+
+int
 JACKAudioBackend::set_buffer_size (uint32_t nframes)
 {
 	if (!available()) {
@@ -381,6 +403,12 @@ JACKAudioBackend::buffer_size () const
 	return _target_buffer_size;
 }
 
+uint32_t
+JACKAudioBackend::period_size () const
+{
+	return _target_num_periods;
+}
+
 bool
 JACKAudioBackend::interleaved () const
 {
@@ -461,7 +489,7 @@ JACKAudioBackend::setup_jack_startup_command (bool for_latency_measurement)
 	options.driver = _target_driver;
 	options.samplerate = _target_sample_rate;
 	options.period_size = _target_buffer_size;
-	options.num_periods = 2;
+	options.num_periods = _target_num_periods;
 	options.input_device = _target_device;
 	options.output_device = _target_device;
 	if (for_latency_measurement) {
diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h
index 530e3fd..54eea35 100644
--- a/libs/backends/jack/jack_audiobackend.h
+++ b/libs/backends/jack/jack_audiobackend.h
@@ -58,6 +58,7 @@ class JACKAudioBackend : public AudioBackend {
 
     std::vector<float> available_sample_rates (const std::string& device) const;
     std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
+    std::vector<uint32_t> available_period_sizes (const std::string& driver) const;
     uint32_t available_input_channel_count (const std::string& device) const;
     uint32_t available_output_channel_count (const std::string& device) const;
 
@@ -67,6 +68,7 @@ class JACKAudioBackend : public AudioBackend {
     int set_device_name (const std::string&);
     int set_sample_rate (float);
     int set_buffer_size (uint32_t);
+    int set_peridod_size (uint32_t);
     int set_interleaved (bool yn);
     int set_input_channels (uint32_t);
     int set_output_channels (uint32_t);
@@ -80,6 +82,7 @@ class JACKAudioBackend : public AudioBackend {
     std::string  device_name () const;
     float        sample_rate () const;
     uint32_t     buffer_size () const;
+    uint32_t     period_size () const;
     bool         interleaved () const;
     uint32_t     input_channels () const;
     uint32_t     output_channels () const;
@@ -167,6 +170,9 @@ class JACKAudioBackend : public AudioBackend {
     bool can_set_systemic_midi_latencies () const {
 	return false;
     }
+    bool can_set_period_size () const {
+	return true;
+    }
 
     int      midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
     int      midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
@@ -253,6 +259,7 @@ class JACKAudioBackend : public AudioBackend {
     std::string  _target_device;
     float        _target_sample_rate;
     uint32_t     _target_buffer_size;
+    uint32_t     _target_num_periods;
     SampleFormat _target_sample_format;
     bool         _target_interleaved;
     uint32_t     _target_input_channels;
diff --git a/libs/backends/jack/weak_libjack.h b/libs/backends/jack/weak_libjack.h
index 0f98de3..88365de 100644
--- a/libs/backends/jack/weak_libjack.h
+++ b/libs/backends/jack/weak_libjack.h
@@ -194,8 +194,14 @@ int have_libjack(void);
 #include <jack/metadata.h>
 #endif
 
-// prototype for function currently only available in jack1 headers
-int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port_name);
+// prototype for function which is not available in older jack headers
+#ifdef __cplusplus
+extern "C" {
+#endif
+        int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port_name);
+#ifdef __cplusplus
+}
+#endif
 
 #ifdef USE_WEAK_JACK
 
diff --git a/libs/backends/jack/wscript b/libs/backends/jack/wscript
index b2a12b5..17b4d16 100644
--- a/libs/backends/jack/wscript
+++ b/libs/backends/jack/wscript
@@ -49,7 +49,8 @@ def configure(conf):
                    uselib = 'JACK')
 
     # Check to see if jack_port_rename() is available and working
-    conf.check_cxx(fragment = "#include <jack/jack.h>\nint main(void) { jack_client_t* c; jack_port_t* p; jack_port_rename (c, p, \"foo\"); return 0; }\n",
+    if Options.options.libjack_link == 'link':
+            conf.check_cxx(fragment = "#include <jack/jack.h>\nint main(void) { jack_client_t* c; jack_port_t* p; jack_port_rename (c, p, \"foo\"); return 0; }\n",
                    mandatory = False,
                    execute = False,
                    features = ['cxx'],
@@ -61,7 +62,7 @@ def configure(conf):
 
 def build(bld):
     obj = bld(features = 'c cxx cxxshlib')
-    obj.source = [ 
+    obj.source = [
             'jack_api.cc',
             'jack_connection.cc',
             'jack_audiobackend.cc',
@@ -73,7 +74,7 @@ def build(bld):
     obj.includes = ['.']
     obj.name     = 'jack_audiobackend'
     obj.target   = 'jack_audiobackend'
-    obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"', 
+    obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"',
                    'ARDOURBACKEND_DLL_EXPORTS'
                    ]
     obj.use      = 'libardour libpbd ardouralsautil'
@@ -100,14 +101,17 @@ def build(bld):
 
     if bld.env['libjack_link'] == 'link':
         obj.uselib   += [ 'JACK' ]
-    else:
+    elif bld.env['build_target'] == 'mingw':
         obj.defines += [ 'USE_WEAK_JACK' ]
         obj.deps = [ 'weak_libjack.def' ]
+    else:
+        obj.defines += [ 'USE_WEAK_JACK', 'HAVE_JACK_PORT_RENAME' ]
+        obj.deps = [ 'weak_libjack.def' ]
 
     #
     # device discovery code in the jack backend needs ALSA
     # on Linux.
-    # 
+    #
 
     if re.search ("linux", sys.platform) != None:
        obj.uselib += [ 'ALSA' ]
diff --git a/libs/backends/portaudio/portaudio_backend.cc b/libs/backends/portaudio/portaudio_backend.cc
index 3329dee..4f74992 100644
--- a/libs/backends/portaudio/portaudio_backend.cc
+++ b/libs/backends/portaudio/portaudio_backend.cc
@@ -24,6 +24,10 @@
 #include <sys/time.h>
 #endif
 
+#ifdef COMPILER_MINGW
+#include <sys/time.h>
+#endif
+
 #include <glibmm.h>
 
 #include "portaudio_backend.h"
@@ -63,10 +67,13 @@ PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
 	, _run (false)
 	, _active (false)
 	, _freewheel (false)
+	, _freewheeling (false)
+	, _freewheel_ack (false)
+	, _reinit_thread_callback (false)
 	, _measure_latency (false)
-	, m_cycle_count(0)
-	, m_total_deviation_us(0)
-	, m_max_deviation_us(0)
+	, _cycle_count(0)
+	, _total_deviation_us(0)
+	, _max_deviation_us(0)
 	, _input_audio_device("")
 	, _output_audio_device("")
 	, _midi_driver_option(get_standard_device_name(DeviceNone))
@@ -82,6 +89,8 @@ PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
 {
 	_instance_name = s_instance_name;
 	pthread_mutex_init (&_port_callback_mutex, 0);
+	pthread_mutex_init (&_freewheel_mutex, 0);
+	pthread_cond_init (&_freewheel_signal, 0);
 
 	_pcmio = new PortAudioIO ();
 	_midiio = new WinMMEMidiIO ();
@@ -93,6 +102,8 @@ PortAudioBackend::~PortAudioBackend ()
 	delete _midiio; _midiio = 0;
 
 	pthread_mutex_destroy (&_port_callback_mutex);
+	pthread_mutex_destroy (&_freewheel_mutex);
+	pthread_cond_destroy (&_freewheel_signal);
 }
 
 /* AUDIOBACKEND API */
@@ -422,10 +433,10 @@ PortAudioBackend::midi_option () const
 
 /* State Control */
 
-static void * pthread_process (void *arg)
+static void * blocking_thread_func (void *arg)
 {
 	PortAudioBackend *d = static_cast<PortAudioBackend *>(arg);
-	d->main_blocking_process_thread ();
+	d->blocking_process_thread ();
 	pthread_exit (0);
 	return 0;
 }
@@ -471,11 +482,22 @@ PortAudioBackend::_start (bool for_latency_measurement)
 
 	PaErrorCode err = paNoError;
 
+#ifdef USE_BLOCKING_API
 	err = _pcmio->open_blocking_stream(name_to_id(_input_audio_device),
 	                                   name_to_id(_output_audio_device),
 	                                   _samplerate,
 	                                   _samples_per_period);
 
+#else
+	err = _pcmio->open_callback_stream(name_to_id(_input_audio_device),
+	                                   name_to_id(_output_audio_device),
+	                                   _samplerate,
+	                                   _samples_per_period,
+	                                   portaudio_callback,
+	                                   this);
+
+#endif
+
 	// reintepret Portaudio error messages
 	switch (err) {
 	case paNoError:
@@ -523,10 +545,10 @@ PortAudioBackend::_start (bool for_latency_measurement)
 		_midiio->start(); // triggers port discovery, callback coremidi_rediscover()
 	}
 
-	m_cycle_timer.set_samplerate(_samplerate);
-	m_cycle_timer.set_samples_per_cycle(_samples_per_period);
+	_cycle_timer.set_samplerate(_samplerate);
+	_cycle_timer.set_samples_per_cycle(_samples_per_period);
 
-	m_dsp_calc.set_max_time_us (m_cycle_timer.get_length_us());
+	_dsp_calc.set_max_time_us (_cycle_timer.get_length_us());
 
 	DEBUG_MIDI ("Registering MIDI ports\n");
 
@@ -557,20 +579,104 @@ PortAudioBackend::_start (bool for_latency_measurement)
 	_run = true;
 	_port_change_flag = false;
 
+#ifdef USE_BLOCKING_API
 	if (!start_blocking_process_thread()) {
 		return ProcessThreadStartError;
 	}
+#else
+	if (_pcmio->start_stream() != paNoError) {
+		DEBUG_AUDIO("Unable to start stream\n");
+		return AudioDeviceOpenError;
+	}
+
+	if (!start_freewheel_process_thread()) {
+		DEBUG_AUDIO("Unable to start freewheel thread\n");
+		stop();
+		return ProcessThreadStartError;
+	}
+#endif
 
 	return NoError;
 }
 
+int
+PortAudioBackend::portaudio_callback(const void* input,
+                                     void* output,
+                                     unsigned long frame_count,
+                                     const PaStreamCallbackTimeInfo* time_info,
+                                     PaStreamCallbackFlags status_flags,
+                                     void* user_data)
+{
+	PortAudioBackend* pa_backend = static_cast<PortAudioBackend*>(user_data);
+
+	if (!pa_backend->process_callback((const float*)input,
+	                                  (float*)output,
+	                                  frame_count,
+	                                  time_info,
+	                                  status_flags)) {
+		return paAbort;
+	}
+
+	return paContinue;
+}
+
+bool
+PortAudioBackend::process_callback(const float* input,
+                                   float* output,
+                                   uint32_t frame_count,
+                                   const PaStreamCallbackTimeInfo* timeInfo,
+                                   PaStreamCallbackFlags statusFlags)
+{
+	_active = true;
+
+	_dsp_calc.set_start_timestamp_us (PBD::get_microseconds());
+
+	if (_run && _freewheel && !_freewheel_ack) {
+		// acknowledge freewheeling; hand-over thread ID
+		pthread_mutex_lock (&_freewheel_mutex);
+		if (_freewheel) {
+			DEBUG_AUDIO("Setting _freewheel_ack = true;\n");
+			_freewheel_ack = true;
+		}
+		DEBUG_AUDIO("Signalling freewheel thread\n");
+		pthread_cond_signal (&_freewheel_signal);
+		pthread_mutex_unlock (&_freewheel_mutex);
+	}
+
+	if (statusFlags & paInputUnderflow ||
+		statusFlags & paInputOverflow ||
+		statusFlags & paOutputUnderflow ||
+		statusFlags & paOutputOverflow ) {
+		DEBUG_AUDIO("PortAudio: Xrun\n");
+		engine.Xrun();
+		return true;
+	}
+
+	if (!_run || _freewheel) {
+		memset(output, 0, frame_count * sizeof(float) * _system_outputs.size());
+		return true;
+	}
+
+	bool in_main_thread = pthread_equal(_main_thread, pthread_self());
+
+	if (_reinit_thread_callback || !in_main_thread) {
+		_reinit_thread_callback = false;
+		_main_thread = pthread_self();
+		AudioEngine::thread_init_callback (this);
+	}
+
+	process_port_connection_changes();
+
+	return blocking_process_main (input, output);
+}
+
 bool
 PortAudioBackend::start_blocking_process_thread ()
 {
 	if (_realtime_pthread_create (SCHED_FIFO, -20, 100000,
-				&_main_blocking_thread, pthread_process, this))
+				&_main_blocking_thread, blocking_thread_func, this))
 	{
-		if (pthread_create (&_main_blocking_thread, NULL, pthread_process, this))
+		if (pthread_create (&_main_blocking_thread, NULL, blocking_thread_func, this))
 		{
 			DEBUG_AUDIO("Failed to create main audio thread\n");
 			_run = false;
@@ -618,15 +724,138 @@ PortAudioBackend::stop ()
 
 	_run = false;
 
+#ifdef USE_BLOCKING_API
 	if (!stop_blocking_process_thread ()) {
 		return -1;
 	}
+#else
+	_pcmio->close_stream ();
+	_active = false;
+
+	if (!stop_freewheel_process_thread ()) {
+		return -1;
+	}
+
+#endif
 
 	unregister_ports();
 
 	return (_active == false) ? 0 : -1;
 }
 
+static void* freewheel_thread(void* arg)
+{
+	PortAudioBackend* d = static_cast<PortAudioBackend*>(arg);
+	d->freewheel_process_thread ();
+	pthread_exit (0);
+	return 0;
+}
+
+bool
+PortAudioBackend::start_freewheel_process_thread ()
+{
+	if (pthread_create(&_pthread_freewheel, NULL, freewheel_thread, this)) {
+		DEBUG_AUDIO("Failed to create main audio thread\n");
+		return false;
+	}
+
+	int timeout = 5000;
+	while (!_freewheel_thread_active && --timeout > 0) { Glib::usleep (1000); }
+
+	if (timeout == 0 || !_freewheel_thread_active) {
+		DEBUG_AUDIO("Failed to start freewheel thread\n");
+		return false;
+	}
+	return true;
+}
+
+bool
+PortAudioBackend::stop_freewheel_process_thread ()
+{
+	void *status;
+
+	if (!_freewheel_thread_active) {
+		return true;
+	}
+
+	DEBUG_AUDIO("Signaling freewheel thread to stop\n");
+
+	pthread_mutex_lock (&_freewheel_mutex);
+	pthread_cond_signal (&_freewheel_signal);
+	pthread_mutex_unlock (&_freewheel_mutex);
+
+	if (pthread_join (_pthread_freewheel, &status) != 0) {
+		DEBUG_AUDIO("Failed to stop freewheel thread\n");
+		return false;
+	}
+
+	return true;
+}
+
+void*
+PortAudioBackend::freewheel_process_thread()
+{
+	_freewheel_thread_active = true;
+
+	bool first_run = false;
+
+	pthread_mutex_lock (&_freewheel_mutex);
+
+	while(_run) {
+		// check if we should run,
+		if (_freewheeling != _freewheel) {
+			if (!_freewheeling) {
+				DEBUG_AUDIO("Leaving freewheel\n");
+				_freewheel = false; // first mark as disabled
+				_reinit_thread_callback = true; // hand over _main_thread
+				_freewheel_ack = false; // prepare next handshake
+				_midiio->set_enabled(true);
+			} else {
+				first_run = true;
+				_freewheel = true;
+			}
+		}
+
+		if (!_freewheel || !_freewheel_ack) {
+			// wait for a change, we use a timed wait to
+			// terminate early in case some error sets _run = 0
+			struct timeval tv;
+			struct timespec ts;
+			gettimeofday (&tv, NULL);
+			ts.tv_sec = tv.tv_sec + 3;
+			ts.tv_nsec = 0;
+			DEBUG_AUDIO("Waiting for freewheel change\n");
+			pthread_cond_timedwait (&_freewheel_signal, &_freewheel_mutex, &ts);
+			continue;
+		}
+
+		if (first_run) {
+			// tell the engine we're ready to GO.
+			engine.freewheel_callback (_freewheeling);
+			first_run = false;
+			_main_thread = pthread_self();
+			AudioEngine::thread_init_callback (this);
+			_midiio->set_enabled(false);
+		}
+
+		if (!blocking_process_freewheel()) {
+			break;
+		}
+
+		process_port_connection_changes();
+	}
+
+	pthread_mutex_unlock (&_freewheel_mutex);
+
+	_freewheel_thread_active = false;
+
+	if (_run) {
+		// engine.process_callback() returner error
+		engine.halted_callback("CoreAudio Freehweeling aborted.");
+	}
+	return 0;
+}
+
 int
 PortAudioBackend::freewheel (bool onoff)
 {
@@ -634,6 +863,11 @@ PortAudioBackend::freewheel (bool onoff)
 		return 0;
 	}
 	_freewheeling = onoff;
+
+	if (0 == pthread_mutex_trylock (&_freewheel_mutex)) {
+		pthread_cond_signal (&_freewheel_signal);
+		pthread_mutex_unlock (&_freewheel_mutex);
+	}
 	return 0;
 }
 
@@ -674,11 +908,11 @@ PortAudioBackend::samples_since_cycle_start ()
 	if (!_active || !_run || _freewheeling || _freewheel) {
 		return 0;
 	}
-	if (!m_cycle_timer.valid()) {
+	if (!_cycle_timer.valid()) {
 		return 0;
 	}
 
-	return m_cycle_timer.samples_since_cycle_start (PBD::get_microseconds());
+	return _cycle_timer.samples_since_cycle_start (PBD::get_microseconds());
 }
 
 int
@@ -803,9 +1037,15 @@ PortAudioBackend::join_process_threads ()
 bool
 PortAudioBackend::in_process_thread ()
 {
+#ifdef USE_BLOCKING_API
 	if (pthread_equal (_main_blocking_thread, pthread_self()) != 0) {
 		return true;
 	}
+#else
+	if (pthread_equal (_main_thread, pthread_self()) != 0) {
+		return true;
+	}
+#endif
 
 	for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
 	{
@@ -1007,12 +1247,19 @@ PortAudioBackend::register_system_audio_ports()
 	const uint32_t a_ins = _n_inputs;
 	const uint32_t a_out = _n_outputs;
 
-	// XXX PA reported stream latencies don't match measurements
-	const uint32_t portaudio_reported_input_latency =  _samples_per_period ; //  _pcmio->capture_latency();
-	const uint32_t portaudio_reported_output_latency = /* _samples_per_period + */ _pcmio->playback_latency();
+	uint32_t capture_latency = 0;
+	uint32_t playback_latency = 0;
+
+	// guard against erroneous latency values
+	if (_pcmio->capture_latency() > _samples_per_period) {
+		capture_latency = _pcmio->capture_latency() - _samples_per_period;
+	}
+	if (_pcmio->playback_latency() > _samples_per_period) {
+		playback_latency = _pcmio->playback_latency() - _samples_per_period;
+	}
 
 	/* audio ports */
-	lr.min = lr.max = portaudio_reported_input_latency + (_measure_latency ? 0 : _systemic_audio_input_latency);
+	lr.min = lr.max = capture_latency + (_measure_latency ? 0 : _systemic_audio_input_latency);
 	for (uint32_t i = 0; i < a_ins; ++i) {
 		char tmp[64];
 		snprintf(tmp, sizeof(tmp), "system:capture_%d", i+1);
@@ -1025,7 +1272,7 @@ PortAudioBackend::register_system_audio_ports()
 		_system_inputs.push_back (audio_port);
 	}
 
-	lr.min = lr.max = portaudio_reported_output_latency + (_measure_latency ? 0 : _systemic_audio_output_latency);
+	lr.min = lr.max = playback_latency + (_measure_latency ? 0 : _systemic_audio_output_latency);
 	for (uint32_t i = 0; i < a_out; ++i) {
 		char tmp[64];
 		snprintf(tmp, sizeof(tmp), "system:playback_%d", i+1);
@@ -1056,7 +1303,7 @@ PortAudioBackend::register_system_midi_ports()
 	for (std::vector<WinMMEMidiInputDevice*>::const_iterator i = inputs.begin ();
 	     i != inputs.end ();
 	     ++i) {
-		std::string port_name = "system_midi:" + (*i)->name() + " capture";
+		std::string port_name = "system:midi_capture_" + (*i)->name();
 		PortHandle p =
 		    add_port (port_name,
 		              DataType::MIDI,
@@ -1074,7 +1321,7 @@ PortAudioBackend::register_system_midi_ports()
 	for (std::vector<WinMMEMidiOutputDevice*>::const_iterator i = outputs.begin ();
 	     i != outputs.end ();
 	     ++i) {
-		std::string port_name = "system_midi:" + (*i)->name() + " playback";
+		std::string port_name = "system:midi_playback_" + (*i)->name();
 		PortHandle p =
 		    add_port (port_name,
 		              DataType::MIDI,
@@ -1443,7 +1690,7 @@ PortAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes)
 
 
 void *
-PortAudioBackend::main_blocking_process_thread ()
+PortAudioBackend::blocking_process_thread ()
 {
 	AudioEngine::thread_init_callback (this);
 	_active = true;
@@ -1523,7 +1770,7 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data,
 	int64_t min_elapsed_us = 1000000;
 	int64_t max_elapsed_us = 0;
 
-	m_dsp_calc.set_start_timestamp_us (PBD::get_microseconds());
+	_dsp_calc.set_start_timestamp_us (PBD::get_microseconds());
 
 	i = 0;
 	/* Copy input audio data into input port buffers */
@@ -1548,28 +1795,28 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data,
 		       _samples_per_period * sizeof(Sample));
 	}
 
-	m_last_cycle_start = m_cycle_timer.get_start();
-	m_cycle_timer.reset_start(PBD::get_microseconds());
-	m_cycle_count++;
+	_last_cycle_start = _cycle_timer.get_start();
+	_cycle_timer.reset_start(PBD::get_microseconds());
+	_cycle_count++;
 
-	uint64_t cycle_diff_us = (m_cycle_timer.get_start() - m_last_cycle_start);
-	int64_t deviation_us = (cycle_diff_us - m_cycle_timer.get_length_us());
-	m_total_deviation_us += ::llabs(deviation_us);
-	m_max_deviation_us =
-	    std::max(m_max_deviation_us, (uint64_t)::llabs(deviation_us));
+	uint64_t cycle_diff_us = (_cycle_timer.get_start() - _last_cycle_start);
+	int64_t deviation_us = (cycle_diff_us - _cycle_timer.get_length_us());
+	_total_deviation_us += ::llabs(deviation_us);
+	_max_deviation_us =
+	    std::max(_max_deviation_us, (uint64_t)::llabs(deviation_us));
 
-	if ((m_cycle_count % 1000) == 0) {
-		uint64_t mean_deviation_us = m_total_deviation_us / m_cycle_count;
+	if ((_cycle_count % 1000) == 0) {
+		uint64_t mean_deviation_us = _total_deviation_us / _cycle_count;
 		DEBUG_TIMING(string_compose("Mean avg cycle deviation: %1(ms), max %2(ms)\n",
 		                            mean_deviation_us * 1e-3,
-		                            m_max_deviation_us * 1e-3));
+		                            _max_deviation_us * 1e-3));
 	}
 
-	if (::llabs(deviation_us) > m_cycle_timer.get_length_us()) {
+	if (::llabs(deviation_us) > _cycle_timer.get_length_us()) {
 		DEBUG_TIMING(
 		    string_compose("time between process(ms): %1, Est(ms): %2, Dev(ms): %3\n",
 		                   cycle_diff_us * 1e-3,
-		                   m_cycle_timer.get_length_us() * 1e-3,
+		                   _cycle_timer.get_length_us() * 1e-3,
 		                   deviation_us * 1e-3));
 	}
 
@@ -1597,14 +1844,14 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data,
 	_processed_samples += _samples_per_period;
 
 	/* calculate DSP load */
-	m_dsp_calc.set_stop_timestamp_us (PBD::get_microseconds());
-	_dsp_load = m_dsp_calc.get_dsp_load();
+	_dsp_calc.set_stop_timestamp_us (PBD::get_microseconds());
+	_dsp_load = _dsp_calc.get_dsp_load();
 
 	DEBUG_TIMING(string_compose("DSP Load: %1\n", _dsp_load));
 
-	max_elapsed_us = std::max(m_dsp_calc.elapsed_time_us(), max_elapsed_us);
-	min_elapsed_us = std::min(m_dsp_calc.elapsed_time_us(), min_elapsed_us);
-	if ((m_cycle_count % 1000) == 0) {
+	max_elapsed_us = std::max(_dsp_calc.elapsed_time_us(), max_elapsed_us);
+	min_elapsed_us = std::min(_dsp_calc.elapsed_time_us(), min_elapsed_us);
+	if ((_cycle_count % 1000) == 0) {
 		DEBUG_TIMING(string_compose("Elapsed process time(usecs) max: %1, min: %2\n",
 		                            max_elapsed_us,
 		                            min_elapsed_us));
@@ -1660,12 +1907,12 @@ PortAudioBackend::process_incoming_midi ()
 		uint8_t data[256];
 		size_t size = sizeof(data);
 		while (_midiio->dequeue_input_event(i,
-		                                    m_cycle_timer.get_start(),
-		                                    m_cycle_timer.get_next_start(),
+		                                    _cycle_timer.get_start(),
+		                                    _cycle_timer.get_next_start(),
 		                                    timestamp,
 		                                    data,
 		                                    size)) {
-			sample_offset = m_cycle_timer.samples_since_cycle_start(timestamp);
+			sample_offset = _cycle_timer.samples_since_cycle_start(timestamp);
 			midi_event_put(mbuf, sample_offset, data, size);
 			DEBUG_MIDI(string_compose("Dequeuing incoming MIDI data for device: %1 "
 			                          "sample_offset: %2 timestamp: %3, size: %4\n",
@@ -1698,7 +1945,7 @@ PortAudioBackend::process_outgoing_midi ()
 		for (PortMidiBuffer::const_iterator mit = src->begin(); mit != src->end();
 		     ++mit) {
 			uint64_t timestamp =
-			    m_cycle_timer.timestamp_from_sample_offset((*mit)->timestamp());
+			    _cycle_timer.timestamp_from_sample_offset((*mit)->timestamp());
 			DEBUG_MIDI(string_compose("Queuing outgoing MIDI data for device: "
 			                          "%1 sample_offset: %2 timestamp: %3, size: %4\n",
 			                          _midiio->get_outputs()[i]->name(),
@@ -1754,7 +2001,7 @@ static bool already_configured ();
 static bool available ();
 
 static ARDOUR::AudioBackendInfo _descriptor = {
-	"PortAudio",
+	BACKEND_NAME,
 	instantiate,
 	deinstantiate,
 	backend_factory,
diff --git a/libs/backends/portaudio/portaudio_backend.h b/libs/backends/portaudio/portaudio_backend.h
index b0d1487..f0ef5fa 100644
--- a/libs/backends/portaudio/portaudio_backend.h
+++ b/libs/backends/portaudio/portaudio_backend.h
@@ -318,7 +318,9 @@ class PortAudioBackend : public AudioBackend {
 
 		void* get_buffer (PortHandle, pframes_t);
 
-		void* main_blocking_process_thread ();
+		void* blocking_process_thread ();
+
+		void* freewheel_process_thread ();
 
 	private: // Methods
 		bool start_blocking_process_thread ();
@@ -334,6 +336,22 @@ class PortAudioBackend : public AudioBackend {
 		bool engine_halted ();
 		bool running ();
 
+		static int portaudio_callback(const void* input,
+	                                  void* output,
+	                                  unsigned long frameCount,
+	                                  const PaStreamCallbackTimeInfo* timeInfo,
+	                                  PaStreamCallbackFlags statusFlags,
+	                                  void* userData);
+
+		bool process_callback(const float* input,
+	                          float* output,
+	                          uint32_t frame_count,
+	                          const PaStreamCallbackTimeInfo* timeInfo,
+	                          PaStreamCallbackFlags statusFlags);
+
+		bool start_freewheel_process_thread ();
+		bool stop_freewheel_process_thread ();
+
 		static bool set_mmcss_pro_audio (HANDLE* task_handle);
 		static bool reset_mmcss (HANDLE task_handle);
 
@@ -346,16 +364,23 @@ class PortAudioBackend : public AudioBackend {
 		bool  _active; /* is running, process thread */
 		bool  _freewheel;
 		bool  _freewheeling;
+		bool  _freewheel_ack;
+		bool  _reinit_thread_callback;
 		bool  _measure_latency;
 
-		ARDOUR::DSPLoadCalculator m_dsp_calc;
+		ARDOUR::DSPLoadCalculator _dsp_calc;
 
-		uint64_t m_cycle_count;
-		uint64_t m_total_deviation_us;
-		uint64_t m_max_deviation_us;
+		bool _freewheel_thread_active;
 
-		CycleTimer m_cycle_timer;
-		uint64_t m_last_cycle_start;
+		pthread_mutex_t _freewheel_mutex;
+		pthread_cond_t _freewheel_signal;
+
+		uint64_t _cycle_count;
+		uint64_t _total_deviation_us;
+		uint64_t _max_deviation_us;
+
+		CycleTimer _cycle_timer;
+		uint64_t _last_cycle_start;
 
 		static std::vector<std::string> _midi_options;
 		static std::vector<AudioBackend::DeviceStatus> _input_audio_device_status;
@@ -387,6 +412,12 @@ class PortAudioBackend : public AudioBackend {
 		/* blocking thread */
 		pthread_t _main_blocking_thread;
 
+		/* main thread in callback mode(or fw thread when running) */
+		pthread_t _main_thread;
+
+		/* freewheel thread in callback mode */
+		pthread_t _pthread_freewheel;
+
 		/* process threads */
 		static void* portaudio_process_thread (void *);
 		std::vector<pthread_t> _threads;
diff --git a/libs/backends/portaudio/portaudio_io.cc b/libs/backends/portaudio/portaudio_io.cc
index 678a59f..22314f8 100644
--- a/libs/backends/portaudio/portaudio_io.cc
+++ b/libs/backends/portaudio/portaudio_io.cc
@@ -204,8 +204,17 @@ PortAudioIO::get_asio_buffer_properties (int device_id,
 	return true;
 }
 
+static
 bool
-PortAudioIO::get_asio_buffer_sizes (int device_id, std::vector<uint32_t>& buffer_sizes)
+is_power_of_two (uint32_t v)
+{
+	return ((v != 0) && !(v & (v - 1)));
+}
+
+bool
+PortAudioIO::get_asio_buffer_sizes(int device_id,
+                                   std::vector<uint32_t>& buffer_sizes,
+                                   bool preferred_only)
 {
 	long min_size_frames = 0;
 	long max_size_frames = 0;
@@ -231,26 +240,51 @@ PortAudioIO::get_asio_buffer_sizes (int device_id, std::vector<uint32_t>& buffer
 	                             preferred_size_frames,
 	                             granularity));
 
-#ifdef USE_ASIO_MIN_MAX_BUFFER_SIZES
-	if (min_size_frames >= max_size_frames) {
-		buffer_sizes.push_back (preferred_size_frames);
+	bool driver_returns_one_size = (min_size_frames == max_size_frames) &&
+	                               (min_size_frames == preferred_size_frames);
+
+	if (preferred_only || driver_returns_one_size) {
+		buffer_sizes.push_back(preferred_size_frames);
 		return true;
 	}
 
 	long buffer_size = min_size_frames;
-	while (buffer_size <= max_size_frames) {
-		buffer_sizes.push_back (buffer_size);
 
-		if (granularity <= 0) {
-			// buffer sizes are power of 2
-			buffer_size = buffer_size * 2;
-		} else {
+	// If min size and granularity are power of two then just use values that
+	// are power of 2 even if the granularity allows for more values
+	bool use_power_of_two =
+	    is_power_of_two(min_size_frames) && is_power_of_two(granularity);
+
+	if (granularity <= 0 || use_power_of_two) {
+		// driver uses buffer sizes that are power of 2
+		while (buffer_size <= max_size_frames) {
+			buffer_sizes.push_back(buffer_size);
+			buffer_size *= 2;
+		}
+	} else {
+		if (min_size_frames == max_size_frames) {
+			// The devices I have tested either return the same values for
+			// min/max/preferred and changing buffer size is intended to only be
+			// done via the control dialog or they return a range where min != max
+			// but I guess min == max could happen if a driver only supports a single
+			// buffer size
+			buffer_sizes.push_back(min_size_frames);
+			return true;
+		}
+
+		// If min_size_frames is not power of 2 use at most 8 of the possible
+		// buffer sizes spread evenly between min and max
+		long max_values = 8;
+		while (((max_size_frames - min_size_frames) / granularity) > max_values) {
+			granularity *= 2;
+		}
+
+		while (buffer_size < max_size_frames) {
+			buffer_sizes.push_back(buffer_size);
 			buffer_size += granularity;
 		}
+		buffer_sizes.push_back(max_size_frames);
 	}
-#else
-	buffer_sizes.push_back (preferred_size_frames);
-#endif
 	return true;
 }
 #endif
@@ -272,7 +306,7 @@ PortAudioIO::available_buffer_sizes(int device_id, std::vector<uint32_t>& buffer
 {
 #ifdef WITH_ASIO
 	if (get_current_host_api_type() == paASIO) {
-		if (get_asio_buffer_sizes (device_id, buffer_sizes)) {
+		if (get_asio_buffer_sizes (device_id, buffer_sizes, false)) {
 			return 0;
 		}
 	}
@@ -745,6 +779,49 @@ PortAudioIO::pre_stream_open(int device_input,
 }
 
 PaErrorCode
+PortAudioIO::open_callback_stream(int device_input,
+                                  int device_output,
+                                  double sample_rate,
+                                  uint32_t samples_per_period,
+                                  PaStreamCallback* callback,
+                                  void* data)
+{
+	PaStreamParameters inputParam;
+	PaStreamParameters outputParam;
+
+	PaErrorCode error_code =
+	    pre_stream_open(device_input, inputParam, device_output, outputParam);
+
+	if (error_code != paNoError) return error_code;
+
+	PaError err = paNoError;
+
+	DEBUG_AUDIO ("Open Callback Stream\n");
+
+	err = Pa_OpenStream(&_stream,
+	                    _capture_channels > 0 ? &inputParam : NULL,
+	                    _playback_channels > 0 ? &outputParam : NULL,
+	                    sample_rate,
+	                    samples_per_period,
+	                    paDitherOff,
+	                    callback,
+	                    data);
+
+	if (err != paNoError) {
+		DEBUG_AUDIO ("PortAudio failed to start stream.\n");
+		return paInternalError;
+	}
+
+	if (!set_sample_rate_and_latency_from_stream()) {
+		DEBUG_AUDIO ("PortAudio failed to query stream information.\n");
+		close_stream();
+		return paInternalError;
+	}
+
+	return paNoError;
+}
+
+PaErrorCode
 PortAudioIO::open_blocking_stream(int device_input,
                                   int device_output,
                                   double sample_rate,
diff --git a/libs/backends/portaudio/portaudio_io.h b/libs/backends/portaudio/portaudio_io.h
index bc0da78..c67fdc1 100644
--- a/libs/backends/portaudio/portaudio_io.h
+++ b/libs/backends/portaudio/portaudio_io.h
@@ -63,16 +63,26 @@ public:
 	                                 long& preferred_size_frames,
 	                                 long& granularity);
 
-	bool get_asio_buffer_sizes (int device_id, std::vector<uint32_t>& buffer_size);
+	bool get_asio_buffer_sizes(int device_id,
+	                           std::vector<uint32_t>& buffer_size,
+	                           bool preferred_only);
 #endif
 
 	std::string control_app_name (int device_id) const;
 	void launch_control_app (int device_id);
 
 	PaErrorCode open_blocking_stream(int device_input,
-	                               int device_output,
-	                               double sample_rate,
-	                               uint32_t samples_per_period);
+	                                 int device_output,
+	                                 double sample_rate,
+	                                 uint32_t samples_per_period);
+
+	PaErrorCode open_callback_stream(int device_input,
+	                                 int device_output,
+	                                 double sample_rate,
+	                                 uint32_t samples_per_period,
+	                                 PaStreamCallback* callback,
+	                                 void* data);
+
 	PaErrorCode start_stream(void);
 
 	PaErrorCode close_stream(void);
diff --git a/libs/backends/portaudio/wscript b/libs/backends/portaudio/wscript
index 0d679a1..46b0e25 100644
--- a/libs/backends/portaudio/wscript
+++ b/libs/backends/portaudio/wscript
@@ -19,7 +19,7 @@ def configure(conf):
     autowaf.check_pkg(conf, 'portaudio-2.0', uselib_store='PORTAUDIO', atleast_version='19')
     conf.check(header_name='pa_asio.h', define_name='WITH_ASIO', mandatory=False)
 
-def build(bld):
+def build_portaudio (bld, name, defines):
     obj = bld(features = 'cxx cxxshlib')
     obj.source = [ 'portaudio_backend.cc',
                    'portaudio_io.cc',
@@ -29,8 +29,8 @@ def build(bld):
                    'midi_util.cc',
                  ]
     obj.includes = ['.']
-    obj.name     = 'portaudio_backend'
-    obj.target   = 'portaudio_backend'
+    obj.name     = name
+    obj.target   = name
     obj.use      = 'libardour libpbd'
     obj.uselib   = ['PORTAUDIO']
     obj.install_path  = os.path.join(bld.env['LIBDIR'], 'backends')
@@ -38,3 +38,8 @@ def build(bld):
                    'ARDOURBACKEND_DLL_EXPORTS',
                    'USE_MMCSS_THREAD_PRIORITIES'
                   ]
+    obj.defines += defines
+
+def build(bld):
+    build_portaudio (bld, 'portaudio_callback_backend', ['BACKEND_NAME="PortAudio (default)"'])
+    build_portaudio (bld, 'portaudio_blocking_backend', ['BACKEND_NAME="PortAudio (no-callback)"', 'USE_BLOCKING_API'])
diff --git a/libs/backends/wscript b/libs/backends/wscript
index a504796..833d831 100644
--- a/libs/backends/wscript
+++ b/libs/backends/wscript
@@ -19,7 +19,7 @@ def sub_config_and_use(conf, name, has_objects = True):
 def configure(conf):
     autowaf.set_recursive()
     autowaf.configure(conf)
-    
+
     backends = conf.env['BACKENDS']
     for i in backends:
         sub_config_and_use(conf, i)
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index 0fcac6a..6bf1959 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -389,6 +389,7 @@ GtkCanvas::GtkCanvas ()
 	, _single_exposure (1)
 	, current_tooltip_item (0)
 	, tooltip_window (0)
+	, _in_dtor (false)
 {
 	/* these are the events we want to know about */
 	add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK |
@@ -779,6 +780,10 @@ GtkCanvas::on_size_allocate (Gtk::Allocation& a)
 bool
 GtkCanvas::on_expose_event (GdkEventExpose* ev)
 {
+	if (_in_dtor) {
+		return true;
+	}
+
 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
 	Cairo::RefPtr<Cairo::Context> draw_context;
 	Cairo::RefPtr<Cairo::Context> window_context;
@@ -1039,6 +1044,10 @@ GtkCanvas::on_leave_notify_event (GdkEventCrossing* ev)
 void
 GtkCanvas::request_redraw (Rect const & request)
 {
+	if (_in_dtor) {
+		return;
+	}
+
 	Rect real_area;
 
 	Coord const w = width ();
diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h
index 87e580e..b818c7e 100644
--- a/libs/canvas/canvas/canvas.h
+++ b/libs/canvas/canvas/canvas.h
@@ -172,6 +172,7 @@ class LIBCANVAS_API GtkCanvas : public Canvas, public Gtk::EventBox
 {
 public:
 	GtkCanvas ();
+	~GtkCanvas () { _in_dtor = true ; }
 
 	void request_redraw (Rect const &);
 	void request_size (Duple);
@@ -238,6 +239,8 @@ private:
 	bool show_tooltip ();
 	void hide_tooltip ();
 	bool really_start_tooltip_timeout ();
+
+	bool _in_dtor;
 };
 
 /** A GTK::Alignment with a GtkCanvas inside it plus some Gtk::Adjustments for
diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc
index 47eb77d..dc82245 100644
--- a/libs/canvas/item.cc
+++ b/libs/canvas/item.cc
@@ -18,7 +18,7 @@
 */
 
 #include "pbd/compose.h"
-#include "pbd/stacktrace.h"
+#include "pbd/demangle.h"
 #include "pbd/convert.h"
 
 #include "ardour/utils.h"
diff --git a/libs/canvas/wave_view.cc b/libs/canvas/wave_view.cc
index fce30e7..3d70527 100644
--- a/libs/canvas/wave_view.cc
+++ b/libs/canvas/wave_view.cc
@@ -73,6 +73,8 @@ WaveView::DrawingRequestQueue WaveView::request_queue;
 PBD::Signal0<void> WaveView::VisualPropertiesChanged;
 PBD::Signal0<void> WaveView::ClipLevelChanged;
 
+#undef ENABLE_THREADED_WAVEFORM_RENDERING
+
 WaveView::WaveView (Canvas* c, boost::shared_ptr<ARDOUR::AudioRegion> region)
 	: Item (c)
 	, _region (region)
@@ -835,7 +837,12 @@ WaveView::get_image (framepos_t start, framepos_t end, bool& full_image) const
 
 	if (!ret || !full_image) {
 
-		if ((rendered && get_image_in_thread) || always_get_image_in_thread) {
+#ifndef ENABLE_THREADED_WAVEFORM_RENDERING
+		if (1)
+#else
+		if ((rendered && get_image_in_thread) || always_get_image_in_thread)
+#endif
+		{
 
 			DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1: generating image in caller thread\n", name));
 
@@ -1508,7 +1515,7 @@ WaveView::start_drawing_thread ()
 void
 WaveView::stop_drawing_thread ()
 {
-	if (_drawing_thread) {
+	while (_drawing_thread) {
 		Glib::Threads::Mutex::Lock lm (request_queue_lock);
 		g_atomic_int_set (&drawing_thread_should_quit, 1);
 		request_cond.signal ();
@@ -1537,8 +1544,7 @@ WaveView::drawing_thread ()
 		}
 
 		if (request_queue.empty()) {
-			assert (g_atomic_int_get (&drawing_thread_should_quit));
-			continue; // or break;
+			continue;
 		}
 
 		/* remove the request from the queue (remember: the "request"
diff --git a/libs/canvas/wscript b/libs/canvas/wscript
index 67d26ea..2a4cc0b 100644
--- a/libs/canvas/wscript
+++ b/libs/canvas/wscript
@@ -81,7 +81,7 @@ def build(bld):
         obj.cxxflags     = [ '-fPIC' ]
         obj.cflags       = [ '-fPIC' ]
         obj.defines      = [ ]
-        
+
     obj.export_includes = ['.']
     obj.includes     = ['.']
     obj.uselib       = 'SIGCPP CAIROMM GTKMM BOOST'
@@ -91,7 +91,7 @@ def build(bld):
     obj.vnum         = CANVAS_LIB_VERSION
     obj.install_path = bld.env['LIBDIR']
     obj.defines      += [ 'PACKAGE="' + I18N_PACKAGE + '"' ]
-    
+
     if bld.env['BUILD_TESTS'] and bld.env['HAVE_CPPUNIT']:
 
             manual_tests              = '''
@@ -114,7 +114,7 @@ def build(bld):
                     manual_testobj.name         = 'libcanvas-manual-test-%s' % name
                     manual_testobj.target       = target
                     manual_testobj.install_path = ''
-                    
+
                     unit_testobj              = bld.new_task_gen('cxx', 'program')
                     unit_testobj.source       = '''
                         test/group.cc
@@ -139,7 +139,7 @@ def build(bld):
                     unit_testobj.cxxflags     += ['-DDATA_DIR="' + os.path.normpath(bld.env['DATADIR']) + '"']
                     unit_testobj.cxxflags     += ['-DCONFIG_DIR="' + os.path.normpath(bld.env['CONFIGDIR']) + '"']
                     unit_testobj.cxxflags     += ['-DMODULE_DIR="' + os.path.normpath(bld.env['LIBDIR']) + '"']
-                    
+
             benchmarks = '''
                         benchmark/items_at_point.cc
                         benchmark/render_parts.cc
diff --git a/libs/evoral/MSVCevoral/evoral.vcproj b/libs/evoral/MSVCevoral/evoral.vcproj
index e80bee5..2a299d3 100644
--- a/libs/evoral/MSVCevoral/evoral.vcproj
+++ b/libs/evoral/MSVCevoral/evoral.vcproj
@@ -41,7 +41,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI$(TargetSxsFolder)\targetsxs.h"
 				Optimization="0"
-				AdditionalIncludeDirectories="..;..\..\pbd;"$(GenericIncludeFolder)";"$(GenericLibraryFolder)\glib-2.0\include""
+				AdditionalIncludeDirectories="..;..\..\pbd;"$(GenericIncludeFolder)";"$(GenericLibraryFolder)\glib-2.0\include";"$(GenericIncludeFolder)\ardourext""
 				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;BUILDING_EVORAL;LIBEVORAL_DLL_EXPORTS;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;WIN32;_WIN32;_DEBUG;DEBUG="Debug";ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PACKAGE="\"libevoral\"";PROGRAM_NAME="\"Mixbus3\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
 				MinimalRebuild="true"
 				RuntimeLibrary="3"
@@ -120,7 +120,7 @@
 				AdditionalOptions="/FI$(TargetSxsFolder)\targetsxs.h"
 				Optimization="2"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..;..\..\pbd;"$(GenericIncludeFolder)";"$(GenericLibraryFolder)\glib-2.0\include""
+				AdditionalIncludeDirectories="..;..\..\pbd;"$(GenericIncludeFolder)";"$(GenericLibraryFolder)\glib-2.0\include";"$(GenericIncludeFolder)\ardourext""
 				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;_SECURE_SCL=0;BUILDING_EVORAL;LIBEVORAL_DLL_EXPORTS;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;WIN32;_WIN32;NDEBUG;ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PACKAGE="\"libevoral\"";PROGRAM_NAME="\"Mixbus3\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
 				StringPooling="false"
 				RuntimeLibrary="2"
@@ -199,7 +199,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI$(TargetSxsFolder)\targetsxs.h"
 				Optimization="0"
-				AdditionalIncludeDirectories="..;..\..\pbd;"$(GenericIncludeFolder)";"$(GenericLibraryFolder)\glib-2.0\include""
+				AdditionalIncludeDirectories="..;..\..\pbd;"$(GenericIncludeFolder)";"$(GenericLibraryFolder)\glib-2.0\include";"$(GenericIncludeFolder)\ardourext""
 				PreprocessorDefinitions="PLATFORM_WINDOWS;COMPILER_MSVC;UINTSDEFINED=1;_SECURE_SCL=0;BUILDING_EVORAL;LIBEVORAL_DLL_EXPORTS;INCLUDE_ARDOUR_MISCELLANEOUS=1;BOOST_REGEX_DYN_LINK;BOOST_REGEX_NO_LIB;BOOST_CHRONO_NO_LIB;BOOST_SYSTEM_NO_LIB;BOOST_THREAD_NO_LIB;BOOST_DATE_TIME_NO_LIB;WIN32;_WIN32;ARCH_X86;USE_XMMINTRIN;BUILD_SSE_OPTIMIZATIONS;ENABLE_NLS;PACKAGE="\"libevoral\"";PROGRAM_NAME="\"Mixbus3\"";_REENTRANT;_USE_MATH_DEFINES;_LARGEFILE_SOURCE;_LARGEFILE64_SOURCE;LIBC_DISABLE_DEPRECATED;BOOST_SYSTEM_NO_DEPRECATED;__STDC_LIMIT_MACROS;__STDC_FORMAT_MACROS;INTERNAL_SHARED_LIBS=1;JACK_SESSION=1;HAVE_GLIB=1;HAVE_GTHREAD=1;HAVE_SNDFILE=1;HAVE_GIOMM=1;HAVE_CURL=1;HAVE_LO=1;HAVE_MODE_T=1;PHONE_HOME=1;FREESOUND=1;WINDOWS_KEY=\"Mod4><Super\";IS_OSX=0;HAVE_XML=1;HAVE_UUID=1;HAVE_LIBS_PBD=1;HAVE_JACK=1;HAVE_LIBS_MIDIPP2=1;HAVE_LIBS_EVORAL=1;HAVE_FFTW3=1;HAVE_FFTW3F=1;HAVE_AUBIO=1;HAVE_LIBS_VAMP_SDK=1;HAVE_LIBS_VAMP_PLUGINS=1;HAVE_LIBS_TAGLIB=1;HAVE_LIBS_LIBLTC=1;HAVE_LIBS_RUBBERBAND=1;HAVE_CONTROL_PROTOCOL=1;HAVE_FRONTIER=1;HAVE_GENERIC_MIDI=1;HAVE_MACKIE=1;HAVE_OSC=1;HAVE_TRANZPORT=1;HAVE_WIIMOTE=1;HAVE_LIBS_SURFACES=1;HAVE_2IN2OUT=1;HAVE_1IN2OUT=1;HAVE_VBAP=1;HAVE_LIBS_PANNERS=1;HAVE_LIBS_TIMECODE=1;HAVE_LRDF=1;HAVE_SAMPLERATE=1;HAVE_SERD=1;HAVE_SORD=1;HAVE_SRATOM=1;HAVE_LILV=1;HAVE_LILV_0_16_0=1;HAVE_OGG=1;HAVE_FLAC=1;HAVE_RUBBERBAND=1;USE_RUBBERBAND=1;HAVE_JACK_SESSION=1;HAVE_UNISTD=1;HAVE_JACK_ON_INFO_SHUTDOWN=1;HAVE_JACK_VIDEO_SUPPORT=1;HAVE_BOOST_SCOPED_PTR_HPP=1;HAVE_BOOST_PTR_CONTAINER_PTR_LIST_HPP=1;HAVE_LIBS_ARDOUR=1;HAVE_GTKMM=1;HAVE_GTK=1;HAVE_LIBS_GTKMM2EXT=1;HAVE_LIBS_CLEARLOOKS_NEWER=1;HAVE_BOOST_FORMAT_HPP=1;HAVE_LIBS_AUDIOGRAPHER=1;HAVE_GNOMECANVAS=0;HAVE_GNOMECANVASMM=0;HAVE_X11=0;HAVE_FONTCONFIG=1;HAVE_BOOST_SHARED_PTR_HPP=1;HAVE_BOOST_WEAK_PTR_HPP=1;HAVE_GTK2_ARDOUR=1;HAVE_EXPORT=1;HAVE_MIDI_MAPS=1;HAVE_MCP=1;HAVE_PATCHFILES=1;HAVE_TOOLS_SANITY_CHECK=1;SMF_VERSION=\"1.2\";CURRENT_SESSION_FILE_VERSION=3001"
 				StringPooling="false"
 				RuntimeLibrary="2"
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 3784b25..f1a4627 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -125,7 +125,8 @@ public:
 	void shift (double before, double distance);
 
 	virtual void add (double when, double value, bool with_guards=true, bool with_initial=true);
-	virtual void editor_add (double when, double value, bool with_guard);
+
+	virtual bool editor_add (double when, double value, bool with_guard);
 
 	void fast_simple_add (double when, double value);
 
@@ -266,6 +267,7 @@ public:
         void write_pass_finished (double when, double thinning_factor=0.0);
         void set_in_write_pass (bool, bool add_point = false, double when = 0.0);
         bool in_write_pass () const;
+	bool in_new_write_pass () { return new_write_pass; }
 
 	/** Emitted when mark_dirty() is called on this object */
 	mutable PBD::Signal0<void> Dirty;
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp
index d8665d3..73c1675 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -451,12 +451,19 @@ ControlList::in_write_pass () const
 	return _in_write_pass;
 }
 
-void
+bool
 ControlList::editor_add (double when, double value, bool with_guard)
 {
 	/* this is for making changes from a graphical line editor
 	*/
 
+	ControlEvent cp (when, 0.0f);
+	iterator i = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
+
+	if (i != _events.end () && (*i)->when == when) {
+		return false;
+	}
+
 	if (_events.empty()) {
 
 		/* as long as the point we're adding is not at zero,
@@ -477,15 +484,18 @@ ControlList::editor_add (double when, double value, bool with_guard)
 		maybe_add_insert_guard (when);
 	}
 
-	ControlEvent cp (when, 0.0f);
-	iterator i = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
+	iterator result;
 	DEBUG_TRACE (DEBUG::ControlList, string_compose ("editor_add: actually add when= %1 value= %2\n", when, value));
-	_events.insert (i, new ControlEvent (when, value));
+	result = _events.insert (i, new ControlEvent (when, value));
 
-	mark_dirty ();
+	if (i == result) {
+		return false;
+	}
 
+	mark_dirty ();
 	maybe_signal_changed ();
 
+	return true;
 }
 
 void
@@ -574,8 +584,15 @@ ControlList::add (double when, double value, bool with_guards, bool with_initial
 			/* empty: add an "anchor" point if the point we're adding past time 0 */
 
 			if (when >= 1) {
-				_events.insert (_events.end(), new ControlEvent (0, value));
-				DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added default value %2 at zero\n", this, _default_value));
+				if (_desc.toggled) {
+					const double opp_val = ((value < 0.5) ? 1.0 : 0.0);
+					_events.insert (_events.end(), new ControlEvent (0, opp_val));
+					DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added toggled value %2 at zero\n", this, opp_val));
+
+				} else {
+					_events.insert (_events.end(), new ControlEvent (0, value));
+					DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added default value %2 at zero\n", this, _default_value));
+				}
 			}
 		}
 
@@ -1646,6 +1663,9 @@ ControlList::paste (const ControlList& alist, double pos, float /*times*/)
 				value /= (src_desc.upper - src_desc.lower);  // normalize range
 				value *= (_desc.upper - _desc.lower);  // scale to our range
 				value += _desc.lower;  // translate to our offset
+				if (_desc.toggled) {
+					value = (value < 0.5) ? 0.0 : 1.0;
+				}
 			}
 			_events.insert (where, new ControlEvent((*i)->when + pos, value));
 			end = (*i)->when + pos;
diff --git a/libs/evoral/src/Event.cpp b/libs/evoral/src/Event.cpp
index 86b70da..64caba3 100644
--- a/libs/evoral/src/Event.cpp
+++ b/libs/evoral/src/Event.cpp
@@ -38,6 +38,15 @@ init_event_id_counter(event_id_t n)
 event_id_t
 next_event_id ()
 {
+	/* TODO: handle 31bit overflow , event_id_t is an int32_t,
+	 * and libsmf only supports loading uint32_t vlq's, see smf_extract_vlq()
+	 *
+	 * event-IDs only have to be unique per .mid file.
+	 * Previously (Ardour 4.2ish) Ardour re-generated those IDs when loading the
+	 * file but that lead to .mid files being modified on every load/save.
+	 *
+	 * current user-record: is event-counter="276390506" (just abov 2^28)
+	 */
 	return g_atomic_int_add (&_event_id_counter, 1);
 }
 
diff --git a/libs/evoral/src/libsmf/smf_load.c b/libs/evoral/src/libsmf/smf_load.c
index a23a88f..001774c 100644
--- a/libs/evoral/src/libsmf/smf_load.c
+++ b/libs/evoral/src/libsmf/smf_load.c
@@ -214,13 +214,19 @@ smf_extract_vlq(const unsigned char *buf, const size_t buffer_length, uint32_t *
 {
 	uint32_t val = 0;
 	const unsigned char *c = buf;
+	int i = 0;
 
-	for (;;) {
+	for (;; ++i) {
 		if (c >= buf + buffer_length) {
 			g_critical("End of buffer in extract_vlq().");
 			return (-1);
 		}
 
+		if (i == 4 && (val & 0xfe000000)) {
+			g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
+			return (-2);
+		}
+
 		val = (val << 7) + (*c & 0x7F);
 
 		if (*c & 0x80)
@@ -233,7 +239,7 @@ smf_extract_vlq(const unsigned char *buf, const size_t buffer_length, uint32_t *
 	*value = val;
 	*len = c - buf + 1;
 
-	if (*len > 4) {
+	if (*len > 5) {
 		g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
 		return (-2);
 	}
diff --git a/libs/fst/wscript b/libs/fst/wscript
index 76e0b93..9fe165c 100644
--- a/libs/fst/wscript
+++ b/libs/fst/wscript
@@ -66,6 +66,7 @@ def build(bld):
         obj.target = 'ardour-vst-scanner.exe.so'
         obj.uselib = ['GIOMM', 'DL']
         obj.use = [ 'libpbd' ]
+        obj.cxxflags  = [ '-fPIC' ]
     else:
         obj = bld (features = 'cxx c cxxprogram')
         obj.source = ( 'scanner.cc' )
diff --git a/libs/gtkmm2ext/dndtreeview.cc b/libs/gtkmm2ext/dndtreeview.cc
index 53b212d..bc6745d 100644
--- a/libs/gtkmm2ext/dndtreeview.cc
+++ b/libs/gtkmm2ext/dndtreeview.cc
@@ -33,6 +33,7 @@ DnDTreeViewBase::DragData DnDTreeViewBase::drag_data;
 
 DnDTreeViewBase::DnDTreeViewBase ()
 	: TreeView ()
+	, _drag_column (-1)
 {
 	draggable.push_back (TargetEntry ("GTK_TREE_MODEL_ROW", TARGET_SAME_WIDGET));
 	data_column = -1;
@@ -44,6 +45,74 @@ DnDTreeViewBase::DnDTreeViewBase ()
 }
 
 void
+DnDTreeViewBase::on_drag_begin (Glib::RefPtr<Gdk::DragContext> const & context) {
+	if (_drag_column >= 0) {
+		/* this code is a customized drop-in replacement for
+		 * Gtk::TreeView::on_drag_begin().
+		 * We can use it's cleanup function for the generated Pixmap
+		 */
+
+		TreeModel::Path path;
+		TreeViewColumn* column;
+		int cell_x;
+		int cell_y;
+
+		if (!get_path_at_pos ((int)press_start_x, (int)press_start_y, path, column, cell_x, cell_y)) {
+			return;
+		}
+
+		TreeIter iter = get_model()->get_iter (path);
+		int x_offset, y_offset, width, height;
+
+		Gdk::Rectangle unused;
+		TreeViewColumn* clm = get_column(_drag_column);
+
+		clm->cell_set_cell_data (get_model(), iter, false, false);
+		clm->cell_get_size (unused, x_offset, y_offset, width, height);
+
+		Glib::RefPtr<Gdk::Pixmap> pixmap = Gdk::Pixmap::create (get_root_window(), width, height);
+
+		CellRenderer* cell_renderer = clm->get_first_cell ();
+		Gdk::Rectangle cell_background (0, 0, width, height);
+		Gdk::Rectangle cell_size (x_offset, y_offset, width, height);
+
+		// the cell-renderer only clears the background if
+		// cell->cell_background_set and priv->cell_background
+		Gdk::Color clr = get_style()->get_bg(STATE_NORMAL);
+		// code dup from gtk_cell_renderer_render() to clear the background:
+		cairo_t *cr = gdk_cairo_create (Glib::unwrap(pixmap));
+		gdk_cairo_rectangle (cr, (cell_background).gobj());
+		gdk_cairo_set_source_color (cr, clr.gobj());
+		cairo_fill (cr);
+		cairo_destroy (cr);
+
+		// gtkmm wants a "window", gtk itself is happy with a "drawable",
+		// cell_renderer->render (pixmap, *this, cell_area, cell_area, cell_area, 0);
+		// We ain't got no window, so use gtk directly:
+		gtk_cell_renderer_render (cell_renderer->gobj(),
+				Glib::unwrap(pixmap), ((Gtk::Widget*)this)->gobj(),
+				(cell_background).gobj(),
+				(cell_size).gobj(),
+				(cell_size).gobj(),
+				((GtkCellRendererState)(0)));
+
+		context->set_icon (pixmap->get_colormap(),
+				pixmap, Glib::RefPtr<Gdk::Bitmap>(NULL),
+				width / 2 + 1, cell_y + 1);
+
+	} else {
+		Gtk::TreeView::on_drag_begin (context);
+	}
+	start_object_drag ();
+}
+
+void
+DnDTreeViewBase::on_drag_end (Glib::RefPtr<Gdk::DragContext> const & context) {
+	Gtk::TreeView::on_drag_end (context);
+	end_object_drag ();
+}
+
+void
 DnDTreeViewBase::add_drop_targets (list<TargetEntry>& targets)
 {
 	for (list<TargetEntry>::iterator i = targets.begin(); i != targets.end(); ++i) {
diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc
index d160146..b550b6c 100644
--- a/libs/gtkmm2ext/gtk_ui.cc
+++ b/libs/gtkmm2ext/gtk_ui.cc
@@ -67,8 +67,8 @@ BaseUI::RequestType Gtkmm2ext::AddTimeout = BaseUI::new_request_type();
 
 template class AbstractUI<Gtkmm2ext::UIRequest>;
 
-UI::UI (string namestr, int *argc, char ***argv)
-	: AbstractUI<UIRequest> (namestr)
+UI::UI (string application_name, string thread_name, int *argc, char ***argv)
+	: AbstractUI<UIRequest> (thread_name)
 	, _receiver (*this)
 	, errors (0)
 
@@ -98,6 +98,10 @@ UI::UI (string namestr, int *argc, char ***argv)
 
 	set_event_loop_for_thread (this);
 
+	/* we will be receiving requests */
+
+	EventLoop::register_request_buffer_factory ("gui", request_buffer_factory);
+
 	/* attach our request source to the default main context */
 
 	attach_request_source ();
@@ -107,7 +111,7 @@ UI::UI (string namestr, int *argc, char ***argv)
 	errors->text().set_name ("ErrorText");
 	errors->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Editor/toggle-log-window")));
 
-	Glib::set_application_name(namestr);
+	Glib::set_application_name (application_name);
 
 	WindowTitle title(Glib::get_application_name());
 	title += _("Log");
@@ -449,7 +453,7 @@ UI::do_request (UIRequest* req)
 	} else if (req->type == CallSlot) {
 #ifndef NDEBUG
 		if (getenv ("DEBUG_THREADED_SIGNALS")) {
-			cerr << "call slot for " << name() << endl;
+			cerr << "call slot for " << event_loop_name() << endl;
 		}
 #endif
 		req->the_slot ();
@@ -704,7 +708,7 @@ UI::popup_error (const string& text)
 
 	MessageDialog msg (text);
 	msg.set_title (string_compose (_("I'm sorry %1, I can't do that"), g_get_user_name()));
-	msg.set_wmclass (X_("error"), name());
+	msg.set_wmclass (X_("error"), Glib::get_application_name());
 	msg.set_position (WIN_POS_MOUSE);
 	msg.run ();
 }
diff --git a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
index 083fee6..29ae084 100644
--- a/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
+++ b/libs/gtkmm2ext/gtkmm2ext/dndtreeview.h
@@ -48,9 +48,13 @@ class LIBGTKMM2EXT_API DnDTreeViewBase : public Gtk::TreeView
 	void add_drop_targets (std::list<Gtk::TargetEntry>&);
 	void add_object_drag (int column, std::string type_name);
 
-	void on_drag_begin (Glib::RefPtr<Gdk::DragContext> const & context) {
-		Gtk::TreeView::on_drag_begin (context);
-		start_object_drag ();
+	void on_drag_begin (Glib::RefPtr<Gdk::DragContext> const & context);
+	void on_drag_end (Glib::RefPtr<Gdk::DragContext> const & context);
+
+	bool on_button_press_event (GdkEventButton *ev) {
+		press_start_x = ev->x;
+		press_start_y = ev->y;
+		return TreeView::on_button_press_event (ev);
 	}
 
 	void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& context, guint time) {
@@ -65,12 +69,20 @@ class LIBGTKMM2EXT_API DnDTreeViewBase : public Gtk::TreeView
 
 	bool on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
 
+	void set_drag_column (int c) {
+		_drag_column = c;
+	}
+
   protected:
 	std::list<Gtk::TargetEntry> draggable;
 	Gdk::DragAction             suggested_action;
 	int                         data_column;
 	std::string                 object_type;
 
+	double press_start_x;
+	double press_start_y;
+	int _drag_column;
+
 	struct DragData {
 	    DragData () : source (0) {}
 
@@ -86,6 +98,12 @@ class LIBGTKMM2EXT_API DnDTreeViewBase : public Gtk::TreeView
 		drag_data.data_column = data_column;
 		drag_data.object_type = object_type;
 	}
+
+	void end_object_drag () {
+		drag_data.source = 0;
+		drag_data.data_column = -1;
+		drag_data.object_type = "";
+	}
 };
 
 template<class DataType>
@@ -95,7 +113,7 @@ class /*LIBGTKMM2EXT_API*/ DnDTreeView : public DnDTreeViewBase
 	DnDTreeView() {}
 	~DnDTreeView() {}
 
-	sigc::signal<void,const std::list<DataType>&,Gtk::TreeView*,int,int,Glib::RefPtr<Gdk::DragContext>&> signal_drop;
+	sigc::signal<void, const Glib::RefPtr<Gdk::DragContext>&, const Gtk::SelectionData&> signal_drop;
 
 	void on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time) {
 		if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
@@ -104,12 +122,11 @@ class /*LIBGTKMM2EXT_API*/ DnDTreeView : public DnDTreeViewBase
 
 		} else if (selection_data.get_target() == object_type) {
 
-			/* we don't care about the data passed around by DnD, but
-			   we have to provide something otherwise it will stop.
+			/* return a pointer to this object, which allows
+			 * the receiver to call on_drag_data_received()
 			 */
-
-			guchar c;
-			selection_data.set (8, (guchar*)&c, 1);
+			void *c = this;
+			selection_data.set (8, (guchar*)&c, sizeof(void*));
 		}
 	}
 
@@ -124,14 +141,10 @@ class /*LIBGTKMM2EXT_API*/ DnDTreeView : public DnDTreeViewBase
 		}
 
 		if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
-
 			TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
-
-
 		} else if (selection_data.get_target() == object_type) {
-
-			end_object_drag (const_cast<Glib::RefPtr<Gdk::DragContext>& > (context), x, y);
-
+			signal_drop (context, selection_data);
+			context->drag_finish (true, false, time);
 		} else {
 			/* some kind of target type added by the app, which will be handled by a signal handler */
 		}
@@ -142,7 +155,7 @@ class /*LIBGTKMM2EXT_API*/ DnDTreeView : public DnDTreeViewBase
 	 * object that wants to get the list of dragged items.
 	 */
 
-	void get_object_drag_data (std::list<DataType>& l, Gtk::TreeView** source) {
+	void get_object_drag_data (std::list<DataType>& l, Gtk::TreeView** source) const {
 
 		if (drag_data.source == 0) {
 			return;
@@ -159,15 +172,6 @@ class /*LIBGTKMM2EXT_API*/ DnDTreeView : public DnDTreeViewBase
 
 		*source = drag_data.source;
 	}
-
-  private:
-	void end_object_drag (Glib::RefPtr<Gdk::DragContext>& context, int x, int y) {
-		std::list<DataType> l;
-		Gtk::TreeView* source;
-		get_object_drag_data (l, &source);
-		signal_drop (l, source, x, y, context);
-	}
-
 };
 
 } // namespace
diff --git a/libs/gtkmm2ext/gtkmm2ext/dndvbox.h b/libs/gtkmm2ext/gtkmm2ext/dndvbox.h
index 84289af..aba413b 100644
--- a/libs/gtkmm2ext/gtkmm2ext/dndvbox.h
+++ b/libs/gtkmm2ext/gtkmm2ext/dndvbox.h
@@ -44,6 +44,8 @@ public:
 
 	/** @return True if the child can be selected in the list ( if you don't want it to copy/paste/drag then turn this off ) */
 	virtual bool is_selectable () const = 0;
+
+	virtual bool drag_data_get (Glib::RefPtr<Gdk::DragContext> const, Gtk::SelectionData &) { return false; }
 };
 
 /** A VBox whose contents can be dragged and dropped */
@@ -51,9 +53,13 @@ template <class T>
 class /*LIBGTKMM2EXT_API*/ DnDVBox : public Gtk::EventBox
 {
 public:
-	DnDVBox () : _active (0), _drag_icon (0), _expecting_unwanted_button_event (false), _placeholder (0)
+	DnDVBox (std::list<Gtk::TargetEntry> targets)
+		: _targets (targets)
+		, _active (0)
+		, _drag_icon (0)
+		, _expecting_unwanted_button_event (false)
+		, _placeholder (0)
 	{
-		_targets.push_back (Gtk::TargetEntry ("processor"));
 
 		add (_internal_vbox);
 		add_events (
@@ -81,9 +87,13 @@ public:
 	}
 
 	/** Add a child at the end of the widget.  The DnDVBox will take responsibility for deleting the child */
-	void add_child (T* child)
+	void add_child (T* child, std::list<Gtk::TargetEntry> targets = std::list<Gtk::TargetEntry>())
 	{
-		child->action_widget().drag_source_set (_targets);
+		if (targets.empty ()) {
+			child->action_widget().drag_source_set (_targets);
+		} else {
+			child->action_widget().drag_source_set (targets);
+		}
 		child->action_widget().signal_drag_begin().connect (sigc::bind (mem_fun (*this, &DnDVBox::drag_begin), child));
 		child->action_widget().signal_drag_data_get().connect (sigc::bind (mem_fun (*this, &DnDVBox::drag_data_get), child));
 		child->action_widget().signal_drag_end().connect (sigc::bind (mem_fun (*this, &DnDVBox::drag_end), child));
@@ -220,6 +230,7 @@ public:
 	 *  Parameters are the source DnDVBox, our child which the other one was dropped on (or 0) and the DragContext.
 	 */
 	sigc::signal<void, DnDVBox*, T*, Glib::RefPtr<Gdk::DragContext> const & > DropFromAnotherBox;
+	sigc::signal<void, Gtk::SelectionData const &, T*, Glib::RefPtr<Gdk::DragContext> const & > DropFromExternal;
 	sigc::signal<void> SelectionChanged;
 
 private:
@@ -340,9 +351,11 @@ private:
 		return false;
 	}
 
-	void drag_data_get (Glib::RefPtr<Gdk::DragContext> const &, Gtk::SelectionData & selection_data, guint, guint, T* child)
+	void drag_data_get (Glib::RefPtr<Gdk::DragContext> const &context, Gtk::SelectionData & selection_data, guint, guint, T* child)
 	{
-		selection_data.set (selection_data.get_target(), 8, (const guchar *) &child, sizeof (&child));
+		if (!child->drag_data_get(context, selection_data)) {
+			selection_data.set (selection_data.get_target(), 8, (const guchar *) &child, sizeof (&child));
+		}
 	}
 
 	void drag_data_received (
@@ -352,6 +365,12 @@ private:
 		/* work out where it was dropped */
 		std::pair<T*, double> const drop = get_child_at_position (y);
 
+		if (selection_data.get_target () != _targets.front ().get_target ()) {
+			DropFromExternal (selection_data, drop.first, context);
+			context->drag_finish (false, false, time);
+			return;
+		}
+
 		if (_drag_source == this) {
 
 			/* dropped from ourselves onto ourselves */
diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
index 868f71f..acddbe7 100644
--- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
+++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
@@ -113,7 +113,7 @@ class LIBGTKMM2EXT_API UI : public AbstractUI<UIRequest>
 	MyReceiver _receiver;
 
   public:
-	UI (std::string name, int *argc, char **argv[]);
+	UI (std::string, std::string, int *argc, char **argv[]);
 	virtual ~UI ();
 
 	static UI *instance() { return theGtkUI; }
diff --git a/libs/gtkmm2ext/gtkmm2ext/keyboard.h b/libs/gtkmm2ext/gtkmm2ext/keyboard.h
index fca5d9f..4319c9a 100644
--- a/libs/gtkmm2ext/gtkmm2ext/keyboard.h
+++ b/libs/gtkmm2ext/gtkmm2ext/keyboard.h
@@ -70,8 +70,6 @@ class LIBGTKMM2EXT_API Keyboard : public sigc::trackable, PBD::Stateful
 	static const char* secondary_modifier_name ();
 	static const char* tertiary_modifier_name ();
 	static const char* level4_modifier_name ();
-	static const char* copy_modifier_name ();
-	static const char* rangeselect_modifier_name ();
 
 	static void set_primary_modifier (uint32_t newval) {
 		set_modifier (newval, PrimaryModifier);
diff --git a/libs/gtkmm2ext/gtkmm2ext/paths_dialog.h b/libs/gtkmm2ext/gtkmm2ext/paths_dialog.h
index 4f18511..120d037 100644
--- a/libs/gtkmm2ext/gtkmm2ext/paths_dialog.h
+++ b/libs/gtkmm2ext/gtkmm2ext/paths_dialog.h
@@ -30,7 +30,7 @@ namespace Gtkmm2ext {
 class LIBGTKMM2EXT_API PathsDialog : public Gtk::Dialog
 {
   public:
-	PathsDialog (std::string, std::string current_paths = "", std::string default_paths = "");
+	PathsDialog (Gtk::Window& parent, std::string, std::string current_paths = "", std::string default_paths = "");
 	~PathsDialog ();
 
 	std::string get_serialized_paths ();
diff --git a/libs/gtkmm2ext/gtkmm2ext/utils.h b/libs/gtkmm2ext/gtkmm2ext/utils.h
index 688f443..43baf59 100644
--- a/libs/gtkmm2ext/gtkmm2ext/utils.h
+++ b/libs/gtkmm2ext/gtkmm2ext/utils.h
@@ -28,6 +28,7 @@
 #include <pangomm/fontdescription.h>
 
 #include <gtkmm/container.h>
+#include <gtkmm/filechooser.h>
 #include <gtkmm/treeview.h>
 #include <gdkmm/window.h> /* for WMDecoration */
 #include <gdkmm/pixbuf.h>
@@ -170,6 +171,8 @@ namespace Gtkmm2ext {
 	 * use a std::string
 	 */
 	LIBGTKMM2EXT_API std::string markup_escape_text (std::string const& s);
+
+	LIBGTKMM2EXT_API void add_volume_shortcuts (Gtk::FileChooser& c);
 };
 
 #endif /*  __gtkmm2ext_utils_h__ */
diff --git a/libs/gtkmm2ext/keyboard.cc b/libs/gtkmm2ext/keyboard.cc
index c6a534d..37ca6db 100644
--- a/libs/gtkmm2ext/keyboard.cc
+++ b/libs/gtkmm2ext/keyboard.cc
@@ -70,8 +70,6 @@ const char* Keyboard::primary_modifier_name() { return _("Command"); }
 const char* Keyboard::secondary_modifier_name() { return _("Control"); }
 const char* Keyboard::tertiary_modifier_name() { return S_("Key|Shift"); }
 const char* Keyboard::level4_modifier_name() { return _("Option"); }
-const char* Keyboard::copy_modifier_name() { return _("Control"); }
-const char* Keyboard::rangeselect_modifier_name() { return S_("Key|Shift"); }
 
 guint Keyboard::snap_mod = Keyboard::Level4Modifier|Keyboard::TertiaryModifier; // XXX this is probably completely wrong
 guint Keyboard::snap_delta_mod = Keyboard::Level4Modifier;
@@ -89,9 +87,7 @@ guint Keyboard::button2_modifiers = 0; /* not used */
 const char* Keyboard::primary_modifier_name() { return _("Control"); }
 const char* Keyboard::secondary_modifier_name() { return _("Alt"); }
 const char* Keyboard::tertiary_modifier_name() { return S_("Key|Shift"); }
-const char* Keyboard::level4_modifier_name() { return _("Meta"); }
-const char* Keyboard::copy_modifier_name() { return _("Control"); }
-const char* Keyboard::rangeselect_modifier_name() { return S_("Key|Shift"); }
+const char* Keyboard::level4_modifier_name() { return _("Windows"); }
 
 guint Keyboard::snap_mod = Keyboard::SecondaryModifier;
 guint Keyboard::snap_delta_mod = Keyboard::SecondaryModifier|Keyboard::Level4Modifier;
diff --git a/libs/gtkmm2ext/motionfeedback.cc b/libs/gtkmm2ext/motionfeedback.cc
index 0c1a325..0dccdab 100644
--- a/libs/gtkmm2ext/motionfeedback.cc
+++ b/libs/gtkmm2ext/motionfeedback.cc
@@ -46,6 +46,7 @@ using namespace Gtkmm2ext;
 using namespace sigc;
 
 using PBD::error;
+using PBD::Controllable;
 
 Gdk::Color* MotionFeedback::base_color;
 
@@ -191,11 +192,11 @@ MotionFeedback::pixwin_button_release_event (GdkEventButton *ev)
 		}
                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                         /* shift click back to the default */
-                        _controllable->set_value (default_value);
+	                _controllable->set_value (default_value, Controllable::NoGroup);
                         return true;
                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 			/* ctrl click back to the minimum value */
-			_controllable->set_value (_controllable->lower ());
+	                _controllable->set_value (_controllable->lower (), Controllable::NoGroup);
 		}
 		break;
 
@@ -246,7 +247,7 @@ MotionFeedback::pixwin_motion_notify_event (GdkEventMotion *ev)
                 y_delta *= multiplier;
                 y_delta /= 10;
 
-                _controllable->set_value (adjust ((grab_is_fine ? step_inc : page_inc) * y_delta));
+                _controllable->set_value (adjust ((grab_is_fine ? step_inc : page_inc) * y_delta), Controllable::NoGroup);
 
         } else if (ev->state & Gdk::BUTTON2_MASK) {
 
@@ -263,7 +264,7 @@ MotionFeedback::pixwin_motion_notify_event (GdkEventMotion *ev)
                 angle = -(2.0/3.0) * (angle - 1.25);
                 angle *= multiplier;
 
-                _controllable->set_value (to_control_value (angle));
+                _controllable->set_value (to_control_value (angle), Controllable::NoGroup);
         }
 
 
@@ -301,32 +302,32 @@ MotionFeedback::pixwin_key_press_event (GdkEventKey *ev)
 	switch (ev->keyval) {
 	case GDK_Page_Up:
 	        retval = true;
-		_controllable->set_value (adjust (multiplier * page_inc));
+	        _controllable->set_value (adjust (multiplier * page_inc), Controllable::NoGroup);
 		break;
 
 	case GDK_Page_Down:
 	        retval = true;
-		_controllable->set_value (adjust (-multiplier * page_inc));
+	        _controllable->set_value (adjust (-multiplier * page_inc), Controllable::NoGroup);
 		break;
 
 	case GDK_Up:
 	        retval = true;
-		_controllable->set_value (adjust (multiplier * step_inc));
+	        _controllable->set_value (adjust (multiplier * step_inc), Controllable::NoGroup);
 		break;
 
 	case GDK_Down:
 	        retval = true;
-		_controllable->set_value (adjust (-multiplier * step_inc));
+	        _controllable->set_value (adjust (-multiplier * step_inc), Controllable::NoGroup);
 		break;
 
 	case GDK_Home:
 	        retval = true;
-		_controllable->set_value (_controllable->lower());
+	        _controllable->set_value (_controllable->lower(), Controllable::NoGroup);
 		break;
 
 	case GDK_End:
 	        retval = true;
-		_controllable->set_value (_controllable->upper());
+	        _controllable->set_value (_controllable->upper(), Controllable::NoGroup);
 		break;
 	}
 
@@ -406,12 +407,12 @@ MotionFeedback::pixwin_scroll_event (GdkEventScroll* ev)
 	switch (ev->direction) {
 	case GDK_SCROLL_UP:
 	case GDK_SCROLL_RIGHT:
-		_controllable->set_value (adjust (scale * page_inc));
+		_controllable->set_value (adjust (scale * page_inc), Controllable::NoGroup);
 		break;
 
 	case GDK_SCROLL_DOWN:
 	case GDK_SCROLL_LEFT:
-		_controllable->set_value (adjust (-scale * page_inc));
+		_controllable->set_value (adjust (-scale * page_inc), Controllable::NoGroup);
 		break;
 	}
 
diff --git a/libs/gtkmm2ext/paths_dialog.cc b/libs/gtkmm2ext/paths_dialog.cc
index 1f3a3b5..f169a5a 100644
--- a/libs/gtkmm2ext/paths_dialog.cc
+++ b/libs/gtkmm2ext/paths_dialog.cc
@@ -26,8 +26,8 @@ using namespace Gtk;
 using namespace std;
 using namespace Gtkmm2ext;
 
-PathsDialog::PathsDialog (std::string title, std::string current_paths, std::string default_paths)
-	: Dialog (title, true)
+PathsDialog::PathsDialog (Gtk::Window& parent, std::string title, std::string current_paths, std::string default_paths)
+	: Dialog (title, parent, true)
 	, paths_list_view(1, false, Gtk::SELECTION_SINGLE)
 	, add_path_button(_("Add"))
 	, remove_path_button(_("Delete"))
diff --git a/libs/gtkmm2ext/po/de.po b/libs/gtkmm2ext/po/de.po
index 18856e3..d3b6039 100644
--- a/libs/gtkmm2ext/po/de.po
+++ b/libs/gtkmm2ext/po/de.po
@@ -6,8 +6,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-03-18 16:48+0100\n"
-"PO-Revision-Date: 2015-01-18 11:41+0100\n"
+"POT-Creation-Date: 2015-11-11 15:37+0100\n"
+"PO-Revision-Date: 2015-12-09 12:33+0100\n"
 "Last-Translator: Edgar Aichinger <edogawa at aon.at>\n"
 "Language-Team: German <ardour-dev at lists.ardour.org>\n"
 "Language: de\n"
@@ -17,11 +17,7 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Lokalize 1.5\n"
 
-#: actions.cc:336
-msgid "programming error: %1"
-msgstr "Programmierfehler: %1"
-
-#: actions.cc:511
+#: actions.cc:519
 msgid "Unknown action name: %1"
 msgstr "Unbekannter Aktionsname: %1"
 
@@ -57,49 +53,49 @@ msgstr ""
 "\n"
 "Kurzbefehl: "
 
-#: gtk_ui.cc:638
+#: gtk_ui.cc:670
 msgid "Press To Exit"
 msgstr "Zum Beenden drücken"
 
-#: gtk_ui.cc:674
+#: gtk_ui.cc:706
 msgid "I'm sorry %1, I can't do that"
 msgstr "Leider kann ich das nicht tun, %1"
 
-#: keyboard.cc:73
+#: keyboard.cc:69
 msgid "Command"
 msgstr "Befehl"
 
-#: keyboard.cc:74 keyboard.cc:77 keyboard.cc:90 keyboard.cc:94
+#: keyboard.cc:70 keyboard.cc:87
 msgid "Control"
 msgstr "Strg"
 
-#: keyboard.cc:75 keyboard.cc:78 keyboard.cc:92 keyboard.cc:95
+#: keyboard.cc:71 keyboard.cc:89
 msgid "Key|Shift"
 msgstr "Key|Shift"
 
-#: keyboard.cc:76
+#: keyboard.cc:72
 msgid "Option"
 msgstr "Option"
 
-#: keyboard.cc:91
+#: keyboard.cc:88
 msgid "Alt"
 msgstr "Alt"
 
-#: keyboard.cc:93
-msgid "Meta"
-msgstr "Meta"
+#: keyboard.cc:90
+msgid "Windows"
+msgstr "Windows"
 
-#: keyboard.cc:144 keyboard.cc:540
+#: keyboard.cc:141 keyboard.cc:580
 msgid "Unknown"
 msgstr "Unbekannt"
 
-#: keyboard.cc:551
+#: keyboard.cc:591
 msgid "key bindings file not found at \"%2\" or contains errors."
 msgstr ""
 "Die Tastenkürzel-Datei \"%1\" konnte nicht gefunden werden oder enthält "
 "Fehler."
 
-#: keyboard.cc:602
+#: keyboard.cc:642
 msgid "Cannot rename your own keybinding file (%1)"
 msgstr "Kann Ihre eigene Tastaturkürzeldatei nicht umbenennen (%1)"
 
@@ -144,6 +140,6 @@ msgstr "Klicken, um in ein eigenes Fenster abzureißen"
 msgid "Click to put this back in the main window"
 msgstr "Klicken, um an das Hauptfenster anzudocken"
 
-#: textviewer.cc:34
+#: textviewer.cc:32
 msgid "Close"
 msgstr "Schließen"
diff --git a/libs/gtkmm2ext/utils.cc b/libs/gtkmm2ext/utils.cc
index 3762f88..a7790e6 100644
--- a/libs/gtkmm2ext/utils.cc
+++ b/libs/gtkmm2ext/utils.cc
@@ -973,3 +973,31 @@ Gtkmm2ext::markup_escape_text (std::string const& s)
 {
 	return Glib::Markup::escape_text (s);
 }
+
+void
+Gtkmm2ext::add_volume_shortcuts (Gtk::FileChooser& c)
+{
+#ifdef __APPLE__
+	try {
+		/* This is a first order approach, listing all mounted volumes (incl network).
+		 * One could use `diskutil` or `mount` to query local disks only, or
+		 * something even fancier if deemed appropriate.
+		 */
+		Glib::Dir dir("/Volumes");
+		for (Glib::DirIterator di = dir.begin(); di != dir.end(); di++) {
+			string fullpath = Glib::build_filename ("/Volumes", *di);
+			if (!Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR)) continue;
+
+			try { /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
+				c.add_shortcut_folder (fullpath);
+			}
+			catch (Glib::Error& e) {
+				std::cerr << "add_shortcut_folder() threw Glib::Error: " << e.what() << std::endl;
+			}
+		}
+	}
+	catch (Glib::FileError& e) {
+		std::cerr << "listing /Volumnes failed: " << e.what() << std::endl;
+	}
+#endif
+}
diff --git a/libs/gtkmm2ext/wscript b/libs/gtkmm2ext/wscript
index b7545c3..89614bd 100644
--- a/libs/gtkmm2ext/wscript
+++ b/libs/gtkmm2ext/wscript
@@ -84,7 +84,8 @@ def configure(conf):
 
 
 def build(bld):
-    sources = gtkmm2ext_sources
+    # operate on copy to avoid adding sources twice
+    sources = list(gtkmm2ext_sources)
     if bld.is_tracks_build():
         sources += [ 'waves_fastmeter.cc', 'fader.cc' ]
     else:
@@ -123,7 +124,7 @@ def build(bld):
             lang = os.path.basename(mo.srcpath()).replace('.mo', '')
             bld.install_as (os.path.join(os.path.normpath(bld.env['LOCALEDIR']), lang, 'LC_MESSAGES', I18N_PACKAGE + '.mo'),
                             mo)
-                           
+
 def i18n(bld):
     autowaf.build_i18n(bld, top, 'libs/gtkmm2ext', I18N_PACKAGE, gtkmm2ext_sources,
                        'Paul Davis')
diff --git a/libs/midi++2/channel.cc b/libs/midi++2/channel.cc
index b3cb42f..f296737 100644
--- a/libs/midi++2/channel.cc
+++ b/libs/midi++2/channel.cc
@@ -27,9 +27,14 @@ using namespace MIDI;
 
 Channel::Channel (MIDI::byte channelnum, Port &p)
 	: _port (p)
+	, _channel_number (channelnum)
+	, _rpn_msb (0)
+	, _rpn_lsb (0)
+	, _nrpn_msb (0)
+	, _nrpn_lsb (0)
+	, _rpn_state (RPNState (0))
+	, _nrpn_state (RPNState (0))
 {
-	_channel_number = channelnum;
-
 	reset (0, 1, false);
 }
 
@@ -75,10 +80,8 @@ Channel::reset (timestamp_t timestamp, framecnt_t /*nframes*/, bool notes_off)
 		_controller_14bit[n] = false;
 	}
 
-	_rpn_msb = 0;
-	_rpn_lsb = 0;
-	_nrpn_msb = 0;
-	_nrpn_lsb = 0;
+	rpn_reset ();
+	nrpn_reset ();
 
 	_omni = true;
 	_poly = false;
@@ -87,6 +90,26 @@ Channel::reset (timestamp_t timestamp, framecnt_t /*nframes*/, bool notes_off)
 }
 
 void
+Channel::rpn_reset ()
+{
+	_rpn_msb = 0;
+	_rpn_lsb = 0;
+	_rpn_val_msb = 0;
+	_rpn_val_lsb = 0;
+	_rpn_state = RPNState (0);
+}
+
+void
+Channel::nrpn_reset ()
+{
+	_nrpn_msb = 0;
+	_nrpn_lsb = 0;
+	_nrpn_val_msb = 0;
+	_nrpn_val_lsb = 0;
+	_nrpn_state = RPNState (0);
+}
+
+void
 Channel::process_note_off (Parser & /*parser*/, EventTwoBytes *tb)
 {
 	_last_note_off = tb->note_number;
@@ -105,8 +128,130 @@ Channel::process_note_on (Parser & /*parser*/, EventTwoBytes *tb)
 	_notes_on++;
 }
 
+const Channel::RPNState Channel::RPN_READY_FOR_VALUE = RPNState (HaveLSB|HaveMSB);
+const Channel::RPNState Channel::RPN_VALUE_READY = RPNState (HaveLSB|HaveMSB|HaveValue);
+
+bool
+Channel::maybe_process_rpns (Parser& parser, EventTwoBytes *tb)
+{
+	switch (tb->controller_number) {
+	case 0x62:
+		_rpn_state = RPNState (_rpn_state|HaveMSB);
+		_rpn_lsb = tb->value;
+		if (_rpn_msb == 0x7f && _rpn_lsb == 0x7f) {
+			rpn_reset ();
+		}
+		return true;
+	case 0x63:
+		_rpn_state = RPNState (_rpn_state|HaveLSB);
+		_rpn_msb = tb->value;
+		if (_rpn_msb == 0x7f && _rpn_lsb == 0x7f) {
+			rpn_reset ();
+		}
+		return true;
+
+	case 0x64:
+		_nrpn_state = RPNState (_rpn_state|HaveMSB);
+		_rpn_lsb = tb->value;
+		if (_nrpn_msb == 0x7f && _nrpn_lsb == 0x7f) {
+			nrpn_reset ();
+		}
+		return true;
+	case 0x65:
+		_nrpn_state = RPNState (_rpn_state|HaveLSB);
+		_rpn_msb = tb->value;
+		if (_rpn_msb == 0x7f && _rpn_lsb == 0x7f) {
+			nrpn_reset ();
+		}
+		return true;
+	}
+
+	if ((_nrpn_state & RPN_READY_FOR_VALUE) == RPN_READY_FOR_VALUE) {
+
+		uint16_t rpn_id = (_rpn_msb << 7)|_rpn_lsb;
+
+		switch (tb->controller_number) {
+		case 0x60:
+			/* data increment */
+			_nrpn_state = RPNState (_nrpn_state|HaveValue);
+			parser.channel_nrpn_change[_channel_number] (parser, rpn_id, 1); /* EMIT SIGNAL */
+			return true;
+		case 0x61:
+			/* data decrement */
+			_nrpn_state = RPNState (_nrpn_state|HaveValue);
+			parser.channel_nrpn_change[_channel_number] (parser, rpn_id, -1); /* EMIT SIGNAL */
+			return true;
+		case 0x06:
+			/* data entry MSB */
+			_nrpn_state = RPNState (_nrpn_state|HaveValue);
+			_nrpn_val_msb = tb->value;
+			break;
+		case 0x26:
+			/* data entry LSB */
+			_nrpn_state = RPNState (_nrpn_state|HaveValue);
+			_nrpn_val_lsb = tb->value;
+		}
+
+		if (_nrpn_state == RPN_VALUE_READY) {
+
+			float rpn_val = ((_rpn_val_msb << 7)|_rpn_val_lsb)/16384.0;
+
+			std::pair<RPNList::iterator,bool> result = nrpns.insert (std::make_pair (rpn_id, rpn_val));
+
+			if (!result.second) {
+				result.first->second = rpn_val;
+			}
+
+			parser.channel_nrpn[_channel_number] (parser, rpn_id, rpn_val); /* EMIT SIGNAL */
+			return true;
+		}
+
+	} else if ((_rpn_state & RPN_READY_FOR_VALUE) == RPN_READY_FOR_VALUE) {
+
+		uint16_t rpn_id = (_rpn_msb << 7)|_rpn_lsb;
+
+		switch (tb->controller_number) {
+		case 0x60:
+			/* data increment */
+			_rpn_state = RPNState (_rpn_state|HaveValue);
+			parser.channel_rpn_change[_channel_number] (parser, rpn_id, 1); /* EMIT SIGNAL */
+			return true;
+		case 0x61:
+			/* data decrement */
+			_rpn_state = RPNState (_rpn_state|HaveValue);
+			parser.channel_rpn_change[_channel_number] (parser, rpn_id, -1); /* EMIT SIGNAL */
+			return true;
+		case 0x06:
+			/* data entry MSB */
+			_rpn_state = RPNState (_rpn_state|HaveValue);
+			_rpn_val_msb = tb->value;
+			break;
+		case 0x26:
+			/* data entry LSB */
+			_rpn_state = RPNState (_rpn_state|HaveValue);
+			_rpn_val_lsb = tb->value;
+		}
+
+		if (_rpn_state == RPN_VALUE_READY) {
+
+			float    rpn_val = ((_rpn_val_msb << 7)|_rpn_val_lsb)/16384.0;
+
+			std::pair<RPNList::iterator,bool> result = rpns.insert (std::make_pair (rpn_id, rpn_val));
+
+			if (!result.second) {
+				result.first->second = rpn_val;
+			}
+
+			parser.channel_rpn[_channel_number] (parser, rpn_id, rpn_val); /* EMIT SIGNAL */
+			return true;
+		}
+	}
+
+	return false;
+}
+
 void
-Channel::process_controller (Parser & /*parser*/, EventTwoBytes *tb)
+Channel::process_controller (Parser & parser, EventTwoBytes *tb)
 {
 	unsigned short cv;
 
@@ -115,6 +260,16 @@ Channel::process_controller (Parser & /*parser*/, EventTwoBytes *tb)
 	   all changes *are* atomic.
 	*/
 
+	if (maybe_process_rpns (parser, tb)) {
+		return;
+	}
+
+	/* Note: if RPN data controllers (0x60, 0x61, 0x6, 0x26) are received
+	 * without a previous RPN parameter ID message, or after the RPN ID
+	 * has been reset, they will be treated like ordinary CC messages.
+	 */
+
+
 	if (tb->controller_number < 32) { /* unsigned: no test for >= 0 */
 
 		/* if this controller is already known to use 14 bits,
@@ -272,3 +427,35 @@ Channel::channel_msg (MIDI::byte id, MIDI::byte val1, MIDI::byte val2, timestamp
 
 	return _port.midimsg (msg, len, timestamp);
 }
+
+float
+Channel::rpn_value (uint16_t rpn) const
+{
+	return rpn_value_absolute (rpn) / 16384.0f;
+}
+
+float
+Channel::rpn_value_absolute (uint16_t rpn) const
+{
+	RPNList::const_iterator r = rpns.find (rpn);
+	if (r == rpns.end()) {
+		return 0.0;
+	}
+	return r->second;
+}
+
+float
+Channel::nrpn_value (uint16_t nrpn) const
+{
+	return nrpn_value_absolute (nrpn) / 16384.0f;
+}
+
+float
+Channel::nrpn_value_absolute (uint16_t nrpn) const
+{
+	RPNList::const_iterator r = nrpns.find (nrpn);
+	if (r == nrpns.end()) {
+		return 0.0;
+	}
+	return r->second;
+}
diff --git a/libs/midi++2/ipmidi_port.cc b/libs/midi++2/ipmidi_port.cc
index ace51ea..0210935 100644
--- a/libs/midi++2/ipmidi_port.cc
+++ b/libs/midi++2/ipmidi_port.cc
@@ -31,12 +31,12 @@
 #endif
 #if defined(PLATFORM_WINDOWS)
 #include <winsock2.h>
+#include <ws2tcpip.h>
 #else
 #include <netdb.h>
 #endif
 
 #if defined(PLATFORM_WINDOWS)
-static WSADATA g_wsaData;
 typedef int socklen_t;
 #else
 #include <unistd.h>
@@ -112,12 +112,12 @@ IPMIDIPort::close_sockets ()
 	}
 }
 
+#ifndef PLATFORM_WINDOWS
 static bool
 get_address (int sock, struct in_addr *inaddr, const string& ifname )
 {
 	// Get interface address from supplied name.
 
-#if !defined(PLATFORM_WINDOWS)
 	struct ifreq ifr;
 	::strncpy(ifr.ifr_name, ifname.c_str(), sizeof(ifr.ifr_name));
 
@@ -141,18 +141,12 @@ get_address (int sock, struct in_addr *inaddr, const string& ifname )
 	inaddr->s_addr = sa.sin_addr.s_addr;
 
 	return true;
-
-#else
-
-	return false;
-
-#endif	// !PLATFORM_WINDOWS'
 }
+#endif
 
 bool
 IPMIDIPort::open_sockets (int base_port, const string& ifname)
 {
-#if !defined(PLATFORM_WINDOWS)
 	int protonum = 0;
 	struct protoent *proto = ::getprotobyname("IP");
 
@@ -181,6 +175,7 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname)
 	// INADDR_ANY will bind to default interface,
 	// specify alternate interface nameon which to bind...
 	struct in_addr if_addr_in;
+#ifndef PLATFORM_WINDOWS
 	if (!ifname.empty()) {
 		if (!get_address(sockin, &if_addr_in, ifname)) {
 			error << string_compose ("socket(in): could not find interface address for %1", ifname) << endmsg;
@@ -194,6 +189,9 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname)
 	} else {
 		if_addr_in.s_addr = htonl (INADDR_ANY);
 	}
+#else
+	if_addr_in.s_addr = htonl (INADDR_ANY);
+#endif
 
 	struct ip_mreq mreq;
 	mreq.imr_multiaddr.s_addr = ::inet_addr("225.0.0.37");
@@ -214,6 +212,7 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname)
 	}
 
 	// Will Hall, Oct 2007
+#ifndef PLATFORM_WINDOWS
 	if (!ifname.empty()) {
 		struct in_addr if_addr_out;
 		if (!get_address(sockout, &if_addr_out, ifname)) {
@@ -225,6 +224,7 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname)
 			return false;
 		}
 	}
+#endif
 
 	::memset(&addrout, 0, sizeof(struct sockaddr_in));
 	addrout.sin_family = AF_INET;
@@ -238,6 +238,8 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname)
 		return false;
 	}
 
+#ifndef PLATFORM_WINDOWS
+
 	if (fcntl (sockin, F_SETFL, O_NONBLOCK)) {
 		error << "cannot set non-blocking mode for IP MIDI input socket (" << ::strerror (errno) << ')' << endmsg;
 		return false;
@@ -248,10 +250,21 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname)
 		return false;
 	}
 
-	return true;
 #else
-	return false;
-#endif	// !PLATFORM_WINDOWS'
+	// If imode !=0, non-blocking mode is enabled.
+	u_long mode=1;
+	if (ioctlsocket(sockin,FIONBIO,&mode)) {
+		error << "cannot set non-blocking mode for IP MIDI input socket (" << ::strerror (errno) << ')' << endmsg;
+		return false;
+	}
+	mode = 1; /* just in case it was modified in the previous call */
+	if (ioctlsocket(sockout,FIONBIO,&mode)) {
+		error << "cannot set non-blocking mode for IP MIDI output socket (" << ::strerror (errno) << ')' << endmsg;
+		return false;
+	}
+#endif
+
+	return true;
 }
 
 int
@@ -299,4 +312,3 @@ IPMIDIPort::parse (framecnt_t timestamp)
 		::perror ("failed to recv from socket");
 	}
 }
-
diff --git a/libs/midi++2/midi++/channel.h b/libs/midi++2/midi++/channel.h
index 6f49282..6bd0807 100644
--- a/libs/midi++2/midi++/channel.h
+++ b/libs/midi++2/midi++/channel.h
@@ -21,6 +21,7 @@
 #define __midichannel_h__
 
 #include <queue>
+#include <map>
 
 #include "pbd/signals.h"
 #include "midi++/parser.h"
@@ -75,6 +76,9 @@ class LIBMIDIPP_API Channel : public PBD::ScopedConnectionList {
 		_controller_val[n%128] = val;
 	}
 
+	controller_value_t rpn_value (uint16_t rpn_id);
+	controller_value_t nrpn_value (uint16_t rpn_id);
+
 	bool channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp);
 	bool all_notes_off (timestamp_t timestamp) {
 		return channel_msg (MIDI::controller, 123, 0, timestamp);
@@ -108,6 +112,11 @@ class LIBMIDIPP_API Channel : public PBD::ScopedConnectionList {
 		return channel_msg (MIDI::pitchbend, lsb, msb, timestamp);
 	}
 
+	float rpn_value (uint16_t rpn) const;
+	float nrpn_value (uint16_t nrpn) const;
+	float rpn_value_absolute (uint16_t rpn) const;
+	float nrpn_value_absolute (uint16_t nrpn) const;
+
   protected:
 	friend class Port;
 	void connect_signals ();
@@ -115,14 +124,26 @@ class LIBMIDIPP_API Channel : public PBD::ScopedConnectionList {
   private:
 	Port& _port;
 
+	enum RPNState {
+		HaveLSB = 0x1,
+		HaveMSB = 0x2,
+		HaveValue = 0x4
+	};
+
 	/* Current channel values */
 	byte               _channel_number;
 	unsigned short     _bank_number;
 	byte               _program_number;
 	byte               _rpn_msb;
 	byte               _rpn_lsb;
+	byte               _rpn_val_msb;
+	byte               _rpn_val_lsb;
 	byte               _nrpn_msb;
 	byte               _nrpn_lsb;
+	byte               _nrpn_val_lsb;
+	byte               _nrpn_val_msb;
+	RPNState           _rpn_state;
+	RPNState           _nrpn_state;
 	byte               _chanpress;
 	byte               _polypress[128];
 	bool               _controller_14bit[128];
@@ -139,6 +160,11 @@ class LIBMIDIPP_API Channel : public PBD::ScopedConnectionList {
 	bool               _mono;
 	size_t             _notes_on;
 
+	typedef std::map<uint16_t,float> RPNList;
+
+	RPNList rpns;
+	RPNList nrpns;
+
 	void reset (timestamp_t timestamp, framecnt_t nframes, bool notes_off = true);
 
 	void process_note_off (Parser &, EventTwoBytes *);
@@ -149,6 +175,14 @@ class LIBMIDIPP_API Channel : public PBD::ScopedConnectionList {
 	void process_chanpress (Parser &, byte);
 	void process_pitchbend (Parser &, pitchbend_t);
 	void process_reset (Parser &);
+	bool maybe_process_rpns (Parser&, EventTwoBytes *);
+
+	void rpn_reset ();
+	void nrpn_reset ();
+
+	static const RPNState RPN_READY_FOR_VALUE;
+	static const RPNState RPN_VALUE_READY;
+
 };
 
 } // namespace MIDI
diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h
index e252e76..683f52f 100644
--- a/libs/midi++2/midi++/midnam_patch.h
+++ b/libs/midi++2/midi++/midnam_patch.h
@@ -465,9 +465,11 @@ public:
 	typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
 
 	MIDINameDocument() {}
-	MIDINameDocument(const std::string& filename);
+	MIDINameDocument(const std::string& file_path);
 	virtual ~MIDINameDocument() {};
 
+	const std::string& file_path () const { return _file_path; }
+
 	const std::string& author() const { return _author; }
 	void set_author(const std::string& author) { _author = author; }
 
@@ -481,6 +483,7 @@ public:
 	int      set_state (const XMLTree&, const XMLNode&);
 
 private:
+	const std::string             _file_path;
 	std::string                   _author;
 	MasterDeviceNamesList         _master_device_names_list;
 	MasterDeviceNames::Models     _all_models;
diff --git a/libs/midi++2/midi++/parser.h b/libs/midi++2/midi++/parser.h
index 0f2ecf4..7040e9b 100644
--- a/libs/midi++2/midi++/parser.h
+++ b/libs/midi++2/midi++/parser.h
@@ -39,6 +39,8 @@ typedef PBD::Signal2<void,Parser&,framecnt_t>        TimestampedSignal;
 typedef PBD::Signal2<void,Parser&, byte>             OneByteSignal;
 typedef PBD::Signal2<void,Parser &, EventTwoBytes *> TwoByteSignal;
 typedef PBD::Signal2<void,Parser &, pitchbend_t>     PitchBendSignal;
+typedef PBD::Signal3<void,Parser &, uint16_t, int>   RPNSignal;
+typedef PBD::Signal3<void,Parser &, uint16_t, float> RPNValueSignal;
 typedef PBD::Signal3<void,Parser &, byte *, size_t>  Signal;
 
 class LIBMIDIPP_API Parser {
@@ -75,6 +77,10 @@ class LIBMIDIPP_API Parser {
 	TwoByteSignal         channel_controller[16];
 	ZeroByteSignal        channel_active_preparse[16];
 	ZeroByteSignal        channel_active_postparse[16];
+	RPNValueSignal        channel_rpn[16];
+	RPNValueSignal        channel_nrpn[16];
+	RPNSignal             channel_rpn_change[16];
+	RPNSignal             channel_nrpn_change[16];
 
 	OneByteSignal         mtc_quarter_frame; /* see below for more useful signals */
 	Signal                mtc;
diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc
index 2205e5e..cb1e285 100644
--- a/libs/midi++2/midnam_patch.cc
+++ b/libs/midi++2/midnam_patch.cc
@@ -877,14 +877,15 @@ MasterDeviceNames::get_state(void)
 	return nothing;
 }
 
-MIDINameDocument::MIDINameDocument (const string& filename)
+MIDINameDocument::MIDINameDocument (const string& file_path)
+	: _file_path(file_path)
 {
 	XMLTree document;
-	if (!document.read (filename)) {
+	if (!document.read (file_path)) {
 		throw failed_constructor ();
 	}
 
-	document.set_filename (filename);
+	document.set_filename (file_path);
 	set_state (document, *document.root());
 }
 
diff --git a/libs/midi++2/parser.cc b/libs/midi++2/parser.cc
index e11094d..fcee844 100644
--- a/libs/midi++2/parser.cc
+++ b/libs/midi++2/parser.cc
@@ -174,7 +174,7 @@ Parser::trace_event (Parser &, MIDI::byte *msg, size_t len)
 		*o << trace_prefix
 		   << "Channel "
 		   << (msg[0]&0xF)+1
-		   << " PolyPressure"
+		   << " PolyPressure "
 		   << (int) msg[1]
 		   << endmsg;
 		break;
diff --git a/libs/midi++2/run-tests.sh b/libs/midi++2/run-tests.sh
index 8b4666c..7cc9441 100755
--- a/libs/midi++2/run-tests.sh
+++ b/libs/midi++2/run-tests.sh
@@ -9,7 +9,7 @@ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$LIBS_DIR/midi++:$LIBS_DIR/pbd:$LIBS_DIR
 export MIDIPP_TEST_PATH=$TOP/patchfiles
 
 cd $LIBS_DIR/midi++2
-if [ "$1" == "debug" ]; then 
+if [ "$1" = "debug" ]; then
 	gdb ./run-tests
 else
 	./run-tests
diff --git a/libs/midi++2/wscript b/libs/midi++2/wscript
index 9592e31..10a3746 100644
--- a/libs/midi++2/wscript
+++ b/libs/midi++2/wscript
@@ -74,7 +74,7 @@ def build(bld):
     obj.vnum         = LIBMIDIPP_LIB_VERSION
     obj.install_path = bld.env['LIBDIR']
 
-    if bld.env['BUILD_TESTS'] and bld.is_defined('HAVE_CPPUNIT'): 
+    if bld.env['BUILD_TESTS'] and bld.is_defined('HAVE_CPPUNIT'):
         # Unit tests
         obj              = bld(features = 'cxx cxxprogram')
         obj.source       = '''
diff --git a/libs/panners/1in2out/panner_1in2out.cc b/libs/panners/1in2out/panner_1in2out.cc
index 022f4d6..b522d65 100644
--- a/libs/panners/1in2out/panner_1in2out.cc
+++ b/libs/panners/1in2out/panner_1in2out.cc
@@ -76,7 +76,7 @@ Panner1in2out::Panner1in2out (boost::shared_ptr<Pannable> p)
 {
         if (!Profile->get_trx () ) {
             if (!_pannable->has_state ()) {
-                _pannable->pan_azimuth_control->set_value (0.5);
+	            _pannable->pan_azimuth_control->set_value (0.5, Controllable::NoGroup);
             }
         }
 
@@ -112,7 +112,7 @@ void
 Panner1in2out::set_position (double p)
 {
         if (clamp_position (p)) {
-                _pannable->pan_azimuth_control->set_value (p);
+	        _pannable->pan_azimuth_control->set_value (p, Controllable::NoGroup);
         }
 }
 
diff --git a/libs/panners/2in2out/panner_2in2out.cc b/libs/panners/2in2out/panner_2in2out.cc
index 611f13d..d8a7428 100644
--- a/libs/panners/2in2out/panner_2in2out.cc
+++ b/libs/panners/2in2out/panner_2in2out.cc
@@ -74,8 +74,8 @@ Panner2in2out::Panner2in2out (boost::shared_ptr<Pannable> p)
 	: Panner (p)
 {
         if (!_pannable->has_state()) {
-                _pannable->pan_azimuth_control->set_value (0.5);
-                _pannable->pan_width_control->set_value (1.0);
+	        _pannable->pan_azimuth_control->set_value (0.5, Controllable::NoGroup);
+	        _pannable->pan_width_control->set_value (1.0, Controllable::NoGroup);
         }
 
         double const w = width();
@@ -119,7 +119,7 @@ void
 Panner2in2out::set_position (double p)
 {
         if (clamp_position (p)) {
-                _pannable->pan_azimuth_control->set_value (p);
+	        _pannable->pan_azimuth_control->set_value (p, Controllable::NoGroup);
         }
 }
 
@@ -127,7 +127,7 @@ void
 Panner2in2out::set_width (double p)
 {
         if (clamp_width (p)) {
-                _pannable->pan_width_control->set_value (p);
+	        _pannable->pan_width_control->set_value (p, Controllable::NoGroup);
         }
 }
 
diff --git a/libs/panners/stereobalance/panner_balance.cc b/libs/panners/stereobalance/panner_balance.cc
index 281ea4b..b2efb0f 100644
--- a/libs/panners/stereobalance/panner_balance.cc
+++ b/libs/panners/stereobalance/panner_balance.cc
@@ -75,7 +75,7 @@ Pannerbalance::Pannerbalance (boost::shared_ptr<Pannable> p)
 	: Panner (p)
 {
 	if (!_pannable->has_state()) {
-		_pannable->pan_azimuth_control->set_value (0.5);
+		_pannable->pan_azimuth_control->set_value (0.5, Controllable::NoGroup);
 	}
 
 	update ();
@@ -102,7 +102,7 @@ Pannerbalance::position () const
 Pannerbalance::set_position (double p)
 {
 	if (clamp_position (p)) {
-		_pannable->pan_azimuth_control->set_value (p);
+		_pannable->pan_azimuth_control->set_value (p, Controllable::NoGroup);
 	}
 }
 
diff --git a/libs/panners/vbap/vbap.cc b/libs/panners/vbap/vbap.cc
index f890b50..df34ddd 100644
--- a/libs/panners/vbap/vbap.cc
+++ b/libs/panners/vbap/vbap.cc
@@ -463,19 +463,19 @@ VBAPanner::set_position (double p)
 	int over = p;
 	over -= (p >= 0) ? 0 : 1;
 	p -= (double)over;
-	_pannable->pan_azimuth_control->set_value (p);
+	_pannable->pan_azimuth_control->set_value (p, Controllable::NoGroup);
 }
 
 void
 VBAPanner::set_width (double w)
 {
-        _pannable->pan_width_control->set_value (min (1.0, max (-1.0, w)));
+	_pannable->pan_width_control->set_value (min (1.0, max (-1.0, w)), Controllable::NoGroup);
 }
 
 void
 VBAPanner::set_elevation (double e)
 {
-        _pannable->pan_elevation_control->set_value (min (1.0, max (0.0, e)));
+	_pannable->pan_elevation_control->set_value (min (1.0, max (0.0, e)), Controllable::NoGroup);
 }
 
 void
diff --git a/libs/panners/wscript b/libs/panners/wscript
index feedfa3..3ee237f 100644
--- a/libs/panners/wscript
+++ b/libs/panners/wscript
@@ -9,7 +9,7 @@ out = 'build'
 
 
 def options(opt):
-    
+
     autowaf.set_options(opt)
 
 def sub_config_and_use(conf, name, has_objects = True):
diff --git a/libs/pbd/MSVCpbd/pbd.vcproj b/libs/pbd/MSVCpbd/pbd.vcproj
index b86cb97..490090d 100644
--- a/libs/pbd/MSVCpbd/pbd.vcproj
+++ b/libs/pbd/MSVCpbd/pbd.vcproj
@@ -315,6 +315,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\demangle.cc"
+				>
+			</File>
+			<File
 				RelativePath="..\enums.cc"
 				>
 			</File>
@@ -347,10 +351,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\glib_semaphore.cc"
-				>
-			</File>
-			<File
 				RelativePath="..\id.cc"
 				>
 			</File>
@@ -677,10 +677,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\pbd\glib_semaphore.h"
-				>
-			</File>
-			<File
 				RelativePath="..\pbd\libpbd_visibility.h"
 				>
 			</File>
@@ -757,10 +753,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\pbd\semaphore.h"
-				>
-			</File>
-			<File
 				RelativePath="..\pbd\semutils.h"
 				>
 			</File>
diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc
index 09dfa74..c56fb8f 100644
--- a/libs/pbd/base_ui.cc
+++ b/libs/pbd/base_ui.cc
@@ -47,10 +47,10 @@ uint64_t BaseUI::rt_bit = 1;
 BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
 BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type();
 
-BaseUI::BaseUI (const string& str)
-	: m_context(MainContext::get_default())
+BaseUI::BaseUI (const string& loop_name)
+	: EventLoop (loop_name)
+	, m_context(MainContext::get_default())
 	, run_loop_thread (0)
-	, _name (str)
 	, request_channel (true)
 {
 	base_ui_instance = this;
@@ -79,7 +79,7 @@ BaseUI::new_request_type ()
 void
 BaseUI::main_thread ()
 {
-	DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", name(), pthread_name()));
+	DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", event_loop_name(), pthread_name()));
 	set_event_loop_for_thread (this);
 	thread_init ();
 	_main_loop->get_context()->signal_idle().connect (sigc::mem_fun (*this, &BaseUI::signal_running));
diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc
index 17b8133..58ae731 100644
--- a/libs/pbd/controllable.cc
+++ b/libs/pbd/controllable.cc
@@ -143,7 +143,7 @@ Controllable::set_state (const XMLNode& node, int /*version*/)
 		float val;
 
 		if (sscanf (prop->value().c_str(), "%f", &val) == 1) {
-			set_value (val);
+			set_value (val, NoGroup);
 		}
         }
 
diff --git a/libs/pbd/demangle.cc b/libs/pbd/demangle.cc
new file mode 100644
index 0000000..97d4e11
--- /dev/null
+++ b/libs/pbd/demangle.cc
@@ -0,0 +1,72 @@
+/*
+    Copyright (C) 2000-2007 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "pbd/demangle.h"
+
+#if defined(__GLIBCXX__)
+#include <cxxabi.h>
+#endif
+
+std::string
+PBD::demangle_symbol (const std::string& mangled_symbol)
+{
+#if defined(__GLIBCXX__)
+	int status;
+
+	try {
+
+		char* realname = abi::__cxa_demangle (mangled_symbol.c_str(), 0, 0, &status);
+		std::string demangled_symbol (realname);
+		free (realname);
+		return demangled_symbol;
+	} catch (std::exception) {
+
+	}
+#endif
+
+	/* Note: on win32, you can use UnDecorateSymbolName.
+	   See http://msdn.microsoft.com/en-us/library/ms681400%28VS.85%29.aspx
+	   See also: http://msdn.microsoft.com/en-us/library/ms680344%28VS.85%29.aspx
+	*/
+
+	return mangled_symbol;
+}
+
+std::string
+PBD::demangle (std::string const& str)
+{
+	std::string::size_type const b = str.find_first_of ("(");
+
+	if (b == std::string::npos) {
+		return demangle_symbol (str);
+	}
+
+	std::string::size_type const p = str.find_last_of ("+");
+	if (p == std::string::npos) {
+		return demangle_symbol (str);
+	}
+
+	if ((p - b) <= 1) {
+		return demangle_symbol (str);
+	}
+
+	std::string const symbol = str.substr (b + 1, p - b - 1);
+
+	return demangle_symbol (symbol);
+}
diff --git a/libs/pbd/event_loop.cc b/libs/pbd/event_loop.cc
index d3f2fe5..671e26b 100644
--- a/libs/pbd/event_loop.cc
+++ b/libs/pbd/event_loop.cc
@@ -17,9 +17,13 @@
 
 */
 
+#include "pbd/compose.h"
 #include "pbd/event_loop.h"
+#include "pbd/error.h"
 #include "pbd/stacktrace.h"
 
+#include "i18n.h"
+
 using namespace PBD;
 using namespace std;
 
@@ -27,8 +31,18 @@ static void do_not_delete_the_loop_pointer (void*) { }
 
 Glib::Threads::Private<EventLoop> EventLoop::thread_event_loop (do_not_delete_the_loop_pointer);
 
+Glib::Threads::RWLock EventLoop::thread_buffer_requests_lock;
+EventLoop::ThreadRequestBufferList EventLoop::thread_buffer_requests;
+EventLoop::RequestBufferSuppliers EventLoop::request_buffer_suppliers;
+
+EventLoop::EventLoop (string const& name)
+	: _name (name)
+{
+}
+
 EventLoop*
-EventLoop::get_event_loop_for_thread() {
+EventLoop::get_event_loop_for_thread()
+{
 	return thread_event_loop.get ();
 }
 
@@ -79,3 +93,98 @@ EventLoop::invalidate_request (void* data)
         return 0;
 }
 
+vector<EventLoop::ThreadBufferMapping>
+EventLoop::get_request_buffers_for_target_thread (const std::string& target_thread)
+{
+	vector<ThreadBufferMapping> ret;
+	Glib::Threads::RWLock::WriterLock lm (thread_buffer_requests_lock);
+
+	for (ThreadRequestBufferList::const_iterator x = thread_buffer_requests.begin();
+	     x != thread_buffer_requests.end(); ++x) {
+
+		if (x->second.target_thread_name == target_thread) {
+			ret.push_back (x->second);
+		}
+	}
+
+	return ret;
+}
+
+void
+EventLoop::register_request_buffer_factory (const string& target_thread_name,
+                                            void* (*factory)(uint32_t))
+{
+
+	RequestBufferSupplier trs;
+	trs.name = target_thread_name;
+	trs.factory = factory;
+
+	{
+		Glib::Threads::RWLock::WriterLock lm (thread_buffer_requests_lock);
+		request_buffer_suppliers.push_back (trs);
+	}
+}
+
+void
+EventLoop::pre_register (const string& emitting_thread_name, uint32_t num_requests)
+{
+	/* Threads that need to emit signals "towards" other threads, but with
+	   RT safe behavior may be created before the receiving threads
+	   exist. This makes it impossible for them to use the
+	   ThreadCreatedWithRequestSize signal to notify receiving threads of
+	   their existence.
+
+	   This function creates a request buffer for them to use with
+	   the (not yet) created threads, and stores it where the receiving
+	   thread can find it later.
+	 */
+
+	ThreadBufferMapping mapping;
+	Glib::Threads::RWLock::ReaderLock lm (thread_buffer_requests_lock);
+
+	for (RequestBufferSuppliers::iterator trs = request_buffer_suppliers.begin(); trs != request_buffer_suppliers.end(); ++trs) {
+
+		if (!trs->factory) {
+			/* no factory - no request buffer required or expected */
+			continue;
+		}
+
+		if (emitting_thread_name == trs->name) {
+			/* no need to register an emitter with itself */
+			continue;
+		}
+
+		mapping.emitting_thread = pthread_self();
+		mapping.target_thread_name = trs->name;
+
+		/* Allocate a suitably sized request buffer. This will set the
+		 * thread-local variable that holds a pointer to this request
+		 * buffer.
+		 */
+		mapping.request_buffer = trs->factory (num_requests);
+
+		/* now store it where the receiving thread (trs->name) can find
+		   it if and when it is created. (Discovery happens in the
+		   AbstractUI constructor. Note that if
+		*/
+
+		/* make a key composed of the emitter and receiver thread names */
+
+		string key = emitting_thread_name;
+		key += '/';
+		key +=  mapping.target_thread_name;
+
+		/* if the emitting thread was killed and recreated (with the
+		 * same name), this will replace the entry in
+		 * thread_buffer_requests. The old entry will be lazily deleted
+		 * when the target thread finds the request buffer and realizes
+		 * that it is dead.
+		 *
+		 * If the request buffer is replaced before the target thread
+		 * ever finds the dead version, we will leak the old request
+		 * buffer.
+		 */
+
+		thread_buffer_requests[key] = mapping;
+	}
+}
diff --git a/libs/pbd/file_utils.cc b/libs/pbd/file_utils.cc
index 1f72ce2..6cf43f3 100644
--- a/libs/pbd/file_utils.cc
+++ b/libs/pbd/file_utils.cc
@@ -440,29 +440,31 @@ remove_directory_internal (const string& dir, size_t* size, vector<string>* path
 	get_paths (tmp_paths, dir, just_remove_files, true);
 
 	for (vector<string>::const_iterator i = tmp_paths.begin();
-	     i != tmp_paths.end(); ++i) {
+			i != tmp_paths.end(); ++i) {
 
-                if (g_stat (i->c_str(), &statbuf)) {
+		if (g_stat (i->c_str(), &statbuf)) {
 			continue;
 		}
 
-                if (::g_remove (i->c_str())) {
-                        error << string_compose (_("cannot remove path %1 (%2)"), *i, strerror (errno))
-                              << endmsg;
-                        ret = 1;
-                }
+		if (::g_remove (i->c_str())) {
+			error << string_compose (_("cannot remove path %1 (%2)"), *i, strerror (errno))
+				<< endmsg;
+			ret = 1;
+			continue;
+		}
 
-                if (paths) {
-                        paths->push_back (Glib::path_get_basename(*i));
-                }
+		if (paths) {
+			paths->push_back (Glib::path_get_basename(*i));
+		}
 
-                if (size) {
-                        *size += statbuf.st_size;
-                }
+		// statbuf.st_size is off_t
+		if (size && statbuf.st_size > 0) {
+			*size += statbuf.st_size;
+		}
 
 	}
 
-        return ret;
+	return ret;
 }
 
 int
diff --git a/libs/pbd/glib_semaphore.cc b/libs/pbd/glib_semaphore.cc
deleted file mode 100644
index 7565e0c..0000000
--- a/libs/pbd/glib_semaphore.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-    Copyright (C) 2010 Tim Mayberry
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "pbd/glib_semaphore.h"
-
-namespace PBD {
-
-GlibSemaphore::GlibSemaphore (gint initial_val)
-	:
-		m_counter(initial_val)
-{ }
-
-void
-GlibSemaphore::wait ()
-{
-	Glib::Threads::Mutex::Lock guard (m_mutex);
-
-	while (m_counter.get() < 1) {
-		m_cond.wait(m_mutex);
-	}
-
-	// this shouldn't need to be inside the lock
-	--m_counter;
-}
-
-bool
-GlibSemaphore::try_wait ()
-{
-	if (!m_mutex.trylock())
-	{
-		return false;
-	}
-	// lock successful
-	while (m_counter.get() < 1) {
-		m_cond.wait(m_mutex);
-	}
-
-	// the order of these should not matter
-	--m_counter;
-	m_mutex.unlock();
-	return true;
-}
-
-void
-GlibSemaphore::post ()
-{
-	// atomic, no locking required
-	++m_counter;
-	m_cond.signal();
-}
-
-} // namespace PBD
diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
index 323435b..116a827 100644
--- a/libs/pbd/pbd/abstract_ui.cc
+++ b/libs/pbd/pbd/abstract_ui.cc
@@ -14,7 +14,6 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
 */
 
 #include <unistd.h>
@@ -42,7 +41,7 @@ using namespace std;
 template<typename RequestBuffer> void
 cleanup_request_buffer (void* ptr)
 {
-        RequestBuffer* rb = (RequestBuffer*) ptr;
+	RequestBuffer* rb = (RequestBuffer*) ptr;
 
 	/* this is called when the thread for which this request buffer was
 	 * allocated dies. That could be before or after the end of the UI
@@ -65,17 +64,28 @@ template <typename RequestObject>
 AbstractUI<RequestObject>::AbstractUI (const string& name)
 	: BaseUI (name)
 {
-	void (AbstractUI<RequestObject>::*pmf)(string,pthread_t,string,uint32_t) = &AbstractUI<RequestObject>::register_thread;
+	void (AbstractUI<RequestObject>::*pmf)(pthread_t,string,uint32_t) = &AbstractUI<RequestObject>::register_thread;
 
 	/* better to make this connect a handler that runs in the UI event loop but the syntax seems hard, and
 	   register_thread() is thread safe anyway.
 	*/
 
-	PBD::ThreadCreatedWithRequestSize.connect_same_thread (new_thread_connection, boost::bind (pmf, this, _1, _2, _3, _4));
+	PBD::ThreadCreatedWithRequestSize.connect_same_thread (new_thread_connection, boost::bind (pmf, this, _1, _2, _3));
+
+	/* find pre-registerer threads */
+
+	vector<EventLoop::ThreadBufferMapping> tbm = EventLoop::get_request_buffers_for_target_thread (event_loop_name());
+
+	{
+		Glib::Threads::Mutex::Lock lm (request_buffer_map_lock);
+		for (vector<EventLoop::ThreadBufferMapping>::iterator t = tbm.begin(); t != tbm.end(); ++t) {
+			request_buffers[t->emitting_thread] = static_cast<RequestBuffer*> (t->request_buffer);
+		}
+	}
 }
 
 template <typename RequestObject> void
-AbstractUI<RequestObject>::register_thread (string target_gui, pthread_t thread_id, string /*thread name*/, uint32_t num_requests)
+AbstractUI<RequestObject>::register_thread (pthread_t thread_id, string thread_name, uint32_t num_requests)
 {
 	/* the calling thread wants to register with the thread that runs this
 	 * UI's event loop, so that it will have its own per-thread queue of
@@ -83,30 +93,39 @@ AbstractUI<RequestObject>::register_thread (string target_gui, pthread_t thread_
 	 * do so in a realtime-safe manner (no locks).
 	 */
 
-	if (target_gui != name()) {
-		/* this UI is not the UI that the calling thread is trying to
-		   register with
-		*/
-		return;
-	}
+	DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("in %1 (thread name %4), %2 (%5) wants to register with UIs\n", event_loop_name(), thread_name, pthread_name(), DEBUG_THREAD_SELF));
 
 	/* the per_thread_request_buffer is a thread-private variable.
 	   See pthreads documentation for more on these, but the key
 	   thing is that it is a variable that as unique value for
-	   each thread, guaranteed.
+	   each thread, guaranteed. Note that the thread in question
+	   is the caller of this function, which is assumed to be the
+	   thread from which signals will be emitted that this UI's
+	   event loop will catch.
 	*/
 
 	RequestBuffer* b = per_thread_request_buffer.get();
 
-        if (b) {
-                /* thread already registered with this UI
-                 */
-                return;
-        }
+	if (!b) {
+
+		/* create a new request queue/ringbuffer */
 
-	/* create a new request queue/ringbuffer */
+		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("create new request buffer for %1 in %2\n", thread_name, event_loop_name()));
 
-        b = new RequestBuffer (num_requests, *this);
+		b = new RequestBuffer (num_requests);
+		/* set this thread's per_thread_request_buffer to this new
+		   queue/ringbuffer. remember that only this thread will
+		   get this queue when it calls per_thread_request_buffer.get()
+
+		   the second argument is a function that will be called
+		   when the thread exits, and ensures that the buffer is marked
+		   dead. it will then be deleted during a call to handle_ui_requests()
+		*/
+
+		per_thread_request_buffer.set (b);
+	} else {
+		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1 : %2 is already registered\n", event_loop_name(), thread_name));
+	}
 
 	{
 		/* add the new request queue (ringbuffer) to our map
@@ -119,16 +138,6 @@ AbstractUI<RequestObject>::register_thread (string target_gui, pthread_t thread_
 		request_buffers[thread_id] = b;
 	}
 
-	/* set this thread's per_thread_request_buffer to this new
-	   queue/ringbuffer. remember that only this thread will
-	   get this queue when it calls per_thread_request_buffer.get()
-
-	   the second argument is a function that will be called
-	   when the thread exits, and ensures that the buffer is marked
-	   dead. it will then be deleted during a call to handle_ui_requests()
-	*/
-
-	per_thread_request_buffer.set (b);
 }
 
 template <typename RequestObject> RequestObject*
@@ -151,14 +160,14 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
 		rbuf->get_write_vector (&vec);
 
 		if (vec.len[0] == 0) {
-			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: no space in per thread pool for request of type %2\n", name(), rt));
+			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: no space in per thread pool for request of type %2\n", event_loop_name(), rt));
 			return 0;
 		}
 
-		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", name(), rt, pthread_name()));
+		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", event_loop_name(), rt, pthread_name()));
 
 		vec.buf[0]->type = rt;
-                vec.buf[0]->valid = true;
+		vec.buf[0]->valid = true;
 		return vec.buf[0];
 	}
 
@@ -167,7 +176,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
 	 * are not at work.
 	 */
 
-	DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", name(), rt, pthread_name()));
+	DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", event_loop_name(), rt, pthread_name()));
 
 	RequestObject* req = new RequestObject;
 	req->type = rt;
@@ -187,52 +196,52 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 
 	for (i = request_buffers.begin(); i != request_buffers.end(); ++i) {
 
-                while (true) {
-
-                        /* we must process requests 1 by 1 because
-                           the request may run a recursive main
-                           event loop that will itself call
-                           handle_ui_requests. when we return
-                           from the request handler, we cannot
-                           expect that the state of queued requests
-                           is even remotely consistent with
-                           the condition before we called it.
-                        */
-
-                        i->second->get_read_vector (&vec);
-
-                        if (vec.len[0] == 0) {
-                                break;
-                        } else {
-                                if (vec.buf[0]->valid) {
-                                        request_buffer_map_lock.unlock ();
-                                        do_request (vec.buf[0]);
-                                        request_buffer_map_lock.lock ();
-                                        if (vec.buf[0]->invalidation) {
-                                                vec.buf[0]->invalidation->requests.remove (vec.buf[0]);
-                                        }
-                                        delete vec.buf[0];
-                                        i->second->increment_read_ptr (1);
-                                }
-                        }
-                }
-        }
-
-        /* clean up any dead request buffers (their thread has exited) */
+		while (true) {
+
+			/* we must process requests 1 by 1 because
+			 * the request may run a recursive main
+			 * event loop that will itself call
+			 * handle_ui_requests. when we return
+			 * from the request handler, we cannot
+			 * expect that the state of queued requests
+			 * is even remotely consistent with
+			 * the condition before we called it.
+			 */
+
+			i->second->get_read_vector (&vec);
+
+			if (vec.len[0] == 0) {
+				break;
+			} else {
+				if (vec.buf[0]->valid) {
+					request_buffer_map_lock.unlock ();
+					do_request (vec.buf[0]);
+					request_buffer_map_lock.lock ();
+					if (vec.buf[0]->invalidation) {
+						vec.buf[0]->invalidation->requests.remove (vec.buf[0]);
+					}
+				}
+				i->second->increment_read_ptr (1);
+			}
+		}
+	}
+
+	/* clean up any dead request buffers (their thread has exited) */
 
 	for (i = request_buffers.begin(); i != request_buffers.end(); ) {
-             if ((*i).second->dead) {
-		     DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 deleting dead per-thread request buffer for %3 @ %4\n",
-									  name(), pthread_name(), i->second));
-                     delete (*i).second;
-                     RequestBufferMapIterator tmp = i;
-                     ++tmp;
-                     request_buffers.erase (i);
-                     i = tmp;
-             } else {
-                     ++i;
-             }
-        }
+		if ((*i).second->dead) {
+			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 deleting dead per-thread request buffer for %3 @ %4\n",
+			                                                     event_loop_name(), pthread_name(), i->second));
+			cerr << event_loop_name() << " noticed that a buffer was dead\n";
+			delete (*i).second;
+			RequestBufferMapIterator tmp = i;
+			++tmp;
+			request_buffers.erase (i);
+			i = tmp;
+		} else {
+			++i;
+		}
+	}
 
 	request_buffer_map_lock.unlock ();
 
@@ -244,34 +253,34 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 		RequestObject* req = request_list.front ();
 		request_list.pop_front ();
 
-                /* We need to use this lock, because its the one
-                   returned by slot_invalidation_mutex() and protects
-                   against request invalidation.
-                */
+		/* We need to use this lock, because its the one
+		 * returned by slot_invalidation_mutex() and protects
+		 * against request invalidation.
+		 */
 
-                request_buffer_map_lock.lock ();
-                if (!req->valid) {
-			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", name(), pthread_name(), req->type));
-                        delete req;
-                        request_buffer_map_lock.unlock ();
-                        continue;
-                }
+		request_buffer_map_lock.lock ();
+		if (!req->valid) {
+			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", event_loop_name(), pthread_name(), req->type));
+			delete req;
+			request_buffer_map_lock.unlock ();
+			continue;
+		}
 
-                /* we're about to execute this request, so its
-                   too late for any invalidation. mark
-                   the request as "done" before we start.
-                */
+		/* we're about to execute this request, so its
+		 * too late for any invalidation. mark
+		 * the request as "done" before we start.
+		 */
 
-                if (req->invalidation) {
-			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_name()));
+		if (req->invalidation) {
+			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", event_loop_name(), pthread_name()));
 
 			/* after this call, if the object referenced by the
 			 * invalidation record is deleted, it will no longer
 			 * try to mark the request as invalid.
 			 */
 
-                        req->invalidation->requests.remove (req);
-                }
+			req->invalidation->requests.remove (req);
+		}
 
 		/* at this point, an object involved in a functor could be
 		 * deleted before we actually execute the functor. so there is
@@ -282,7 +291,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 		 * references to objects to enter into the request queue.
 		 */
 
-                request_buffer_map_lock.unlock ();
+		request_buffer_map_lock.unlock ();
 
 		/* unlock the request lock while we execute the request, so
 		 * that we don't needlessly block other threads (note: not RT
@@ -291,7 +300,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 
 		lm.release ();
 
-		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", name(), pthread_name(), req->type));
+		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", event_loop_name(), pthread_name(), req->type));
 
 		/* and lets do it ... this is a virtual call so that each
 		 * specific type of UI can have its own set of requests without
@@ -300,7 +309,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
 
 		do_request (req);
 
-		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", name(), pthread_name(), req->type));
+		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", event_loop_name(), pthread_name(), req->type));
 		delete req;
 
 		/* re-acquire the list lock so that we check again */
@@ -325,7 +334,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
 		/* the thread that runs this UI's event loop is sending itself
 		   a request: we dispatch it immediately and inline.
 		*/
-		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_name(), req->type));
+		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", event_loop_name(), pthread_name(), req->type));
 		do_request (req);
 		delete req;
 	} else {
@@ -345,13 +354,13 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
 		RequestBuffer* rbuf = per_thread_request_buffer.get ();
 
 		if (rbuf != 0) {
-			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", name(), pthread_name(), req->type));
+			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", event_loop_name(), pthread_name(), req->type));
 			rbuf->increment_write_ptr (1);
 		} else {
 			/* no per-thread buffer, so just use a list with a lock so that it remains
 			   single-reader/single-writer semantics
 			*/
-			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", name(), pthread_name(), req->type));
+			DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", event_loop_name(), pthread_name(), req->type));
 			Glib::Threads::Mutex::Lock lm (request_list_lock);
 			request_list.push_back (req);
 		}
@@ -368,7 +377,7 @@ template<typename RequestObject> void
 AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const boost::function<void()>& f)
 {
 	if (caller_is_self()) {
-		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation));
+		DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", event_loop_name(), pthread_name(), &f, invalidation));
 		f ();
 		return;
 	}
@@ -379,7 +388,7 @@ AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const bo
 		return;
 	}
 
-	DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation));
+	DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", event_loop_name(), pthread_name(), &f, invalidation));
 
 	/* copy semantics: copy the functor into the request object */
 
@@ -393,13 +402,20 @@ AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const bo
 	 * a functor that uses an object that is being deleted.
 	 */
 
-        req->invalidation = invalidation;
+	req->invalidation = invalidation;
 
-        if (invalidation) {
-                invalidation->requests.push_back (req);
-                invalidation->event_loop = this;
-        }
+	if (invalidation) {
+		invalidation->requests.push_back (req);
+		invalidation->event_loop = this;
+	}
 
 	send_request (req);
 }
 
+template<typename RequestObject> void*
+AbstractUI<RequestObject>::request_buffer_factory (uint32_t num_requests)
+{
+	RequestBuffer*  mcr = new RequestBuffer (num_requests);
+	per_thread_request_buffer.set (mcr);
+	return mcr;
+}
diff --git a/libs/pbd/pbd/abstract_ui.h b/libs/pbd/pbd/abstract_ui.h
index 5491210..78a337f 100644
--- a/libs/pbd/pbd/abstract_ui.h
+++ b/libs/pbd/pbd/abstract_ui.h
@@ -58,20 +58,20 @@ class ABSTRACT_UI_API AbstractUI : public BaseUI
 	AbstractUI (const std::string& name);
 	virtual ~AbstractUI() {}
 
-	void register_thread (std::string, pthread_t, std::string, uint32_t num_requests);
+	void register_thread (pthread_t, std::string, uint32_t num_requests);
 	void call_slot (EventLoop::InvalidationRecord*, const boost::function<void()>&);
         Glib::Threads::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
 
 	Glib::Threads::Mutex request_buffer_map_lock;
 
+	static void* request_buffer_factory (uint32_t num_requests);
+
   protected:
 	struct RequestBuffer : public PBD::RingBufferNPT<RequestObject> {
                 bool dead;
-                AbstractUI<RequestObject>& ui;
-                RequestBuffer (uint32_t size, AbstractUI<RequestObject>& uir)
+                RequestBuffer (uint32_t size)
                         : PBD::RingBufferNPT<RequestObject> (size)
-                        , dead (false)
-                        , ui (uir) {}
+	                , dead (false) {}
         };
 	typedef typename RequestBuffer::rw_vector RequestBufferVector;
 
@@ -105,5 +105,3 @@ class ABSTRACT_UI_API AbstractUI : public BaseUI
 };
 
 #endif /* __pbd_abstract_ui_h__ */
-
-
diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h
index ec2cf33..029d822 100644
--- a/libs/pbd/pbd/base_ui.h
+++ b/libs/pbd/pbd/base_ui.h
@@ -54,8 +54,6 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop
         Glib::Threads::Thread* event_loop_thread() const { return run_loop_thread; }
         bool caller_is_self () const { return Glib::Threads::Thread::self() == run_loop_thread; }
 
-	std::string name() const { return _name; }
-
 	bool ok() const { return _ok; }
 
 	static RequestType new_request_type();
@@ -107,7 +105,6 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop
 	virtual void handle_ui_requests () = 0;
 
   private:
-	std::string _name;
 	BaseUI* base_ui_instance;
 
 	CrossThreadChannel request_channel;
diff --git a/libs/pbd/pbd/configuration_variable.h b/libs/pbd/pbd/configuration_variable.h
index 86c13b0..6bdf0f7 100644
--- a/libs/pbd/pbd/configuration_variable.h
+++ b/libs/pbd/pbd/configuration_variable.h
@@ -167,7 +167,7 @@ class /*LIBPBD_API*/ ConfigVariableWithMutation : public ConfigVariable<T>
 {
   public:
 	ConfigVariableWithMutation (std::string name, T val, T (*m)(T))
-		: ConfigVariable<T> (name, val), mutator (m) {}
+		: ConfigVariable<T> (name, m (val)), unmutated_value (val), mutator (m) {}
 
 	bool set (T val) {
 		if (unmutated_value != val) {
diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h
index 235c4ce..727153a 100644
--- a/libs/pbd/pbd/controllable.h
+++ b/libs/pbd/pbd/controllable.h
@@ -37,6 +37,19 @@ class XMLNode;
 
 namespace PBD {
 
+/* This is a pure virtual class to represent a scalar control.
+ *
+ * Note that it contains no storage/state for the controllable thing that it
+ * represents. Derived classes must provide set_value()/get_value() methods,
+ * which will involve (somehow) an actual location to store the value.
+ *
+ * In essence, this is an interface, not a class.
+ *
+ * Without overriding upper() and lower(), a derived class will function
+ * as a control whose value can range between 0 and 1.0.
+ *
+ */
+
 class LIBPBD_API Controllable : public PBD::StatefulDestructible {
   public:
 	enum Flag {
@@ -63,8 +76,27 @@ class LIBPBD_API Controllable : public PBD::StatefulDestructible {
 	 * but passed to the processor as a linear quantity.
 	 */
 
-	/** Get and Set `internal' value */
-	virtual void set_value (double) = 0;
+	/* Within an application, various Controllables might be considered to
+	 * be "grouped" in a way that implies that setting 1 of them also
+	 * modifies others in the group.
+	 */
+
+	enum GroupControlDisposition {
+		WholeGroup,  /* set all controls in the same "group" as this one */
+		NoGroup,     /* set only this control */
+		UseGroup     /* use group settings to decide which group controls are altered */
+	};
+
+	/** Get and Set `internal' value
+	 *
+	 * All derived classes must implement this.
+         *
+         * Basic derived classes will ignore @param group_override,
+         * but more sophisticated children, notably those that
+         * proxy the value setting logic via an object that is aware of group
+         * relationships between this control and others, will find it useful.
+         */
+        virtual void set_value (double, GroupControlDisposition group_override) = 0;
 	virtual double get_value (void) const = 0;
 
 	/** Conversions between `internal', 'interface', and 'user' values */
@@ -73,13 +105,13 @@ class LIBPBD_API Controllable : public PBD::StatefulDestructible {
 	virtual double internal_to_user (double i) const {return i;}  //by default the internal value is the same as the user value
 	virtual double user_to_internal (double i) const {return i;}  //by default the internal value is the same as the user value
 
-	/** Get and Set `interface' value  (typically, percent of knob travel) */
+	/** Get and Set `interface' value  (typically, fraction of knob travel) */
 	virtual float get_interface() const { return (internal_to_interface(get_value())); }
-	virtual void set_interface (float percent) { percent = min( max(0.0f, percent), 1.0f);  set_value(interface_to_internal(percent)); }
+	virtual void set_interface (float fraction) { fraction = min( max(0.0f, fraction), 1.0f);  set_value(interface_to_internal(fraction), NoGroup); }
 
 	/** Get and Set `user' value  ( dB or milliseconds, etc.  This MIGHT be the same as the internal value, but in a few cases it is not ) */
 	virtual float get_user() const { return (internal_to_user(get_value())); }
-	virtual void set_user (float user_v) { set_value(user_to_internal(user_v)); }
+	virtual void set_user (float user_v) { set_value(user_to_internal(user_v), NoGroup); }
 	virtual std::string get_user_string() const { return std::string(); }
 
 	PBD::Signal0<void> LearningFinished;
@@ -114,11 +146,10 @@ class LIBPBD_API Controllable : public PBD::StatefulDestructible {
 	static Controllable* by_id (const PBD::ID&);
 	static Controllable* by_name (const std::string&);
         static const std::string xml_node_name;
+
   private:
 	std::string _name;
-
 	std::string _units;
-
 	Flag        _flags;
 	bool        _touching;
 
@@ -140,7 +171,7 @@ class LIBPBD_API IgnorableControllable : public Controllable
 	IgnorableControllable () : PBD::Controllable ("ignoreMe") {}
 	~IgnorableControllable () {}
 
-	void set_value (double /*v*/) {}
+	void set_value (double /*v*/, PBD::Controllable::GroupControlDisposition /* group_override */) {}
 	double get_value () const { return 0.0; }
 };
 
diff --git a/libs/pbd/pbd/demangle.h b/libs/pbd/pbd/demangle.h
index a8487f9..9e28abe 100644
--- a/libs/pbd/pbd/demangle.h
+++ b/libs/pbd/pbd/demangle.h
@@ -24,34 +24,30 @@
 #include <cstdlib>
 #include <typeinfo>
 
-#ifdef __GNUC__
-#include <cxxabi.h>
-#endif
-
 #include "pbd/libpbd_visibility.h"
 
 namespace PBD
 {
-	template<typename T> /*LIBPBD_API*/
-	std::string demangled_name (T const & obj)
-	{
-#ifdef __GNUC__
-		int status;
-		char * res = abi::__cxa_demangle (typeid(obj).name(), 0, 0, &status);
-		if (status == 0) {
-			std::string s(res);
-			free (res);
-			return s;
-		}
-#endif
-
-                /* Note: on win32, you can use UnDecorateSymbolName.
-                   See http://msdn.microsoft.com/en-us/library/ms681400%28VS.85%29.aspx
-                   See also: http://msdn.microsoft.com/en-us/library/ms680344%28VS.85%29.aspx
-                */
-
-		return typeid(obj).name();
-	}
+
+/**
+ * @param symbol a mangled symbol/name
+ * @return a demangled symbol/name
+ */
+LIBPBD_API std::string demangle_symbol(const std::string& symbol);
+
+/**
+ * @param str a string containing a mangled symbol/name
+ * @return a string with the mangled symbol/name replaced with a demangled
+ * name
+ */
+LIBPBD_API std::string demangle(const std::string& str);
+
+template <typename T>
+std::string demangled_name(T const& obj)
+{
+	return demangle_symbol(typeid(obj).name());
+}
+
 } // namespace
 
 #endif // __libpbd_demangle_h__
diff --git a/libs/pbd/pbd/event_loop.h b/libs/pbd/pbd/event_loop.h
index a100365..f4f57f4 100644
--- a/libs/pbd/pbd/event_loop.h
+++ b/libs/pbd/pbd/event_loop.h
@@ -20,8 +20,13 @@
 #ifndef __pbd_event_loop_h__
 #define __pbd_event_loop_h__
 
+#include <string>
+#include <vector>
+#include <map>
 #include <boost/function.hpp>
 #include <boost/bind.hpp> /* we don't need this here, but anything calling call_slot() probably will, so this is convenient */
+#include <stdint.h>
+#include <pthread.h>
 #include <glibmm/threads.h>
 
 #include "pbd/libpbd_visibility.h"
@@ -41,7 +46,7 @@ namespace PBD
 class LIBPBD_API EventLoop
 {
   public:
-	EventLoop() {}
+	EventLoop (std::string const&);
 	virtual ~EventLoop() {}
 
 	enum RequestType {
@@ -73,12 +78,45 @@ class LIBPBD_API EventLoop
 	virtual void call_slot (InvalidationRecord*, const boost::function<void()>&) = 0;
         virtual Glib::Threads::Mutex& slot_invalidation_mutex() = 0;
 
+        std::string event_loop_name() const { return _name; }
+
 	static EventLoop* get_event_loop_for_thread();
 	static void set_event_loop_for_thread (EventLoop* ui);
 
+	struct ThreadBufferMapping {
+		pthread_t emitting_thread;
+		std::string target_thread_name;
+		void* request_buffer;
+	};
+
+	static std::vector<ThreadBufferMapping> get_request_buffers_for_target_thread (const std::string&);
+
+	static void register_request_buffer_factory (const std::string& target_thread_name, void* (*factory) (uint32_t));
+	static void pre_register (const std::string& emitting_thread_name, uint32_t num_requests);
+
   private:
         static Glib::Threads::Private<EventLoop> thread_event_loop;
+	std::string _name;
 
+	typedef std::map<std::string,ThreadBufferMapping> ThreadRequestBufferList;
+	static ThreadRequestBufferList thread_buffer_requests;
+	static Glib::Threads::RWLock   thread_buffer_requests_lock;
+
+	struct RequestBufferSupplier {
+
+		/* @param name : name of object/entity that will/may accept
+		   requests from other threads, via a request buffer.
+		*/
+		std::string name;
+
+		/* @param factory : a function that can be called (with an
+		   argument specifying the @param number_of_requests) to create and
+		   return a request buffer for communicating with @param name)
+		*/
+		void* (*factory)(uint32_t nunber_of_requests);
+	};
+	typedef std::vector<RequestBufferSupplier> RequestBufferSuppliers;
+	static RequestBufferSuppliers request_buffer_suppliers;
 };
 
 }
diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h
index a5173ad..8f70fda 100644
--- a/libs/pbd/pbd/pthread_utils.h
+++ b/libs/pbd/pbd/pthread_utils.h
@@ -55,8 +55,8 @@ LIBPBD_API const char* pthread_name ();
 LIBPBD_API void pthread_set_name (const char* name);
 
 namespace PBD {
-	LIBPBD_API extern void notify_gui_about_thread_creation (std::string, pthread_t, std::string, int requests = 256);
-	LIBPBD_API extern PBD::Signal4<void,std::string,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
+	LIBPBD_API extern void notify_event_loops_about_thread_creation (pthread_t, const std::string&, int requests = 256);
+	LIBPBD_API extern PBD::Signal3<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
 }
 
 #endif /* __pbd_pthread_utils__ */
diff --git a/libs/pbd/pbd/search_path.h b/libs/pbd/pbd/search_path.h
index 41b1ffe..d287782 100644
--- a/libs/pbd/pbd/search_path.h
+++ b/libs/pbd/pbd/search_path.h
@@ -114,12 +114,30 @@ public:
 	 */
 	LIBPBD_TEMPLATE_MEMBER_API Searchpath& add_subdirectory_to_paths (const std::string& subdir);
 
-protected:
-
+	/**
+	 * Add directory_path to this Searchpath.
+	 */
 	LIBPBD_TEMPLATE_MEMBER_API void add_directory (const std::string& directory_path);
+
+	/**
+	 * Add directories in paths to this Searchpath.
+	 */
 	LIBPBD_TEMPLATE_MEMBER_API void add_directories (const std::vector<std::string>& paths);
+
+	/**
+	 * Remove directory_path from this Searchpath.
+	 */
 	LIBPBD_TEMPLATE_MEMBER_API void remove_directory (const std::string& directory_path);
+
+	/**
+	 * Remove all the directories in paths from this Searchpath.
+	 */
 	LIBPBD_TEMPLATE_MEMBER_API void remove_directories (const std::vector<std::string>& paths);
+
+	/**
+	 * @return true if Searchpath already contains path
+	 */
+	LIBPBD_TEMPLATE_MEMBER_API bool contains (const std::string& path) const;
 };
 
 LIBPBD_API void export_search_path (const std::string& base_dir, const char* varname, const char* dir);
diff --git a/libs/pbd/pbd/semaphore.h b/libs/pbd/pbd/semaphore.h
deleted file mode 100644
index 265a219..0000000
--- a/libs/pbd/pbd/semaphore.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
-  Copyright (C) 2012 Paul Davis
-  Author: David Robillard
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __pbd_semaphore_h__
-#define __pbd_semaphore_h__
-
-#ifdef __APPLE__
-#    include <mach/mach.h>
-#elif defined(PLATFORM_WINDOWS)
-#    include <windows.h>
-#ifndef INFINITE
-#define INFINITE 0xffffffffL
-#endif
-#else
-#    include <semaphore.h>
-#    include <errno.h>
-#endif
-
-#include "pbd/libpbd_visibility.h"
-#include "pbd/failed_constructor.h"
-
-namespace PBD {
-
-/**
-   Unnamed (process local) counting semaphore.
-
-   The civilized person's synchronisation primitive.  A counting semaphore is
-   an integer which is always non-negative, so, an attempted decrement (or
-   "wait") will block if the value is 0, until another thread does an increment
-   (or "post").
-
-   At least on Lignux, the main advantage of this is that it is fast and the
-   only safe way to reliably signal from a real-time audio thread.  The
-   counting semantics also complement ringbuffers of events nicely.
-*/
-class /*LIBPBD_API*/ Semaphore
-{
-public:
-	/**
-	   Create a new semaphore.
-
-	   Chances are you want 1 wait() per 1 post(), an initial value of 0.
-	*/
-	inline Semaphore(unsigned initial);
-
-	inline ~Semaphore();
-
-	/** Post/Increment/Signal */
-	inline void post();
-
-	/** Wait/Decrement.  Returns false on error. */
-	inline bool wait();
-
-	/** Attempt Wait/Decrement.  Returns true iff a decrement occurred. */
-	inline bool try_wait();
-
-private:
-#if defined(__APPLE__)
-	semaphore_t _sem;  // sem_t is a worthless broken mess on OSX
-#elif defined(PLATFORM_WINDOWS)
-	HANDLE _sem;  // types are overrated anyway
-#else
-	sem_t _sem;
-#endif
-};
-
-#ifdef __APPLE__
-
-inline
-Semaphore::Semaphore(unsigned initial)
-{
-	if (semaphore_create(mach_task_self(), &_sem, SYNC_POLICY_FIFO, initial)) {
-		throw failed_constructor();
-	}
-}
-
-inline
-Semaphore::~Semaphore()
-{
-	semaphore_destroy(mach_task_self(), _sem);
-}
-
-inline void
-Semaphore::post()
-{
-	semaphore_signal(_sem);
-}
-
-inline bool
-Semaphore::wait()
-{
-	if (semaphore_wait(_sem) != KERN_SUCCESS) {
-		return false;
-	}
-	return true;
-}
-
-inline bool
-Semaphore::try_wait()
-{
-	const mach_timespec_t zero = { 0, 0 };
-	return semaphore_timedwait(_sem, zero) == KERN_SUCCESS;
-}
-
-#elif defined(PLATFORM_WINDOWS)
-
-inline
-Semaphore::Semaphore(unsigned initial)
-{
-	if (!(_sem = CreateSemaphore(NULL, initial, LONG_MAX, NULL))) {
-		throw failed_constructor();
-	}
-}
-
-inline
-Semaphore::~Semaphore()
-{
-	CloseHandle(_sem);
-}
-
-inline void
-Semaphore::post()
-{
-	ReleaseSemaphore(_sem, 1, NULL);
-}
-
-inline bool
-Semaphore::wait()
-{
-	if (WaitForSingleObject(_sem, INFINITE) != WAIT_OBJECT_0) {
-		return false;
-	}
-	return true;
-}
-
-inline bool
-Semaphore::try_wait()
-{
-	return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0;
-}
-
-#else  /* !defined(__APPLE__) && !defined(PLATFORM_WINDOWS) */
-
-Semaphore::Semaphore(unsigned initial)
-{
-	if (sem_init(&_sem, 0, initial)) {
-		throw failed_constructor();
-	}
-}
-
-inline
-Semaphore::~Semaphore()
-{
-	sem_destroy(&_sem);
-}
-
-inline void
-Semaphore::post()
-{
-	sem_post(&_sem);
-}
-
-inline bool
-Semaphore::wait()
-{
-	while (sem_wait(&_sem)) {
-		if (errno != EINTR) {
-			return false;  // We are all doomed
-		}
-		/* Otherwise, interrupted (rare/weird), so try again. */
-	}
-
-	return true;
-}
-
-inline bool
-Semaphore::try_wait()
-{
-	return (sem_trywait(&_sem) == 0);
-}
-
-#endif
-
-}  // namespace PBD
-
-#endif  /* __pbd_semaphore_h__ */
diff --git a/libs/pbd/pbd/semutils.h b/libs/pbd/pbd/semutils.h
index 5c0191e..6c661ab 100644
--- a/libs/pbd/pbd/semutils.h
+++ b/libs/pbd/pbd/semutils.h
@@ -19,9 +19,14 @@
 #ifndef __pbd_semutils_h__
 #define __pbd_semutils_h__
 
-#ifdef PLATFORM_WINDOWS
+#if (defined PLATFORM_WINDOWS && !defined USE_PTW32_SEMAPHORE)
+#define WINDOWS_SEMAPHORE 1
+#endif
+
+#ifdef WINDOWS_SEMAPHORE
 #include <windows.h>
 #else
+#include <pthread.h>
 #include <semaphore.h>
 #endif
 
@@ -29,9 +34,9 @@
 
 namespace PBD {
 
-class LIBPBD_API ProcessSemaphore {
+class LIBPBD_API Semaphore {
   private:
-#ifdef PLATFORM_WINDOWS
+#ifdef WINDOWS_SEMAPHORE
 	HANDLE _sem;
 
 #elif __APPLE__
@@ -43,10 +48,10 @@ class LIBPBD_API ProcessSemaphore {
 #endif
 
   public:
-	ProcessSemaphore (const char* name, int val);
-	~ProcessSemaphore ();
+	Semaphore (const char* name, int val);
+	~Semaphore ();
 
-#ifdef PLATFORM_WINDOWS
+#ifdef WINDOWS_SEMAPHORE
 
 	int signal ();
 	int wait ();
diff --git a/libs/pbd/pbd/stacktrace.h b/libs/pbd/pbd/stacktrace.h
index 17a719e..99fc9d5 100644
--- a/libs/pbd/pbd/stacktrace.h
+++ b/libs/pbd/pbd/stacktrace.h
@@ -41,7 +41,6 @@ namespace PBD {
 
 	LIBPBD_API void stacktrace (std::ostream& out, int levels = 0);
 	LIBPBD_API void trace_twb();
-	LIBPBD_API std::string demangle (const std::string&);
 
 template<typename T>
 class /*LIBPBD_API*/ thing_with_backtrace
diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h
index 0d00742..fe2df93 100644
--- a/libs/pbd/pbd/stateful.h
+++ b/libs/pbd/pbd/stateful.h
@@ -53,7 +53,7 @@ class LIBPBD_API Stateful {
 	virtual bool apply_changes (PropertyBase const &);
 	PropertyChange apply_changes (PropertyList const &);
 
-        const OwnedPropertyList& properties() const { return *_properties; }
+	const OwnedPropertyList& properties() const { return *_properties; }
 
 	void add_property (PropertyBase& s);
 
@@ -70,20 +70,29 @@ class LIBPBD_API Stateful {
 	void set_id (const std::string&);
 	void reset_id ();
 
-        /* history management */
+	/* RAII structure to manage thread-local ID regeneration.
+	 */
+	struct ForceIDRegeneration {
+		ForceIDRegeneration () {
+			set_regenerate_xml_and_string_ids_in_this_thread (true);
+		}
+		~ForceIDRegeneration () {
+			set_regenerate_xml_and_string_ids_in_this_thread (false);
+		}
+	};
+
+	/* history management */
 
 	void clear_changes ();
 	virtual void clear_owned_changes ();
-        PropertyList* get_changes_as_properties (Command *) const;
+	PropertyList* get_changes_as_properties (Command *) const;
 	virtual void rdiff (std::vector<Command*> &) const;
-        bool changed() const;
+	bool changed() const;
 
-        /* create a property list from an XMLNode
-         */
-        virtual PropertyList* property_factory (const XMLNode&) const;
+	/* create a property list from an XMLNode */
+	virtual PropertyList* property_factory (const XMLNode&) const;
 
-	/* How stateful's notify of changes to their properties
-	 */
+	/* How stateful's notify of changes to their properties */
 	PBD::Signal1<void,const PropertyChange&> PropertyChanged;
 
 	static int current_state_version;
@@ -92,7 +101,7 @@ class LIBPBD_API Stateful {
 	virtual void suspend_property_changes ();
 	virtual void resume_property_changes ();
 
-        bool property_changes_suspended() const { return g_atomic_int_get (const_cast<gint*>(&_stateful_frozen)) > 0; }
+	bool property_changes_suspended() const { return g_atomic_int_get (const_cast<gint*>(&_stateful_frozen)) > 0; }
 
   protected:
 
@@ -111,23 +120,28 @@ class LIBPBD_API Stateful {
 	XMLNode *_extra_xml;
 	XMLNode *_instant_xml;
 	PBD::PropertyChange     _pending_changed;
-        Glib::Threads::Mutex _lock;
+	Glib::Threads::Mutex _lock;
 
 	std::string _xml_node_name; ///< name of node to use for this object in XML
 	OwnedPropertyList* _properties;
 
-        virtual void send_change (const PropertyChange&);
-        /** derived classes can implement this in order to process a property change
-            within thaw() just before send_change() is called.
-        */
-        virtual void mid_thaw (const PropertyChange&) { }
+	virtual void send_change (const PropertyChange&);
+	/** derived classes can implement this in order to process a property change
+	    within thaw() just before send_change() is called.
+	*/
+	virtual void mid_thaw (const PropertyChange&) { }
+
+	bool regenerate_xml_or_string_ids () const;
 
   private:
+	friend struct ForceIDRegeneration;
+	static Glib::Threads::Private<bool> _regenerate_xml_or_string_ids;
 	PBD::ID  _id;
-        gint     _stateful_frozen;
+	gint     _stateful_frozen;
+
+	static void set_regenerate_xml_and_string_ids_in_this_thread (bool yn);
 };
 
 } // namespace PBD
 
 #endif /* __pbd_stateful_h__ */
-
diff --git a/libs/pbd/pbd/timer.h b/libs/pbd/pbd/timer.h
index 4c80d9d..4d96eed 100644
--- a/libs/pbd/pbd/timer.h
+++ b/libs/pbd/pbd/timer.h
@@ -46,6 +46,9 @@ public:
 
 	virtual unsigned int connection_count () const = 0;
 
+	void suspend () { m_suspended = true; }
+	void resume  () { m_suspended = false; }
+
 protected:
 
 	virtual ~Timer() { }
@@ -56,6 +59,8 @@ protected:
 
 	virtual bool on_elapsed () = 0;
 
+	bool suspended  () const { return m_suspended; }
+
 private:
 
 	Timer(const Timer&);
@@ -73,6 +78,8 @@ private:
 
 	const Glib::RefPtr<Glib::MainContext>  m_main_context;
 
+	bool                                   m_suspended;
+
 };
 
 class LIBPBD_API StandardTimer : public Timer
diff --git a/libs/pbd/pthread_utils.cc b/libs/pbd/pthread_utils.cc
index 1abe6a9..7cd25e4 100644
--- a/libs/pbd/pthread_utils.cc
+++ b/libs/pbd/pthread_utils.cc
@@ -44,7 +44,7 @@ static pthread_mutex_t thread_map_lock = PTHREAD_MUTEX_INITIALIZER;
 static Glib::Threads::Private<char> thread_name (free);
 
 namespace PBD {
-	PBD::Signal4<void,std::string, pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
+	PBD::Signal3<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
 }
 
 using namespace PBD;
@@ -58,10 +58,18 @@ static int thread_creator (pthread_t* thread_id, const pthread_attr_t* attr, voi
 #endif
 }
 
+
 void
-PBD::notify_gui_about_thread_creation (std::string target_gui, pthread_t thread, std::string str, int request_count)
+PBD::notify_event_loops_about_thread_creation (pthread_t thread, const std::string& emitting_thread_name, int request_count)
 {
-	ThreadCreatedWithRequestSize (target_gui, thread, str, request_count);
+	/* notify threads that may exist in the future (they may also exist
+	 * already, in which case they will catch the
+	 * ThreadCreatedWithRequestSize signal)
+	 */
+	EventLoop::pre_register (emitting_thread_name, request_count);
+
+	/* notify all existing threads */
+	ThreadCreatedWithRequestSize (thread, emitting_thread_name, request_count);
 }
 
 struct ThreadStartWithName {
@@ -199,4 +207,3 @@ pthread_cancel_one (pthread_t thread)
 	pthread_cancel (thread);
 	pthread_mutex_unlock (&thread_map_lock);
 }
-
diff --git a/libs/pbd/search_path.cc b/libs/pbd/search_path.cc
index d1dc8c3..46292ef 100644
--- a/libs/pbd/search_path.cc
+++ b/libs/pbd/search_path.cc
@@ -163,6 +163,17 @@ Searchpath::add_subdirectory_to_paths (const string& subdir)
 	return *this;
 }
 
+bool
+Searchpath::contains (const string& path) const
+{
+	std::vector<std::string>::const_iterator i = find(begin(), end(), path);
+
+	if (i == end()) {
+		return false;
+	}
+	return true;
+}
+
 /* This is not part of the Searchpath object, but is closely related to the
  * whole idea, and we put it here for convenience.
  */
diff --git a/libs/pbd/semutils.cc b/libs/pbd/semutils.cc
index 5d3ef3d..7f31d30 100644
--- a/libs/pbd/semutils.cc
+++ b/libs/pbd/semutils.cc
@@ -21,9 +21,9 @@
 
 using namespace PBD;
 
-ProcessSemaphore::ProcessSemaphore (const char* name, int val)
+Semaphore::Semaphore (const char* name, int val)
 {
-#ifdef PLATFORM_WINDOWS
+#ifdef WINDOWS_SEMAPHORE
 	if ((_sem = CreateSemaphore(NULL, val, 32767, name)) == NULL) {
 		throw failed_constructor ();
 	}
@@ -48,26 +48,26 @@ ProcessSemaphore::ProcessSemaphore (const char* name, int val)
 #endif
 }
 
-ProcessSemaphore::~ProcessSemaphore ()
+Semaphore::~Semaphore ()
 {
-#ifdef PLATFORM_WINDOWS
+#ifdef WINDOWS_SEMAPHORE
 	CloseHandle(_sem);
 #elif __APPLE__
 	sem_close (ptr_to_sem());
 #endif
 }
 
-#ifdef PLATFORM_WINDOWS
+#ifdef WINDOWS_SEMAPHORE
 
 int
-ProcessSemaphore::signal ()
+Semaphore::signal ()
 {
 	// non-zero on success, opposite to posix
 	return !ReleaseSemaphore(_sem, 1, NULL);
 }
 
 int
-ProcessSemaphore::wait ()
+Semaphore::wait ()
 {
 	DWORD result = 0;
 	result = WaitForSingleObject(_sem, INFINITE);
diff --git a/libs/pbd/stacktrace.cc b/libs/pbd/stacktrace.cc
index 176c5b8..8a7cdfa 100644
--- a/libs/pbd/stacktrace.cc
+++ b/libs/pbd/stacktrace.cc
@@ -21,6 +21,7 @@
 
 #include "pbd/stacktrace.h"
 #include "pbd/debug.h"
+#include "pbd/demangle.h"
 #include "pbd/compose.h"
 #include "pbd/pthread_utils.h"
 
@@ -43,48 +44,6 @@ PBD::trace_twb ()
 #ifdef HAVE_EXECINFO
 
 #include <execinfo.h>
-#include <cxxabi.h>
-
-static std::string
-symbol_demangle (const std::string& l)
-{
-	int status;
-
-	try {
-
-		char* realname = abi::__cxa_demangle (l.c_str(), 0, 0, &status);
-		std::string d (realname);
-		free (realname);
-		return d;
-	} catch (std::exception) {
-
-	}
-
-	return l;
-}
-
-std::string
-PBD::demangle (std::string const & l)
-{
-	std::string::size_type const b = l.find_first_of ("(");
-
-	if (b == std::string::npos) {
-		return symbol_demangle (l);
-	}
-
-	std::string::size_type const p = l.find_last_of ("+");
-	if (p == std::string::npos) {
-		return symbol_demangle (l);
-	}
-
-	if ((p - b) <= 1) {
-		return symbol_demangle (l);
-	}
-
-	std::string const fn = l.substr (b + 1, p - b - 1);
-
-	return symbol_demangle (fn);
-}
 
 void
 PBD::stacktrace (std::ostream& out, int levels)
@@ -127,12 +86,6 @@ extern "C" {
 }
 #endif
 
-std::string
-PBD::demangle (std::string const & l) /* JE - !!!! 'PBD' namespace might possibly get removed (except it's still used in 'libs/canvas/item.cc') */
-{
-	return std::string();
-}
-
 void
 PBD::stacktrace( std::ostream& out, int)
 {
@@ -169,30 +122,18 @@ PBD::stacktrace( std::ostream& out, int)
 #endif
 }
 
-void
-c_stacktrace ()
-{
-	PBD::stacktrace (std::cout);
-}
-
 #else
 
-std::string
-PBD::demangle (std::string const & l) /* JE - !!!! 'PBD' namespace might possibly get removed (except it's still used in 'libs/canvas/item.cc') */
-{
-	return std::string();
-}
-
 void
 PBD::stacktrace (std::ostream& out, int /*levels*/)
 {
 	out << "stack tracing is not enabled on this platform" << std::endl;
 }
 
+#endif
+
 void
 c_stacktrace ()
 {
 	PBD::stacktrace (std::cout);
 }
-
-#endif /* HAVE_EXECINFO */
diff --git a/libs/pbd/stateful.cc b/libs/pbd/stateful.cc
index 845d6ba..3fb11a3 100644
--- a/libs/pbd/stateful.cc
+++ b/libs/pbd/stateful.cc
@@ -44,12 +44,14 @@ namespace PBD {
 int Stateful::current_state_version = 0;
 int Stateful::loading_state_version = 0;
 
+Glib::Threads::Private<bool> Stateful::_regenerate_xml_or_string_ids;
+
 Stateful::Stateful ()
-	: _properties (new OwnedPropertyList)
+	: _extra_xml (0)
+	, _instant_xml (0)
+	, _properties (new OwnedPropertyList)
 	, _stateful_frozen (0)
 {
-	_extra_xml = 0;
-	_instant_xml = 0;
 }
 
 Stateful::~Stateful ()
@@ -69,7 +71,7 @@ Stateful::add_extra_xml (XMLNode& node)
 		_extra_xml = new XMLNode ("Extra");
 	}
 
-	_extra_xml->remove_nodes (node.name());
+	_extra_xml->remove_nodes_and_delete (node.name());
 	_extra_xml->add_child_nocopy (node);
 }
 
@@ -381,6 +383,12 @@ bool
 Stateful::set_id (const XMLNode& node)
 {
 	const XMLProperty* prop;
+	bool* regen = _regenerate_xml_or_string_ids.get();
+
+	if (regen && *regen) {
+		reset_id ();
+		return true;
+	}
 
 	if ((prop = node.property ("id")) != 0) {
 		_id = prop->value ();
@@ -399,7 +407,31 @@ Stateful::reset_id ()
 void
 Stateful::set_id (const string& str)
 {
-	_id = str;
+	bool* regen = _regenerate_xml_or_string_ids.get();
+
+	if (regen && *regen) {
+		reset_id ();
+	} else {
+		_id = str;
+	}
+}
+
+bool
+Stateful::regenerate_xml_or_string_ids () const
+{
+	bool* regen = _regenerate_xml_or_string_ids.get();
+	if (regen && *regen) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+void
+Stateful::set_regenerate_xml_and_string_ids_in_this_thread (bool yn)
+{
+	bool* val = new bool (yn);
+	_regenerate_xml_or_string_ids.set (val);
 }
 
 } // namespace PBD
diff --git a/libs/pbd/system_exec.cc b/libs/pbd/system_exec.cc
index d92987b..02e4ddc 100644
--- a/libs/pbd/system_exec.cc
+++ b/libs/pbd/system_exec.cc
@@ -530,6 +530,7 @@ SystemExec::output_interposer()
 		ReadStdout(data, bytesRead);/* EMIT SIGNAL */
 	}
 	Terminated();/* EMIT SIGNAL */
+	pthread_exit(0);
 }
 
 void
@@ -896,6 +897,7 @@ SystemExec::output_interposer()
 		ReadStdout(rv, r);/* EMIT SIGNAL */
 	}
 	Terminated();/* EMIT SIGNAL */
+	pthread_exit(0);
 }
 
 void
diff --git a/libs/pbd/timer.cc b/libs/pbd/timer.cc
index 662c7dd..8312c53 100644
--- a/libs/pbd/timer.cc
+++ b/libs/pbd/timer.cc
@@ -26,6 +26,7 @@ Timer::Timer (unsigned int interval,
 	: m_timeout_source(NULL)
 	, m_timeout_interval(interval)
 	, m_main_context(main_context)
+	, m_suspended(false)
 {
 
 }
@@ -121,7 +122,9 @@ StandardTimer::on_elapsed()
 		return false;
 	}
 
-	m_signal();
+	if (!suspended ()) {
+		m_signal();
+	}
 	return true;
 }
 
@@ -149,7 +152,9 @@ BlinkTimer::on_elapsed()
 		return false;
 	}
 
-	m_blink_signal(blink_on = !blink_on);
+	if (!suspended ()) {
+		m_blink_signal(blink_on = !blink_on);
+	}
 	return true;
 }
 
diff --git a/libs/pbd/wscript b/libs/pbd/wscript
index c79b257..0d11c85 100644
--- a/libs/pbd/wscript
+++ b/libs/pbd/wscript
@@ -41,6 +41,7 @@ libpbd_sources = [
     'crossthread.cc',
     'cpus.cc',
     'debug.cc',
+    'demangle.cc',
     'enumwriter.cc',
     'event_loop.cc',
     'enums.cc',
@@ -49,7 +50,6 @@ libpbd_sources = [
     'ffs.cc',
     'file_utils.cc',
     'fpu.cc',
-    'glib_semaphore.cc',
     'id.cc',
     'locale_guard.cc',
     'localtime_r.cc',
@@ -114,7 +114,7 @@ def configure(conf):
 def build(bld):
 
     # Make signals_generated.h using signals.py
-    bld(rule = 'python ${SRC} ${TGT}', source = 'pbd/signals.py', target = 'pbd/signals_generated.h')
+    bld(rule = sys.executable + ' ${SRC} ${TGT}', source = 'pbd/signals.py', target = 'pbd/signals_generated.h')
 
     # Library
     if bld.is_defined ('INTERNAL_SHARED_LIBS'):
@@ -176,6 +176,6 @@ def build(bld):
         testobj.defines      = [ 'PACKAGE="' + I18N_PACKAGE + '"' ]
         if sys.platform != 'darwin' and bld.env['build_target'] != 'mingw':
             testobj.linkflags    = ['-lrt']
-            
+
 def shutdown():
     autowaf.shutdown()
diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc
index 0d13c8f..8580d1b 100644
--- a/libs/surfaces/control_protocol/basic_ui.cc
+++ b/libs/surfaces/control_protocol/basic_ui.cc
@@ -100,6 +100,12 @@ BasicUI::goto_start ()
 }
 
 void
+BasicUI::goto_zero ()
+{
+	session->request_locate (0);
+}
+
+void
 BasicUI::goto_end ()
 {
 	session->goto_end ();
diff --git a/libs/surfaces/control_protocol/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/control_protocol/basic_ui.h
index 4c8a8ba..d11fa3b 100644
--- a/libs/surfaces/control_protocol/control_protocol/basic_ui.h
+++ b/libs/surfaces/control_protocol/control_protocol/basic_ui.h
@@ -52,6 +52,7 @@ class LIBCONTROLCP_API BasicUI {
 	void loop_location (framepos_t start, framepos_t end);
 	void access_action ( std::string action_path );
 	static PBD::Signal2<void,std::string,std::string> AccessAction;
+	void goto_zero ();
 	void goto_start ();
 	void goto_end ();
 	void rewind ();
diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
index 8edb3f3..71e8754 100644
--- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h
+++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
@@ -154,16 +154,24 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope
 extern "C" {
 	class ControlProtocolDescriptor {
 	public:
-	    const char* name;      /* descriptive */
-	    const char* id;        /* unique and version-specific */
-	    void*       ptr;       /* protocol can store a value here */
-	    void*       module;    /* not for public access */
-	    int         mandatory; /* if non-zero, always load and do not make optional */
-	    bool        supports_feedback; /* if true, protocol has toggleable feedback mechanism */
-	    bool             (*probe)(ControlProtocolDescriptor*);
-	    ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
-	    void             (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
-
+		const char* name;      /* descriptive */
+		const char* id;        /* unique and version-specific */
+		void*       ptr;       /* protocol can store a value here */
+		void*       module;    /* not for public access */
+		int         mandatory; /* if non-zero, always load and do not make optional */
+		bool        supports_feedback; /* if true, protocol has toggleable feedback mechanism */
+		bool             (*probe)(ControlProtocolDescriptor*);
+		ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
+		void             (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
+		/* this is required if the control protocol connects to signals
+		   from libardour. they all do. It should allocate a
+		   type-specific request buffer for the calling thread, and
+		   store it in a thread-local location that will be used to
+		   find it when sending the event loop a message
+		   (e.g. call_slot()). It should also return the allocated
+		   buffer as a void*.
+		*/
+		void*            (*request_buffer_factory)(uint32_t);
 	};
 }
 
diff --git a/libs/surfaces/faderport/faderport.cc b/libs/surfaces/faderport/faderport.cc
new file mode 100644
index 0000000..cb23163
--- /dev/null
+++ b/libs/surfaces/faderport/faderport.cc
@@ -0,0 +1,1336 @@
+/*
+    Copyright (C) 2015 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <cstdlib>
+#include <sstream>
+#include <algorithm>
+
+#include <stdint.h>
+
+#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+
+#include "pbd/controllable_descriptor.h"
+#include "pbd/error.h"
+#include "pbd/failed_constructor.h"
+#include "pbd/file_utils.h"
+#include "pbd/pthread_utils.h"
+#include "pbd/compose.h"
+#include "pbd/xml++.h"
+
+#include "midi++/port.h"
+
+#include "ardour/async_midi_port.h"
+#include "ardour/audioengine.h"
+#include "ardour/amp.h"
+#include "ardour/bundle.h"
+#include "ardour/debug.h"
+#include "ardour/filesystem_paths.h"
+#include "ardour/midi_port.h"
+#include "ardour/midiport_manager.h"
+#include "ardour/monitor_processor.h"
+#include "ardour/profile.h"
+#include "ardour/rc_configuration.h"
+#include "ardour/route.h"
+#include "ardour/session.h"
+#include "ardour/session_configuration.h"
+#include "ardour/track.h"
+
+#include "faderport.h"
+
+using namespace ARDOUR;
+using namespace ArdourSurface;
+using namespace PBD;
+using namespace Glib;
+using namespace std;
+
+#include "i18n.h"
+
+#include "pbd/abstract_ui.cc" // instantiate template
+
+FaderPort::FaderPort (Session& s)
+	: ControlProtocol (s, _("Faderport"))
+	, AbstractUI<FaderPortRequest> (name())
+	, gui (0)
+	, connection_state (ConnectionState (0))
+	, _device_active (false)
+	, fader_msb (0)
+	, fader_lsb (0)
+	, fader_is_touched (false)
+	, button_state (ButtonState (0))
+	, blink_state (false)
+{
+	last_encoder_time = 0;
+
+	boost::shared_ptr<ARDOUR::Port> inp;
+	boost::shared_ptr<ARDOUR::Port> outp;
+
+	inp  = AudioEngine::instance()->register_input_port (DataType::MIDI, "Faderport Recv", true);
+	outp = AudioEngine::instance()->register_output_port (DataType::MIDI, "Faderport Send", true);
+
+	_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(inp);
+	_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(outp);
+
+	if (_input_port == 0 || _output_port == 0) {
+		throw failed_constructor();
+	}
+
+	_input_bundle.reset (new ARDOUR::Bundle (_("Faderport Support (Receive)"), true));
+	_output_bundle.reset (new ARDOUR::Bundle (_("Faderport Support (Send) "), false));
+
+	_input_bundle->add_channel (
+		inp->name(),
+		ARDOUR::DataType::MIDI,
+		session->engine().make_port_name_non_relative (inp->name())
+		);
+
+	_output_bundle->add_channel (
+		outp->name(),
+		ARDOUR::DataType::MIDI,
+		session->engine().make_port_name_non_relative (outp->name())
+		);
+
+
+	TrackSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort::gui_track_selection_changed, this, _1), this);
+
+	/* Catch port connections and disconnections */
+	ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort::connection_handler, this, _1, _2, _3, _4, _5), this);
+
+	buttons.insert (std::make_pair (Mute, Button (*this, _("Mute"), Mute, 21)));
+	buttons.insert (std::make_pair (Solo, Button (*this, _("Solo"), Solo, 22)));
+	buttons.insert (std::make_pair (Rec, Button (*this, _("Rec"), Rec, 23)));
+	buttons.insert (std::make_pair (Left, Button (*this, _("Left"), Left, 20)));
+	buttons.insert (std::make_pair (Bank, Button (*this, _("Bank"), Bank, 19)));
+	buttons.insert (std::make_pair (Right, Button (*this, _("Right"), Right, 18)));
+	buttons.insert (std::make_pair (Output, Button (*this, _("Output"), Output, 17)));
+	buttons.insert (std::make_pair (FP_Read, Button (*this, _("Read"), FP_Read, 13)));
+	buttons.insert (std::make_pair (FP_Write, Button (*this, _("Write"), FP_Write, 14)));
+	buttons.insert (std::make_pair (FP_Touch, Button (*this, _("Touch"), FP_Touch, 15)));
+	buttons.insert (std::make_pair (FP_Off, Button (*this, _("Off"), FP_Off, 16)));
+	buttons.insert (std::make_pair (Mix, Button (*this, _("Mix"), Mix, 12)));
+	buttons.insert (std::make_pair (Proj, Button (*this, _("Proj"), Proj, 11)));
+	buttons.insert (std::make_pair (Trns, Button (*this, _("Trns"), Trns, 10)));
+	buttons.insert (std::make_pair (Undo, Button (*this, _("Undo"), Undo, 9)));
+	buttons.insert (std::make_pair (Shift, Button (*this, _("Shift"), Shift, 5)));
+	buttons.insert (std::make_pair (Punch, Button (*this, _("Punch"), Punch, 6)));
+	buttons.insert (std::make_pair (User, Button (*this, _("User"), User, 7)));
+	buttons.insert (std::make_pair (Loop, Button (*this, _("Loop"), Loop, 8)));
+	buttons.insert (std::make_pair (Rewind, Button (*this, _("Rewind"), Rewind, 4)));
+	buttons.insert (std::make_pair (Ffwd, Button (*this, _("Ffwd"), Ffwd, 3)));
+	buttons.insert (std::make_pair (Stop, Button (*this, _("Stop"), Stop, 2)));
+	buttons.insert (std::make_pair (Play, Button (*this, _("Play"), Play, 1)));
+	buttons.insert (std::make_pair (RecEnable, Button (*this, _("RecEnable"), RecEnable, 0)));
+	buttons.insert (std::make_pair (FaderTouch, Button (*this, _("Fader (touch)"), FaderTouch, -1)));
+
+	get_button (Shift).set_flash (true);
+	get_button (Mix).set_flash (true);
+	get_button (Proj).set_flash (true);
+	get_button (Trns).set_flash (true);
+	get_button (User).set_flash (true);
+
+	get_button (Left).set_action ( boost::bind (&FaderPort::left, this), true);
+	get_button (Right).set_action ( boost::bind (&FaderPort::right, this), true);
+
+	get_button (Undo).set_action (boost::bind (&FaderPort::undo, this), true);
+	get_button (Undo).set_action (boost::bind (&FaderPort::redo, this), true, ShiftDown);
+	get_button (Undo).set_flash (true);
+
+	get_button (FP_Read).set_action (boost::bind (&FaderPort::read, this), true);
+	get_button (FP_Read).set_action (boost::bind (&FaderPort::off, this), false, LongPress);
+	get_button (FP_Write).set_action (boost::bind (&FaderPort::write, this), true);
+	get_button (FP_Write).set_action (boost::bind (&FaderPort::off, this), false, LongPress);
+	get_button (FP_Touch).set_action (boost::bind (&FaderPort::touch, this), true);
+	get_button (FP_Touch).set_action (boost::bind (&FaderPort::off, this), false, LongPress);
+	get_button (FP_Off).set_action (boost::bind (&FaderPort::off, this), true);
+
+	get_button (Play).set_action (boost::bind (&BasicUI::transport_play, this, true), true);
+	get_button (RecEnable).set_action (boost::bind (&BasicUI::rec_enable_toggle, this), true);
+	/* Stop is a modifier, so we have to use its own button state to get
+	   the default action (since StopDown will be set when looking for the
+	   action to invoke.
+	*/
+	get_button (Stop).set_action (boost::bind (&BasicUI::transport_stop, this), true, StopDown);
+	get_button (Ffwd).set_action (boost::bind (&BasicUI::ffwd, this), true);
+
+	/* See comments about Stop above .. */
+	get_button (Rewind).set_action (boost::bind (&BasicUI::rewind, this), true, RewindDown);
+	get_button (Rewind).set_action (boost::bind (&BasicUI::goto_zero, this), true, ButtonState (RewindDown|StopDown));
+	get_button (Rewind).set_action (boost::bind (&BasicUI::goto_start, this), true, ButtonState (RewindDown|ShiftDown));
+
+	get_button (Ffwd).set_action (boost::bind (&BasicUI::ffwd, this), true);
+	get_button (Ffwd).set_action (boost::bind (&BasicUI::goto_end, this), true, ShiftDown);
+
+	get_button (Punch).set_action (boost::bind (&FaderPort::punch, this), true);
+
+	get_button (Loop).set_action (boost::bind (&BasicUI::loop_toggle, this), true);
+	get_button (Loop).set_action (boost::bind (&BasicUI::add_marker, this, string()), true, ShiftDown);
+
+	get_button (Punch).set_action (boost::bind (&BasicUI::prev_marker, this), true, ShiftDown);
+	get_button (User).set_action (boost::bind (&BasicUI::next_marker, this), true, ButtonState(ShiftDown|UserDown));
+
+	get_button (Mute).set_action (boost::bind (&FaderPort::mute, this), true);
+	get_button (Solo).set_action (boost::bind (&FaderPort::solo, this), true);
+	get_button (Rec).set_action (boost::bind (&FaderPort::rec_enable, this), true);
+
+	get_button (Output).set_action (boost::bind (&FaderPort::use_master, this), true);
+	get_button (Output).set_action (boost::bind (&FaderPort::use_monitor, this), true, ShiftDown);
+}
+
+FaderPort::~FaderPort ()
+{
+	if (_input_port) {
+		DEBUG_TRACE (DEBUG::FaderPort, string_compose ("unregistering input port %1\n", boost::shared_ptr<ARDOUR::Port>(_input_port)->name()));
+		AudioEngine::instance()->unregister_port (_input_port);
+		_input_port.reset ();
+	}
+
+	if (_output_port) {
+//		_output_port->drain (10000);  //ToDo:  is this necessary?  It hangs the shutdown, for me
+		DEBUG_TRACE (DEBUG::FaderPort, string_compose ("unregistering output port %1\n", boost::shared_ptr<ARDOUR::Port>(_output_port)->name()));
+		AudioEngine::instance()->unregister_port (_output_port);
+		_output_port.reset ();
+	}
+
+	tear_down_gui ();
+}
+
+void*
+FaderPort::request_factory (uint32_t num_requests)
+{
+	/* AbstractUI<T>::request_buffer_factory() is a template method only
+	   instantiated in this source module. To provide something visible for
+	   use in the interface/descriptor, we have this static method that is
+	   template-free.
+	*/
+	return request_buffer_factory (num_requests);
+}
+
+void
+FaderPort::start_midi_handling ()
+{
+	/* handle device inquiry response */
+	_input_port->parser()->sysex.connect_same_thread (midi_connections, boost::bind (&FaderPort::sysex_handler, this, _1, _2, _3));
+	/* handle buttons */
+	_input_port->parser()->poly_pressure.connect_same_thread (midi_connections, boost::bind (&FaderPort::button_handler, this, _1, _2));
+	/* handle encoder */
+	_input_port->parser()->pitchbend.connect_same_thread (midi_connections, boost::bind (&FaderPort::encoder_handler, this, _1, _2));
+	/* handle fader */
+	_input_port->parser()->controller.connect_same_thread (midi_connections, boost::bind (&FaderPort::fader_handler, this, _1, _2));
+
+	/* This connection means that whenever data is ready from the input
+	 * port, the relevant thread will invoke our ::midi_input_handler()
+	 * method, which will read the data, and invoke the parser.
+	 */
+
+	_input_port->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &FaderPort::midi_input_handler), _input_port));
+	_input_port->xthread().attach (main_loop()->get_context());
+}
+
+void
+FaderPort::stop_midi_handling ()
+{
+	midi_connections.drop_connections ();
+
+	/* Note: the input handler is still active at this point, but we're no
+	 * longer connected to any of the parser signals
+	 */
+}
+
+void
+FaderPort::do_request (FaderPortRequest* req)
+{
+	if (req->type == CallSlot) {
+
+		call_slot (MISSING_INVALIDATOR, req->the_slot);
+
+	} else if (req->type == Quit) {
+
+		stop ();
+	}
+}
+
+int
+FaderPort::stop ()
+{
+	BaseUI::quit ();
+
+	return 0;
+}
+
+void
+FaderPort::thread_init ()
+{
+	struct sched_param rtparam;
+
+	pthread_set_name (event_loop_name().c_str());
+
+	PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
+	ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
+
+	memset (&rtparam, 0, sizeof (rtparam));
+	rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
+
+	if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
+		// do we care? not particularly.
+	}
+}
+
+void
+FaderPort::all_lights_out ()
+{
+	for (ButtonMap::iterator b = buttons.begin(); b != buttons.end(); ++b) {
+		b->second.set_led_state (_output_port, false);
+	}
+}
+
+FaderPort::Button&
+FaderPort::get_button (ButtonID id) const
+{
+	ButtonMap::const_iterator b = buttons.find (id);
+	assert (b != buttons.end());
+	return const_cast<Button&>(b->second);
+}
+
+bool
+FaderPort::button_long_press_timeout (ButtonID id)
+{
+	if (buttons_down.find (id) != buttons_down.end()) {
+		get_button (id).invoke (ButtonState (LongPress|button_state), false);
+	} else {
+		/* release happened and somehow we were not cancelled */
+	}
+
+	/* whichever button this was, we've used it ... don't invoke the
+	   release action.
+	*/
+	consumed.insert (id);
+
+	return false; /* don't get called again */
+}
+
+void
+FaderPort::start_press_timeout (Button& button, ButtonID id)
+{
+	Glib::RefPtr<Glib::TimeoutSource> timeout = Glib::TimeoutSource::create (500); // milliseconds
+	button.timeout_connection = timeout->connect (sigc::bind (sigc::mem_fun (*this, &FaderPort::button_long_press_timeout), id));
+	timeout->attach (main_loop()->get_context());
+}
+
+void
+FaderPort::button_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb)
+{
+	ButtonID id (ButtonID (tb->controller_number));
+	Button& button (get_button (id));
+
+	DEBUG_TRACE (DEBUG::FaderPort, string_compose ("button event for ID %1 press ? %2\n", (int) tb->controller_number, (tb->value ? "yes" : "no")));
+
+	if (tb->value) {
+		buttons_down.insert (id);
+	} else {
+		buttons_down.erase (id);
+		button.timeout_connection.disconnect ();
+	}
+
+	ButtonState bs (ButtonState (0));
+
+	switch (id) {
+	case Shift:
+		bs = ShiftDown;
+		break;
+	case Stop:
+		bs = StopDown;
+		break;
+	case Rewind:
+		bs = RewindDown;
+		break;
+	case User:
+		bs = UserDown;
+		break;
+	case FaderTouch:
+		fader_is_touched = tb->value;
+		if (_current_route) {
+			boost::shared_ptr<AutomationControl> gain = _current_route->gain_control ();
+			if (gain) {
+				framepos_t now = session->engine().sample_time();
+				if (tb->value) {
+					gain->start_touch (now);
+				} else {
+					gain->stop_touch (true, now);
+				}
+			}
+		}
+		break;
+	default:
+		if (tb->value) {
+			start_press_timeout (button, id);
+		}
+		break;
+	}
+
+	if (bs) {
+		button_state = (tb->value ? ButtonState (button_state|bs) : ButtonState (button_state&~bs));
+		DEBUG_TRACE (DEBUG::FaderPort, string_compose ("reset button state to %1 using %2\n", button_state, (int) bs));
+	}
+
+	if (button.uses_flash()) {
+		button.set_led_state (_output_port, (int)tb->value);
+	}
+
+	set<ButtonID>::iterator c = consumed.find (id);
+
+	if (c == consumed.end()) {
+		button.invoke (button_state, tb->value ? true : false);
+	} else {
+		DEBUG_TRACE (DEBUG::FaderPort, "button was consumed, ignored\n");
+		consumed.erase (c);
+	}
+}
+
+void
+FaderPort::encoder_handler (MIDI::Parser &, MIDI::pitchbend_t pb)
+{
+	int delta = 1;
+
+	if (pb >= 8192) {
+		delta = -1;
+	}
+
+	//knob debouncing and hysteresis.  The presonus encoder often sends bursts of events, or goes the wrong direction
+	{
+		last_last_encoder_delta = last_encoder_delta;
+		last_encoder_delta = delta;
+		microseconds_t now = get_microseconds ();
+		if ((now - last_encoder_time) < 10*1000) { //require at least 10ms interval between changes, because the device sometimes sends multiple deltas
+			return;
+		}
+		if ((now - last_encoder_time) < 100*1000) { //avoid directional changes while "spinning", 100ms window
+			if ( (delta == last_encoder_delta) && (delta == last_last_encoder_delta) ) {
+				last_good_encoder_delta = delta;  //3 in a row, grudgingly accept this as the new direction
+			}
+			if (delta != last_good_encoder_delta) {  //otherwise ensure we keep going the same way
+				delta = last_good_encoder_delta;
+			}
+		} else {  //we aren't yet in a spin window, just assume this move is really what we want
+			//NOTE:  if you are worried about where these get initialized, here it is.
+			last_last_encoder_delta = delta;
+			last_encoder_delta = delta;
+		}
+		last_encoder_time = now;
+		last_good_encoder_delta = delta;
+	}
+
+	if (_current_route) {
+
+		ButtonState trim_modifier;
+		ButtonState width_modifier;
+
+		if (Profile->get_mixbus()) {
+			trim_modifier = ShiftDown;
+			width_modifier = ButtonState (0);
+		} else {
+			trim_modifier = UserDown;
+			width_modifier = ShiftDown;
+		}
+
+		if ((button_state & trim_modifier) == trim_modifier ) {    // mod+encoder = input trim
+			boost::shared_ptr<AutomationControl> trim = _current_route->trim()->gain_control ();
+			if (trim) {
+				float val = trim->get_user();  //for gain elements, the "user" value is in dB
+				val += delta;
+				trim->set_user(val);
+			}
+		} else if (width_modifier && ((button_state & width_modifier) == width_modifier)) {
+			ardour_pan_width (delta);
+
+		} else {  // pan/balance
+			if (!Profile->get_mixbus()) {
+				ardour_pan_azimuth (delta);
+			} else {
+				mixbus_pan (delta);
+			}
+		}
+	}
+
+	/* if the user button was pressed, mark it as consumed so that its
+	 * release action has no effect.
+	 */
+
+	if (!Profile->get_mixbus() && (button_state & UserDown)) {
+		consumed.insert (User);
+	}
+}
+
+void
+FaderPort::fader_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb)
+{
+	bool was_fader = false;
+
+	if (tb->controller_number == 0x0) {
+		fader_msb = tb->value;
+		was_fader = true;
+	} else if (tb->controller_number == 0x20) {
+		fader_lsb = tb->value;
+		was_fader = true;
+	}
+
+	if (was_fader) {
+		if (_current_route) {
+			boost::shared_ptr<AutomationControl> gain = _current_route->gain_control ();
+			if (gain) {
+				int ival = (fader_msb << 7) | fader_lsb;
+				float val = gain->interface_to_internal (ival/16384.0);
+				_current_route->set_gain (val, this);
+			}
+		}
+	}
+}
+
+void
+FaderPort::sysex_handler (MIDI::Parser &p, MIDI::byte *buf, size_t sz)
+{
+        DEBUG_TRACE (DEBUG::FaderPort, string_compose ("sysex message received, size = %1\n", sz));
+
+	if (sz < 17) {
+		return;
+	}
+
+	if (buf[2] != 0x7f ||
+	    buf[3] != 0x06 ||
+	    buf[4] != 0x02 ||
+	    buf[5] != 0x0 ||
+	    buf[6] != 0x1 ||
+	    buf[7] != 0x06 ||
+	    buf[8] != 0x02 ||
+	    buf[9] != 0x0 ||
+	    buf[10] != 0x01 ||
+	    buf[11] != 0x0) {
+		return;
+	}
+
+	_device_active = true;
+
+	DEBUG_TRACE (DEBUG::FaderPort, "FaderPort identified via MIDI Device Inquiry response\n");
+
+	/* put it into native mode */
+
+	MIDI::byte native[3];
+	native[0] = 0x91;
+	native[1] = 0x00;
+	native[2] = 0x64;
+
+	_output_port->write (native, 3, 0);
+
+	all_lights_out ();
+
+	/* catch up on state */
+
+	map_transport_state ();
+	map_recenable_state ();
+}
+
+int
+FaderPort::set_active (bool yn)
+{
+	DEBUG_TRACE (DEBUG::FaderPort, string_compose("Faderport::set_active init with yn: '%1'\n", yn));
+
+	if (yn == active()) {
+		return 0;
+	}
+
+	if (yn) {
+
+		/* start event loop */
+
+		BaseUI::run ();
+
+		connect_session_signals ();
+
+		Glib::RefPtr<Glib::TimeoutSource> blink_timeout = Glib::TimeoutSource::create (200); // milliseconds
+		blink_connection = blink_timeout->connect (sigc::mem_fun (*this, &FaderPort::blink));
+		blink_timeout->attach (main_loop()->get_context());
+
+		Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
+		periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &FaderPort::periodic));
+		periodic_timeout->attach (main_loop()->get_context());
+
+	} else {
+
+		BaseUI::quit ();
+		close ();
+
+	}
+
+	ControlProtocol::set_active (yn);
+
+	DEBUG_TRACE (DEBUG::FaderPort, string_compose("Faderport::set_active done with yn: '%1'\n", yn));
+
+	return 0;
+}
+
+bool
+FaderPort::periodic ()
+{
+	if (!_current_route) {
+		return true;
+	}
+
+	ARDOUR::AutoState gain_state = _current_route->gain_control()->automation_state();
+
+	if (gain_state == ARDOUR::Touch || gain_state == ARDOUR::Play) {
+		map_gain ();
+	}
+
+	return true;
+}
+
+void
+FaderPort::stop_blinking (ButtonID id)
+{
+	blinkers.remove (id);
+	get_button (id).set_led_state (_output_port, false);
+}
+
+void
+FaderPort::start_blinking (ButtonID id)
+{
+	blinkers.push_back (id);
+	get_button (id).set_led_state (_output_port, true);
+}
+
+bool
+FaderPort::blink ()
+{
+	blink_state = !blink_state;
+
+	for (Blinkers::iterator b = blinkers.begin(); b != blinkers.end(); b++) {
+		get_button(*b).set_led_state (_output_port, blink_state);
+	}
+
+	return true;
+}
+
+void
+FaderPort::close ()
+{
+	all_lights_out ();
+
+	stop_midi_handling ();
+	session_connections.drop_connections ();
+	port_connection.disconnect ();
+	blink_connection.disconnect ();
+	selection_connection.disconnect ();
+	route_connections.drop_connections ();
+
+#if 0
+	route_connections.drop_connections ();
+#endif
+}
+
+void
+FaderPort::map_recenable_state ()
+{
+	switch (session->record_status()) {
+	case Session::Disabled:
+		stop_blinking (RecEnable);
+		break;
+	case Session::Enabled:
+		start_blinking (RecEnable);
+		break;
+	case Session::Recording:
+		stop_blinking (RecEnable);
+		break;
+	}
+}
+
+void
+FaderPort::map_transport_state ()
+{
+	get_button (Loop).set_led_state (_output_port, session->get_play_loop());
+
+	float ts = session->transport_speed();
+
+	if (ts == 0) {
+		stop_blinking (Play);
+	} else if (fabs (ts) == 1.0) {
+		stop_blinking (Play);
+		get_button (Play).set_led_state (_output_port, true);
+	} else {
+		start_blinking (Play);
+	}
+
+	get_button (Stop).set_led_state (_output_port, session->transport_stopped ());
+	get_button (Rewind).set_led_state (_output_port, session->transport_speed() < 0.0);
+	get_button (Ffwd).set_led_state (_output_port, session->transport_speed() > 1.0);
+}
+
+void
+FaderPort::parameter_changed (string what)
+{
+	if (what == "punch-in" || what == "punch-out") {
+		bool in = session->config.get_punch_in ();
+		bool out = session->config.get_punch_out ();
+		if (in && out) {
+			get_button (Punch).set_led_state (_output_port, true);
+			blinkers.remove (Punch);
+		} else if (in || out) {
+			start_blinking (Punch);
+		} else {
+			stop_blinking (Punch);
+		}
+	}
+}
+
+void
+FaderPort::connect_session_signals()
+{
+	session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_recenable_state, this), this);
+	session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_transport_state, this), this);
+	/* not session, but treat it similarly */
+	session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::parameter_changed, this, _1), this);
+}
+
+bool
+FaderPort::midi_input_handler (Glib::IOCondition ioc, boost::shared_ptr<ARDOUR::AsyncMIDIPort> port)
+{
+	DEBUG_TRACE (DEBUG::FaderPort, string_compose ("something happend on  %1\n", boost::shared_ptr<MIDI::Port>(port)->name()));
+
+	if (ioc & ~IO_IN) {
+		return false;
+	}
+
+	if (ioc & IO_IN) {
+
+		port->clear ();
+		DEBUG_TRACE (DEBUG::FaderPort, string_compose ("data available on %1\n", boost::shared_ptr<MIDI::Port>(port)->name()));
+		framepos_t now = session->engine().sample_time();
+		port->parse (now);
+	}
+
+	return true;
+}
+
+
+XMLNode&
+FaderPort::get_state ()
+{
+	XMLNode& node (ControlProtocol::get_state());
+
+	XMLNode* child;
+
+	child = new XMLNode (X_("Input"));
+	child->add_child_nocopy (boost::shared_ptr<ARDOUR::Port>(_input_port)->get_state());
+	node.add_child_nocopy (*child);
+
+
+	child = new XMLNode (X_("Output"));
+	child->add_child_nocopy (boost::shared_ptr<ARDOUR::Port>(_output_port)->get_state());
+	node.add_child_nocopy (*child);
+
+	/* Save action state for Mix, Proj, Trns and User buttons, since these
+	 * are user controlled. We can only save named-action operations, since
+	 * internal functions are just pointers to functions and hard to
+	 * serialize without enumerating them all somewhere.
+	 */
+
+	node.add_child_nocopy (get_button (Mix).get_state());
+	node.add_child_nocopy (get_button (Proj).get_state());
+	node.add_child_nocopy (get_button (Trns).get_state());
+	node.add_child_nocopy (get_button (User).get_state());
+
+	return node;
+}
+
+int
+FaderPort::set_state (const XMLNode& node, int version)
+{
+	XMLNodeList nlist;
+	XMLNodeConstIterator niter;
+	XMLNode const* child;
+
+	if (ControlProtocol::set_state (node, version)) {
+		return -1;
+	}
+
+	if ((child = node.child (X_("Input"))) != 0) {
+		XMLNode* portnode = child->child (Port::state_node_name.c_str());
+		if (portnode) {
+			boost::shared_ptr<ARDOUR::Port>(_input_port)->set_state (*portnode, version);
+		}
+	}
+
+	if ((child = node.child (X_("Output"))) != 0) {
+		XMLNode* portnode = child->child (Port::state_node_name.c_str());
+		if (portnode) {
+			boost::shared_ptr<ARDOUR::Port>(_output_port)->set_state (*portnode, version);
+		}
+	}
+
+	for (XMLNodeList::const_iterator n = node.children().begin(); n != node.children().end(); ++n) {
+		if ((*n)->name() == X_("Button")) {
+			XMLProperty const * prop = (*n)->property (X_("id"));
+			if (!prop) {
+				continue;
+			}
+			int xid = atoi (prop->value());
+			ButtonMap::iterator b = buttons.find (ButtonID (xid));
+			if (b == buttons.end()) {
+				continue;
+			}
+			b->second.set_state (**n);
+		}
+	}
+
+	return 0;
+}
+
+bool
+FaderPort::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
+{
+	DEBUG_TRACE (DEBUG::FaderPort, "FaderPort::connection_handler  start\n");
+	if (!_input_port || !_output_port) {
+		return false;
+	}
+
+	string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_input_port)->name());
+	string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_output_port)->name());
+
+	if (ni == name1 || ni == name2) {
+		if (yn) {
+			connection_state |= InputConnected;
+		} else {
+			connection_state &= ~InputConnected;
+		}
+	} else if (no == name1 || no == name2) {
+		if (yn) {
+			connection_state |= OutputConnected;
+		} else {
+			connection_state &= ~OutputConnected;
+		}
+	} else {
+		DEBUG_TRACE (DEBUG::FaderPort, string_compose ("Connections between %1 and %2 changed, but I ignored it\n", name1, name2));
+		/* not our ports */
+		return false;
+	}
+
+	if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
+
+		/* XXX this is a horrible hack. Without a short sleep here,
+		   something prevents the device wakeup messages from being
+		   sent and/or the responses from being received.
+		*/
+
+		g_usleep (100000);
+                DEBUG_TRACE (DEBUG::FaderPort, "device now connected for both input and output\n");
+		connected ();
+
+	} else {
+		DEBUG_TRACE (DEBUG::FaderPort, "Device disconnected (input or output or both) or not yet fully connected\n");
+		_device_active = false;
+	}
+
+	ConnectionChange (); /* emit signal for our GUI */
+
+	DEBUG_TRACE (DEBUG::FaderPort, "FaderPort::connection_handler  end\n");
+
+	return true; /* connection status changed */
+}
+
+void
+FaderPort::connected ()
+{
+	DEBUG_TRACE (DEBUG::FaderPort, "sending device inquiry message...\n");
+
+	start_midi_handling ();
+
+	/* send device inquiry */
+
+	MIDI::byte buf[6];
+
+	buf[0] = 0xf0;
+	buf[1] = 0x7e;
+	buf[2] = 0x7f;
+	buf[3] = 0x06;
+	buf[4] = 0x01;
+	buf[5] = 0xf7;
+
+	_output_port->write (buf, 6, 0);
+}
+
+void
+FaderPort::Button::invoke (FaderPort::ButtonState bs, bool press)
+{
+	DEBUG_TRACE (DEBUG::FaderPort, string_compose ("invoke button %1 for %2 state %3%4%5\n", id, (press ? "press":"release"), hex, bs, dec));
+
+	ToDoMap::iterator x;
+
+	if (press) {
+		if ((x = on_press.find (bs)) == on_press.end()) {
+			DEBUG_TRACE (DEBUG::FaderPort, string_compose ("no press action for button %1 state %2 @ %3 in %4\n", id, bs, this, &on_press));
+			return;
+		}
+	} else {
+		if ((x = on_release.find (bs)) == on_release.end()) {
+			DEBUG_TRACE (DEBUG::FaderPort, string_compose ("no release action for button %1 state %2 @%3 in %4\n", id, bs, this, &on_release));
+			return;
+		}
+	}
+
+	switch (x->second.type) {
+	case NamedAction:
+		if (!x->second.action_name.empty()) {
+			fp.access_action (x->second.action_name);
+		}
+		break;
+	case InternalFunction:
+		if (x->second.function) {
+			x->second.function ();
+		}
+	}
+}
+
+void
+FaderPort::Button::set_action (string const& name, bool when_pressed, FaderPort::ButtonState bs)
+{
+	ToDo todo;
+
+	todo.type = NamedAction;
+
+	if (when_pressed) {
+		if (name.empty()) {
+			on_press.erase (bs);
+		} else {
+			DEBUG_TRACE (DEBUG::FaderPort, string_compose ("set button %1 to action %2 on press + %3%4%5\n", id, name, bs));
+			todo.action_name = name;
+			on_press[bs] = todo;
+		}
+	} else {
+		if (name.empty()) {
+			on_release.erase (bs);
+		} else {
+			DEBUG_TRACE (DEBUG::FaderPort, string_compose ("set button %1 to action %2 on release + %3%4%5\n", id, name, bs));
+			todo.action_name = name;
+			on_release[bs] = todo;
+		}
+	}
+}
+
+string
+FaderPort::Button::get_action (bool press, FaderPort::ButtonState bs)
+{
+	ToDoMap::iterator x;
+
+	if (press) {
+		if ((x = on_press.find (bs)) == on_press.end()) {
+			return string();
+		}
+		if (x->second.type != NamedAction) {
+			return string ();
+		}
+		return x->second.action_name;
+	} else {
+		if ((x = on_release.find (bs)) == on_release.end()) {
+			return string();
+		}
+		if (x->second.type != NamedAction) {
+			return string ();
+		}
+		return x->second.action_name;
+	}
+}
+
+void
+FaderPort::Button::set_action (boost::function<void()> f, bool when_pressed, FaderPort::ButtonState bs)
+{
+	ToDo todo;
+	todo.type = InternalFunction;
+
+	if (when_pressed) {
+		DEBUG_TRACE (DEBUG::FaderPort, string_compose ("set button %1 (%2) @ %5 to some functor on press + %3 in %4\n", id, name, bs, &on_press, this));
+		todo.function = f;
+		on_press[bs] = todo;
+	} else {
+		DEBUG_TRACE (DEBUG::FaderPort, string_compose ("set button %1 (%2) @ %5 to some functor on release + %3\n", id, name, bs, this));
+		todo.function = f;
+		on_release[bs] = todo;
+	}
+}
+
+void
+FaderPort::Button::set_led_state (boost::shared_ptr<MIDI::Port> port, bool onoff)
+{
+	if (out < 0) {
+		/* fader button ID - no LED */
+		return;
+	}
+
+	MIDI::byte buf[3];
+	buf[0] = 0xa0;
+	buf[1] = out;
+	buf[2] = onoff ? 1 : 0;
+	port->write (buf, 3, 0);
+}
+
+int
+FaderPort::Button::set_state (XMLNode const& node)
+{
+	const XMLProperty* prop = node.property ("id");
+	if (!prop) {
+		return -1;
+	}
+
+	int xid = atoi (prop->value());
+	if (xid != id) {
+		return -1;
+	}
+
+	typedef pair<string,FaderPort::ButtonState> state_pair_t;
+	vector<state_pair_t> state_pairs;
+
+	state_pairs.push_back (make_pair (string ("plain"), ButtonState (0)));
+	state_pairs.push_back (make_pair (string ("shift"), ShiftDown));
+	state_pairs.push_back (make_pair (string ("long"), LongPress));
+
+	for (vector<state_pair_t>::const_iterator sp = state_pairs.begin(); sp != state_pairs.end(); ++sp) {
+		string propname;
+
+		propname = sp->first + X_("-press");
+		if ((prop = node.property (propname)) != 0) {
+			set_action (prop->value(), true, sp->second);
+		}
+
+		propname = sp->first + X_("-release");
+		if ((prop = node.property (propname)) != 0) {
+			set_action (prop->value(), false, sp->second);
+		}
+	}
+
+	return 0;
+}
+
+XMLNode&
+FaderPort::Button::get_state () const
+{
+	XMLNode* node = new XMLNode (X_("Button"));
+	char buf[16];
+	snprintf (buf, sizeof (buf), "%d", id);
+
+	node->add_property (X_("id"), buf);
+
+	ToDoMap::const_iterator x;
+	ToDo null;
+	null.type = NamedAction;
+
+	typedef pair<string,FaderPort::ButtonState> state_pair_t;
+	vector<state_pair_t> state_pairs;
+
+	state_pairs.push_back (make_pair (string ("plain"), ButtonState (0)));
+	state_pairs.push_back (make_pair (string ("shift"), ShiftDown));
+	state_pairs.push_back (make_pair (string ("long"), LongPress));
+
+	for (vector<state_pair_t>::const_iterator sp = state_pairs.begin(); sp != state_pairs.end(); ++sp) {
+		if ((x = on_press.find (sp->second)) != on_press.end()) {
+			if (x->second.type == NamedAction) {
+				node->add_property (string (sp->first + X_("-press")).c_str(), x->second.action_name);
+			}
+		}
+
+		if ((x = on_release.find (sp->second)) != on_release.end()) {
+			if (x->second.type == NamedAction) {
+				node->add_property (string (sp->first + X_("-release")).c_str(), x->second.action_name);
+			}
+		}
+	}
+
+	return *node;
+}
+
+void
+FaderPort::gui_track_selection_changed (RouteNotificationListPtr routes)
+{
+	boost::shared_ptr<Route> r;
+
+	if (!routes->empty()) {
+		r = routes->front().lock();
+	}
+
+	set_current_route (r);
+}
+
+void
+FaderPort::drop_current_route ()
+{
+	if (_current_route) {
+		if (_current_route == session->monitor_out()) {
+			set_current_route (session->master_out());
+		} else {
+			set_current_route (boost::shared_ptr<Route>());
+		}
+	}
+}
+
+void
+FaderPort::set_current_route (boost::shared_ptr<Route> r)
+{
+	route_connections.drop_connections ();
+
+	_current_route = r;
+
+	/* turn this off. It will be turned on back on in use_master() or
+	   use_monitor() as appropriate.
+	*/
+	get_button(Output).set_led_state (_output_port, false);
+
+	if (_current_route) {
+		_current_route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::drop_current_route, this), this);
+
+		_current_route->mute_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_mute, this, _1), this);
+		_current_route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_solo, this, _1, _2, _3), this);
+		_current_route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_listen, this, _1, _2), this);
+
+		boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (_current_route);
+		if (t) {
+			t->RecordEnableChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_recenable, this), this);
+		}
+
+		boost::shared_ptr<AutomationControl> control = _current_route->gain_control ();
+		if (control) {
+			control->Changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_gain, this), this);
+			control->alist()->automation_state_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_auto, this), this);
+		}
+
+		boost::shared_ptr<MonitorProcessor> mp = _current_route->monitor_control();
+		if (mp) {
+			mp->cut_control()->Changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort::map_cut, this), this);
+		}
+	}
+
+	//ToDo: subscribe to the fader automation modes so we can light the LEDs
+
+	map_route_state ();
+}
+
+void
+FaderPort::map_auto ()
+{
+	/* Under no circumstances send a message to "enable" the LED state of
+	 * the Off button, because this will disable the fader.
+	 */
+
+	boost::shared_ptr<AutomationControl> control = _current_route->gain_control ();
+	const AutoState as = control->automation_state ();
+
+	switch (as) {
+		case ARDOUR::Play:
+			get_button (FP_Read).set_led_state (_output_port, true);
+			get_button (FP_Write).set_led_state (_output_port, false);
+			get_button (FP_Touch).set_led_state (_output_port, false);
+		break;
+		case ARDOUR::Write:
+			get_button (FP_Read).set_led_state (_output_port, false);
+			get_button (FP_Write).set_led_state (_output_port, true);
+			get_button (FP_Touch).set_led_state (_output_port, false);
+		break;
+		case ARDOUR::Touch:
+			get_button (FP_Read).set_led_state (_output_port, false);
+			get_button (FP_Write).set_led_state (_output_port, false);
+			get_button (FP_Touch).set_led_state (_output_port, true);
+		break;
+		case ARDOUR::Off:
+			get_button (FP_Read).set_led_state (_output_port, false);
+			get_button (FP_Write).set_led_state (_output_port, false);
+			get_button (FP_Touch).set_led_state (_output_port, false);
+		break;
+	}
+
+}
+
+
+void
+FaderPort::map_cut ()
+{
+	boost::shared_ptr<MonitorProcessor> mp = _current_route->monitor_control();
+
+	if (mp) {
+		bool yn = mp->cut_all ();
+		if (yn) {
+			start_blinking (Mute);
+		} else {
+			stop_blinking (Mute);
+		}
+	} else {
+		stop_blinking (Mute);
+	}
+}
+
+void
+FaderPort::map_mute (void*)
+{
+	if (_current_route) {
+		if (_current_route->muted()) {
+			stop_blinking (Mute);
+			get_button (Mute).set_led_state (_output_port, true);
+		} else if (_current_route->muted_by_others()) {
+			start_blinking (Mute);
+		} else {
+			stop_blinking (Mute);
+		}
+	} else {
+		stop_blinking (Mute);
+	}
+}
+
+void
+FaderPort::map_solo (bool, void*, bool)
+{
+	if (_current_route) {
+		get_button (Solo).set_led_state (_output_port, _current_route->soloed() || _current_route->listening_via_monitor());
+	} else {
+		get_button (Solo).set_led_state (_output_port, false);
+	}
+}
+
+void
+FaderPort::map_listen (void*, bool)
+{
+	if (_current_route) {
+		get_button (Solo).set_led_state (_output_port, _current_route->listening_via_monitor());
+	} else {
+		get_button (Solo).set_led_state (_output_port, false);
+	}
+}
+
+void
+FaderPort::map_recenable ()
+{
+	boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (_current_route);
+	if (t) {
+		get_button (Rec).set_led_state (_output_port, t->record_enabled());
+	} else {
+		get_button (Rec).set_led_state (_output_port, false);
+	}
+}
+
+void
+FaderPort::map_gain ()
+{
+	if (fader_is_touched) {
+		/* Do not send fader moves while the user is touching the fader */
+		return;
+	}
+
+	if (!_current_route) {
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> control = _current_route->gain_control ();
+	double val;
+
+	if (!control) {
+		val = 0.0;
+	} else {
+		val = control->internal_to_interface (control->get_value ());
+	}
+
+	/* Faderport sends fader position with range 0..16384 (though some of
+	 * the least-significant bits at the top end are missing - it may only
+	 * get to 1636X or so).
+	 *
+	 * But ... position must be sent in the range 0..1023.
+	 *
+	 * Thanks, Obama.
+	 */
+
+	int ival = (int) lrintf (val * 1023.0);
+
+	/* MIDI normalization requires that we send two separate messages here,
+	 * not one single 6 byte one.
+	 */
+
+	MIDI::byte buf[3];
+
+	buf[0] = 0xb0;
+	buf[1] = 0x0;
+	buf[2] = ival >> 7;
+
+	_output_port->write (buf, 3, 0);
+
+	buf[1] = 0x20;
+	buf[2] = ival & 0x7f;
+
+	_output_port->write (buf, 3, 0);
+}
+
+void
+FaderPort::map_route_state ()
+{
+	if (!_current_route) {
+		stop_blinking (Mute);
+		stop_blinking (Solo);
+		get_button (Rec).set_led_state (_output_port, false);
+	} else {
+		/* arguments to these map_*() methods are all ignored */
+		map_solo (false, 0, false);
+		map_recenable ();
+		map_gain ();
+		map_auto ();
+
+		if (_current_route == session->monitor_out()) {
+			map_cut ();
+		} else {
+			map_mute (0);
+		}
+	}
+}
+
+list<boost::shared_ptr<ARDOUR::Bundle> >
+FaderPort::bundles ()
+{
+	list<boost::shared_ptr<ARDOUR::Bundle> > b;
+
+	if (_input_bundle) {
+		b.push_back (_input_bundle);
+		b.push_back (_output_bundle);
+	}
+
+	return b;
+}
+
+boost::shared_ptr<Port>
+FaderPort::output_port()
+{
+	return _output_port;
+}
+
+boost::shared_ptr<Port>
+FaderPort::input_port()
+{
+	return _input_port;
+}
+
+void
+FaderPort::set_action (ButtonID id, std::string const& action_name, bool on_press, ButtonState bs)
+{
+	get_button(id).set_action (action_name, on_press, bs);
+}
+
+string
+FaderPort::get_action (ButtonID id, bool press, ButtonState bs)
+{
+	return get_button(id).get_action (press, bs);
+}
diff --git a/libs/surfaces/faderport/faderport.h b/libs/surfaces/faderport/faderport.h
new file mode 100644
index 0000000..025cf09
--- /dev/null
+++ b/libs/surfaces/faderport/faderport.h
@@ -0,0 +1,340 @@
+/*
+    Copyright (C) 2006 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef ardour_surface_faderport_h
+#define ardour_surface_faderport_h
+
+#include <list>
+#include <map>
+#include <set>
+#include <glibmm/threads.h>
+
+#define ABSTRACT_UI_EXPORTS
+#include "pbd/abstract_ui.h"
+
+#include "ardour/types.h"
+
+#include "control_protocol/control_protocol.h"
+
+namespace PBD {
+	class Controllable;
+	class ControllableDescriptor;
+}
+
+#include <midi++/types.h>
+
+//#include "pbd/signals.h"
+
+
+//#include "midi_byte_array.h"
+#include "types.h"
+
+#include "glibmm/main.h"
+
+namespace MIDI {
+	class Parser;
+	class Port;
+}
+
+
+namespace ARDOUR {
+	class AsyncMIDIPort;
+	class Bundle;
+	class Port;
+	class Session;
+	class MidiPort;
+}
+
+
+class MIDIControllable;
+class MIDIFunction;
+class MIDIAction;
+
+namespace ArdourSurface {
+
+struct FaderPortRequest : public BaseUI::BaseRequestObject {
+public:
+	FaderPortRequest () {}
+	~FaderPortRequest () {}
+};
+
+class FaderPort : public ARDOUR::ControlProtocol, public AbstractUI<FaderPortRequest> {
+  public:
+	FaderPort (ARDOUR::Session&);
+	virtual ~FaderPort();
+
+	int set_active (bool yn);
+
+	/* we probe for a device when our ports are connected. Before that,
+	   there's no way to know if the device exists or not.
+	 */
+	static bool probe() { return true; }
+	static void* request_factory (uint32_t);
+
+	XMLNode& get_state ();
+	int set_state (const XMLNode&, int version);
+
+	bool has_editor () const { return true; }
+	void* get_gui () const;
+	void  tear_down_gui ();
+
+	/* Note: because the FaderPort speaks an inherently duplex protocol,
+	   we do not implement get/set_feedback() since this aspect of
+	   support for the protocol is not optional.
+	*/
+
+	void do_request (FaderPortRequest*);
+	int stop ();
+
+	void thread_init ();
+
+	PBD::Signal0<void> ConnectionChange;
+
+	boost::shared_ptr<ARDOUR::Port> input_port();
+	boost::shared_ptr<ARDOUR::Port> output_port();
+
+	/* In a feat of engineering brilliance, the Presonus Faderport sends
+	 * one button identifier when the button is pressed/released, but
+	 * responds to another button identifier as a command to light the LED
+	 * corresponding to the button. These ID's define what is sent
+	 * for press/release; a separate data structure contains information
+	 * on what to send to turn the LED on/off.
+	 *
+	 * One can only conclude that Presonus just didn't want to fix this
+	 * issue because it contradicts their own documentation and is more or
+	 * less the first thing you discover when programming the device.
+	 */
+
+	enum ButtonID {
+		Mute = 18,
+		Solo = 17,
+		Rec = 16,
+		Left = 19,
+		Bank = 20,
+		Right = 21,
+		Output = 22,
+		FP_Read = 10,
+		FP_Write = 9,
+		FP_Touch = 8,
+		FP_Off = 23,
+		Mix = 11,
+		Proj = 12,
+		Trns = 13,
+		Undo = 14,
+		Shift = 2,
+		Punch = 1,
+		User = 0,
+		Loop = 15,
+		Rewind = 3,
+		Ffwd = 4,
+		Stop = 5,
+		Play = 6,
+		RecEnable = 7,
+		FaderTouch = 127,
+	};
+
+	enum ButtonState {
+		ShiftDown = 0x1,
+		RewindDown = 0x2,
+		StopDown = 0x4,
+		UserDown = 0x8,
+		LongPress = 0x10
+	};
+
+	void set_action (ButtonID, std::string const& action_name, bool on_press, FaderPort::ButtonState = ButtonState (0));
+	std::string get_action (ButtonID, bool on_press, FaderPort::ButtonState = ButtonState (0));
+
+	std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
+
+  private:
+	boost::shared_ptr<ARDOUR::Route> _current_route;
+	boost::weak_ptr<ARDOUR::Route> pre_master_route;
+	boost::weak_ptr<ARDOUR::Route> pre_monitor_route;
+
+	boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
+	boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
+
+	// Bundle to represent our input ports
+	boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
+	// Bundle to represent our output ports
+	boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
+
+	PBD::ScopedConnectionList midi_connections;
+
+	bool midi_input_handler (Glib::IOCondition ioc, boost::shared_ptr<ARDOUR::AsyncMIDIPort> port);
+
+	mutable void *gui;
+	void build_gui ();
+
+	bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
+	PBD::ScopedConnection port_connection;
+
+	enum ConnectionState {
+		InputConnected = 0x1,
+		OutputConnected = 0x2
+	};
+
+	int connection_state;
+	void connected ();
+	bool _device_active;
+	int fader_msb;
+	int fader_lsb;
+	bool fader_is_touched;
+
+	ARDOUR::microseconds_t last_encoder_time;
+	int last_good_encoder_delta;
+	int last_encoder_delta, last_last_encoder_delta;
+
+	void sysex_handler (MIDI::Parser &p, MIDI::byte *, size_t);
+	void button_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
+	void encoder_handler (MIDI::Parser &, MIDI::pitchbend_t pb);
+	void fader_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
+
+	ButtonState button_state;
+
+	friend class Button;
+
+	class Button {
+	  public:
+
+		enum ActionType {
+			NamedAction,
+			InternalFunction,
+		};
+
+		Button (FaderPort& f, std::string const& str, ButtonID i, int o)
+			: fp (f)
+			, name (str)
+			, id (i)
+			, out (o)
+			, flash (false)
+		{}
+
+		void set_action (std::string const& action_name, bool on_press, FaderPort::ButtonState = ButtonState (0));
+		void set_action (boost::function<void()> function, bool on_press, FaderPort::ButtonState = ButtonState (0));
+		std::string get_action (bool press, FaderPort::ButtonState bs = ButtonState (0));
+
+		void set_led_state (boost::shared_ptr<MIDI::Port>, bool onoff);
+		void invoke (ButtonState bs, bool press);
+		bool uses_flash () const { return flash; }
+		void set_flash (bool yn) { flash = yn; }
+
+		XMLNode& get_state () const;
+		int set_state (XMLNode const&);
+
+		sigc::connection timeout_connection;
+
+	  private:
+		FaderPort& fp;
+		std::string name;
+		ButtonID id;
+		int out;
+		bool flash;
+
+		struct ToDo {
+			ActionType type;
+			/* could be a union if boost::function didn't require a
+			 * constructor
+			 */
+			std::string action_name;
+			boost::function<void()> function;
+		};
+
+		typedef std::map<FaderPort::ButtonState,ToDo> ToDoMap;
+		ToDoMap on_press;
+		ToDoMap on_release;
+	};
+
+	typedef std::map<ButtonID,Button> ButtonMap;
+
+	ButtonMap buttons;
+	Button& get_button (ButtonID) const;
+
+	std::set<ButtonID> buttons_down;
+	std::set<ButtonID> consumed;
+
+	bool button_long_press_timeout (ButtonID id);
+	void start_press_timeout (Button&, ButtonID);
+
+	void all_lights_out ();
+	void close ();
+	void start_midi_handling ();
+	void stop_midi_handling ();
+
+	PBD::ScopedConnectionList session_connections;
+	void connect_session_signals ();
+	void map_recenable_state ();
+	void map_transport_state ();
+
+	sigc::connection periodic_connection;
+	bool periodic ();
+
+	sigc::connection blink_connection;
+	typedef std::list<ButtonID> Blinkers;
+	Blinkers blinkers;
+	bool blink_state;
+	bool blink ();
+	void start_blinking (ButtonID);
+	void stop_blinking (ButtonID);
+
+	void set_current_route (boost::shared_ptr<ARDOUR::Route>);
+	void drop_current_route ();
+	void use_master ();
+	void use_monitor ();
+	void gui_track_selection_changed (ARDOUR::RouteNotificationListPtr);
+	PBD::ScopedConnection selection_connection;
+	PBD::ScopedConnectionList route_connections;
+
+	void map_route_state ();
+	void map_solo (bool,void*,bool);
+	void map_listen (void*,bool);
+	void map_mute (void*);
+	void map_recenable ();
+	void map_gain ();
+	void map_cut ();
+	void map_auto ();
+	void parameter_changed (std::string);
+
+	/* operations (defined in operations.cc) */
+
+	void read ();
+	void write ();
+
+	void left ();
+	void right ();
+
+	void touch ();
+	void off ();
+
+	void undo ();
+	void redo ();
+	void solo ();
+	void mute ();
+	void rec_enable ();
+
+	void ardour_pan_azimuth (int);
+	void ardour_pan_width (int);
+	void mixbus_pan (int);
+
+	void punch ();
+};
+
+}
+
+#endif /* ardour_surface_faderport_h */
diff --git a/libs/surfaces/generic_midi/interface.cc b/libs/surfaces/faderport/faderport_interface.cc
similarity index 53%
copy from libs/surfaces/generic_midi/interface.cc
copy to libs/surfaces/faderport/faderport_interface.cc
index b7e7b63..e7ea5af 100644
--- a/libs/surfaces/generic_midi/interface.cc
+++ b/libs/surfaces/faderport/faderport_interface.cc
@@ -20,53 +20,60 @@
 #include <pbd/failed_constructor.h>
 
 #include "control_protocol/control_protocol.h"
-#include "generic_midi_control_protocol.h"
+#include "faderport.h"
 
 using namespace ARDOUR;
+using namespace ArdourSurface;
 
 static ControlProtocol*
-new_generic_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, Session* s)
+new_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, Session* s)
 {
-	GenericMidiControlProtocol* gmcp;
+	FaderPort* fp;
 
 	try {
-		gmcp =  new GenericMidiControlProtocol (*s);
+		fp =  new FaderPort (*s);
 	} catch (failed_constructor& err) {
 		return 0;
 	}
 
-	if (gmcp->set_active (true)) {
-		delete gmcp;
+	if (fp->set_active (true)) {
+		delete fp;
 		return 0;
 	}
 
-	return gmcp;
+	return fp;
 }
 
 static void
-delete_generic_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, ControlProtocol* cp)
+delete_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, ControlProtocol* cp)
 {
 	delete cp;
 }
 
 static bool
-probe_generic_midi_protocol (ControlProtocolDescriptor* /*descriptor*/)
+probe_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/)
 {
-	return GenericMidiControlProtocol::probe ();
+	return FaderPort::probe ();
 }
 
-// Field names commented out by JE - 06-01-2010
-static ControlProtocolDescriptor generic_midi_descriptor = {
-	/*name :              */   "Generic MIDI",
-	/*id :                */   "uri://ardour.org/surfaces/generic_midi:0",
+static void*
+faderport_request_buffer_factory (uint32_t num_requests)
+{
+	return FaderPort::request_factory (num_requests);
+}
+
+static ControlProtocolDescriptor faderport_midi_descriptor = {
+	/*name :              */   "Faderport",
+	/*id :                */   "uri://ardour.org/surfaces/faderport:0",
 	/*ptr :               */   0,
 	/*module :            */   0,
 	/*mandatory :         */   0,
 	/*supports_feedback : */   true,
-	/*probe :             */   probe_generic_midi_protocol,
-	/*initialize :        */   new_generic_midi_protocol,
-	/*destroy :           */   delete_generic_midi_protocol
+	/*probe :             */   probe_faderport_midi_protocol,
+	/*initialize :        */   new_faderport_midi_protocol,
+	/*destroy :           */   delete_faderport_midi_protocol,
+	/*request_buffer_factory */ faderport_request_buffer_factory
 };
 
-extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &generic_midi_descriptor; }
+extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &faderport_midi_descriptor; }
 
diff --git a/libs/surfaces/faderport/gui.cc b/libs/surfaces/faderport/gui.cc
new file mode 100644
index 0000000..702ba26
--- /dev/null
+++ b/libs/surfaces/faderport/gui.cc
@@ -0,0 +1,635 @@
+/*
+    Copyright (C) 2015 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <gtkmm/alignment.h>
+#include <gtkmm/label.h>
+#include <gtkmm/liststore.h>
+
+#include "pbd/unwind.h"
+#include "pbd/strsplit.h"
+#include "pbd/file_utils.h"
+
+#include "gtkmm2ext/actions.h"
+#include "gtkmm2ext/gtk_ui.h"
+#include "gtkmm2ext/gui_thread.h"
+#include "gtkmm2ext/utils.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/filesystem_paths.h"
+
+#include "faderport.h"
+#include "gui.h"
+
+#include "i18n.h"
+
+using namespace PBD;
+using namespace ARDOUR;
+using namespace ArdourSurface;
+using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+
+void*
+FaderPort::get_gui () const
+{
+	if (!gui) {
+		const_cast<FaderPort*>(this)->build_gui ();
+	}
+	static_cast<Gtk::VBox*>(gui)->show_all();
+	return gui;
+}
+
+void
+FaderPort::tear_down_gui ()
+{
+	if (gui) {
+		Gtk::Widget *w = static_cast<Gtk::VBox*>(gui)->get_parent();
+		if (w) {
+			w->hide();
+			delete w;
+		}
+	}
+	delete static_cast<FPGUI*> (gui);
+	gui = 0;
+}
+
+void
+FaderPort::build_gui ()
+{
+	gui = (void*) new FPGUI (*this);
+}
+
+/*--------------------*/
+
+FPGUI::FPGUI (FaderPort& p)
+	: fp (p)
+	, table (2, 5)
+	, action_table (4, 4)
+	, ignore_active_change (false)
+{
+	set_border_width (12);
+
+	table.set_row_spacings (4);
+	table.set_col_spacings (6);
+	table.set_border_width (12);
+	table.set_homogeneous (false);
+
+	std::string data_file_path;
+	string name = "faderport-small.png";
+	Searchpath spath(ARDOUR::ardour_data_search_path());
+	spath.add_subdirectory_to_paths ("icons");
+	find_file (spath, name, data_file_path);
+	if (!data_file_path.empty()) {
+		image.set (data_file_path);
+		hpacker.pack_start (image, false, false);
+	}
+
+	Gtk::Label* l;
+	Gtk::Alignment* align;
+	int row = 0;
+
+	input_combo.pack_start (midi_port_columns.short_name);
+	output_combo.pack_start (midi_port_columns.short_name);
+
+	input_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &FPGUI::active_port_changed), &input_combo, true));
+	output_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &FPGUI::active_port_changed), &output_combo, false));
+
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Incoming MIDI on:")));
+	l->set_alignment (1.0, 0.5);
+	table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
+	table.attach (input_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
+	row++;
+
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Outgoing MIDI on:")));
+	l->set_alignment (1.0, 0.5);
+	table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
+	table.attach (output_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
+	row++;
+
+	build_mix_action_combo (mix_combo[0], FaderPort::ButtonState(0));
+	build_mix_action_combo (mix_combo[1], FaderPort::ShiftDown);
+	build_mix_action_combo (mix_combo[2], FaderPort::LongPress);
+
+	build_proj_action_combo (proj_combo[0], FaderPort::ButtonState(0));
+	build_proj_action_combo (proj_combo[1], FaderPort::ShiftDown);
+	build_proj_action_combo (proj_combo[2], FaderPort::LongPress);
+
+	build_trns_action_combo (trns_combo[0], FaderPort::ButtonState(0));
+	build_trns_action_combo (trns_combo[1], FaderPort::ShiftDown);
+	build_trns_action_combo (trns_combo[2], FaderPort::LongPress);
+
+	build_available_action_menu ();
+
+	/* No shift-press combo for User because that is labelled as "next"
+	 * (marker)
+	 */
+
+	build_user_action_combo (user_combo[0], FaderPort::ButtonState(0));
+	build_user_action_combo (user_combo[1], FaderPort::LongPress);
+
+	action_table.set_row_spacings (4);
+	action_table.set_col_spacings (6);
+	action_table.set_border_width (12);
+	action_table.set_homogeneous (false);
+
+	int action_row = 0;
+
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Press Action")));
+	l->set_alignment (0.5, 0.5);
+	action_table.attach (*l, 1, 2, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Shift-Press Action")));
+	l->set_alignment (0.5, 0.5);
+	action_table.attach (*l, 2, 3, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Long Press Action")));
+	l->set_alignment (0.5, 0.5);
+	action_table.attach (*l, 3, 4, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	action_row++;
+
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Mix")));
+	l->set_alignment (1.0, 0.5);
+	action_table.attach (*l, 0, 1, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (mix_combo[0]);
+	action_table.attach (*align, 1, 2, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (mix_combo[1]);
+	action_table.attach (*align, 2, 3, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (mix_combo[2]);
+	action_table.attach (*align, 3, 4, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	action_row++;
+
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Proj")));
+	l->set_alignment (1.0, 0.5);
+	action_table.attach (*l, 0, 1, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (proj_combo[0]);
+	action_table.attach (*align, 1, 2, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (proj_combo[1]);
+	action_table.attach (*align, 2, 3, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (proj_combo[2]);
+	action_table.attach (*align, 3, 4, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	action_row++;
+
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Trns")));
+	l->set_alignment (1.0, 0.5);
+	action_table.attach (*l, 0, 1, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (trns_combo[0]);
+	action_table.attach (*align, 1, 2, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (trns_combo[1]);
+	action_table.attach (*align, 2, 3, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (trns_combo[2]);
+	action_table.attach (*align, 3, 4, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	action_row++;
+
+	l = manage (new Gtk::Label);
+	l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("User")));
+	l->set_alignment (1.0, 0.5);
+	action_table.attach (*l, 0, 1, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (user_combo[0]);
+	action_table.attach (*align, 1, 2, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	/* skip shift press combo */
+	align = manage (new Alignment);
+	align->set (0.0, 0.5);
+	align->add (user_combo[1]);
+	action_table.attach (*align, 3, 4, action_row, action_row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	action_row++;
+
+	table.attach (action_table, 0, 5, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
+	row++;
+
+	hpacker.pack_start (table, true, true);
+	pack_start (hpacker, false, false);
+
+	/* update the port connection combos */
+
+	update_port_combos ();
+
+	/* catch future changes to connection state */
+
+	fp.ConnectionChange.connect (connection_change_connection, invalidator (*this), boost::bind (&FPGUI::connection_handler, this), gui_context());
+}
+
+FPGUI::~FPGUI ()
+{
+}
+
+void
+FPGUI::connection_handler ()
+{
+	/* ignore all changes to combobox active strings here, because we're
+	   updating them to match a new ("external") reality - we were called
+	   because port connections have changed.
+	*/
+
+	PBD::Unwinder<bool> ici (ignore_active_change, true);
+
+	update_port_combos ();
+}
+
+void
+FPGUI::update_port_combos ()
+{
+	vector<string> midi_inputs;
+	vector<string> midi_outputs;
+
+	ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsTerminal), midi_inputs);
+	ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsTerminal), midi_outputs);
+
+	Glib::RefPtr<Gtk::ListStore> input = build_midi_port_list (midi_inputs, true);
+	Glib::RefPtr<Gtk::ListStore> output = build_midi_port_list (midi_outputs, false);
+	bool input_found = false;
+	bool output_found = false;
+	int n;
+
+	input_combo.set_model (input);
+	output_combo.set_model (output);
+
+	Gtk::TreeModel::Children children = input->children();
+	Gtk::TreeModel::Children::iterator i;
+	i = children.begin();
+	++i; /* skip "Disconnected" */
+
+
+	for (n = 1;  i != children.end(); ++i, ++n) {
+		string port_name = (*i)[midi_port_columns.full_name];
+		if (fp.input_port()->connected_to (port_name)) {
+			input_combo.set_active (n);
+			input_found = true;
+			break;
+		}
+	}
+
+	if (!input_found) {
+		input_combo.set_active (0); /* disconnected */
+	}
+
+	children = output->children();
+	i = children.begin();
+	++i; /* skip "Disconnected" */
+
+	for (n = 1;  i != children.end(); ++i, ++n) {
+		string port_name = (*i)[midi_port_columns.full_name];
+		if (fp.output_port()->connected_to (port_name)) {
+			output_combo.set_active (n);
+			output_found = true;
+			break;
+		}
+	}
+
+	if (!output_found) {
+		output_combo.set_active (0); /* disconnected */
+	}
+}
+
+void
+FPGUI::build_available_action_menu ()
+{
+	/* build a model of all available actions (needs to be tree structured
+	 * more)
+	 */
+
+	available_action_model = TreeStore::create (action_columns);
+
+	vector<string> paths;
+	vector<string> labels;
+	vector<string> tooltips;
+	vector<string> keys;
+	vector<AccelKey> bindings;
+	typedef std::map<string,TreeIter> NodeMap;
+	NodeMap nodes;
+	NodeMap::iterator r;
+
+	ActionManager::get_all_actions (labels, paths, tooltips, keys, bindings);
+
+	vector<string>::iterator k;
+	vector<string>::iterator p;
+	vector<string>::iterator t;
+	vector<string>::iterator l;
+
+	available_action_model->clear ();
+
+	TreeIter rowp;
+	TreeModel::Row parent;
+
+	/* Disabled item (row 0) */
+
+	rowp = available_action_model->append();
+	parent = *(rowp);
+	parent[action_columns.name] = _("Disabled");
+
+	/* Key aliasing */
+
+	rowp = available_action_model->append();
+	parent = *(rowp);
+	parent[action_columns.name] = _("Shift");
+	rowp = available_action_model->append();
+	parent = *(rowp);
+	parent[action_columns.name] = _("Control");
+	rowp = available_action_model->append();
+	parent = *(rowp);
+	parent[action_columns.name] = _("Option");
+	rowp = available_action_model->append();
+	parent = *(rowp);
+	parent[action_columns.name] = _("CmdAlt");
+
+
+	for (l = labels.begin(), k = keys.begin(), p = paths.begin(), t = tooltips.begin(); l != labels.end(); ++k, ++p, ++t, ++l) {
+
+		TreeModel::Row row;
+		vector<string> parts;
+
+		parts.clear ();
+
+		split (*p, parts, '/');
+
+		if (parts.empty()) {
+			continue;
+		}
+
+		//kinda kludgy way to avoid displaying menu items as mappable
+		if ( parts[1] == _("Main_menu") )
+			continue;
+		if ( parts[1] == _("JACK") )
+			continue;
+		if ( parts[1] == _("redirectmenu") )
+			continue;
+		if ( parts[1] == _("Editor_menus") )
+			continue;
+		if ( parts[1] == _("RegionList") )
+			continue;
+		if ( parts[1] == _("ProcessorMenu") )
+			continue;
+
+		if ((r = nodes.find (parts[1])) == nodes.end()) {
+
+			/* top level is missing */
+
+			TreeIter rowp;
+			TreeModel::Row parent;
+			rowp = available_action_model->append();
+			nodes[parts[1]] = rowp;
+			parent = *(rowp);
+			parent[action_columns.name] = parts[1];
+
+			row = *(available_action_model->append (parent.children()));
+
+		} else {
+
+			row = *(available_action_model->append ((*r->second)->children()));
+
+		}
+
+		/* add this action */
+
+		if (l->empty ()) {
+			row[action_columns.name] = *t;
+			action_map[*t] = *p;
+		} else {
+			row[action_columns.name] = *l;
+			action_map[*l] = *p;
+		}
+
+		string path = (*p);
+		/* ControlProtocol::access_action() is not interested in the
+		   legacy "<Actions>/" prefix part of a path.
+		*/
+		path = path.substr (strlen ("<Actions>/"));
+
+		row[action_columns.path] = path;
+	}
+}
+
+void
+FPGUI::action_changed (Gtk::ComboBox* cb, FaderPort::ButtonID id, FaderPort::ButtonState bs)
+{
+	TreeModel::const_iterator row = cb->get_active ();
+	string action_path = (*row)[action_columns.path];
+
+	/* release binding */
+	fp.set_action (id, action_path, false, bs);
+}
+
+void
+FPGUI::build_action_combo (Gtk::ComboBox& cb, vector<pair<string,string> > const & actions, FaderPort::ButtonID id, FaderPort::ButtonState bs)
+{
+	Glib::RefPtr<Gtk::ListStore> model (Gtk::ListStore::create (action_columns));
+	TreeIter rowp;
+	TreeModel::Row row;
+	string current_action = fp.get_action (id, false, bs); /* lookup release action */
+	int active_row = -1;
+	int n;
+	vector<pair<string,string> >::const_iterator i;
+
+	rowp = model->append();
+	row = *(rowp);
+	row[action_columns.name] = _("Disabled");
+	row[action_columns.path] = string();
+
+	if (current_action.empty()) {
+		active_row = 0;
+	}
+
+	for (i = actions.begin(), n = 0; i != actions.end(); ++i, ++n) {
+		rowp = model->append();
+		row = *(rowp);
+		row[action_columns.name] = i->first;
+		row[action_columns.path] = i->second;
+		if (current_action == i->second) {
+			active_row = n+1;
+		}
+	}
+
+	cb.set_model (model);
+	cb.pack_start (action_columns.name);
+
+	if (active_row >= 0) {
+		cb.set_active (active_row);
+	}
+
+	cb.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &FPGUI::action_changed), &cb, id, bs));
+}
+
+void
+FPGUI::build_mix_action_combo (Gtk::ComboBox& cb, FaderPort::ButtonState bs)
+{
+	vector<pair<string,string> > actions;
+
+	actions.push_back (make_pair (string (_("Toggle Editor & Mixer Windows")), string (X_("Common/toggle-editor-mixer"))));
+	actions.push_back (make_pair (string (_("Show/Hide Mixer list")), string (X_("Common/ToggleMixerList"))));
+	actions.push_back (make_pair (string("Toggle Meterbridge"), string(X_("Common/toggle-meterbridge"))));
+	actions.push_back (make_pair (string (_("Show/Hide Editor mixer strip")), string (X_("Editor/show-editor-mixer"))));
+
+	build_action_combo (cb, actions, FaderPort::Mix, bs);
+}
+
+void
+FPGUI::build_proj_action_combo (Gtk::ComboBox& cb, FaderPort::ButtonState bs)
+{
+	vector<pair<string,string> > actions;
+
+	actions.push_back (make_pair (string("Toggle Editor Lists"), string(X_("Editor/show-editor-list"))));
+	actions.push_back (make_pair (string("Toggle Summary"), string(X_("Editor/ToggleSummary"))));
+	actions.push_back (make_pair (string("Toggle Meterbridge"), string(X_("Common/toggle-meterbridge"))));
+	actions.push_back (make_pair (string (_("Zoom to Session")), string (X_("Editor/zoom-to-session"))));
+
+//	actions.push_back (make_pair (string (_("Zoom In")), string (X_("Editor/temporal-zoom-in"))));
+//	actions.push_back (make_pair (string (_("Zoom Out")), string (X_("Editor/temporal-zoom-out"))));
+
+	build_action_combo (cb, actions, FaderPort::Proj, bs);
+}
+
+void
+FPGUI::build_trns_action_combo (Gtk::ComboBox& cb, FaderPort::ButtonState bs)
+{
+	vector<pair<string,string> > actions;
+
+	actions.push_back (make_pair (string("Toggle Big Clock"), string(X_("Window/toggle-big-clock"))));  //note:  this would really make sense if the Big Clock had transport buttons on it
+	actions.push_back (make_pair (string("Toggle Locations window"), string(X_("Window/toggle-locations"))));
+	actions.push_back (make_pair (string("Toggle Metronome"), string(X_("Transport/ToggleClick"))));
+	actions.push_back (make_pair (string("Toggle External Sync"), string(X_("Transport/ToggleExternalSync"))));
+	actions.push_back (make_pair (string("Toggle Follow Playhead"), string(X_("Editor/toggle-follow-playhead"))));
+
+//	actions.push_back (make_pair (string("Set Playhead @pointer"), string(X_("Editor/set-playhead"))));
+
+
+	build_action_combo (cb, actions, FaderPort::Trns, bs);
+}
+
+bool
+FPGUI::find_action_in_model (const TreeModel::iterator& iter, std::string const & action_path, TreeModel::iterator* found)
+{
+	TreeModel::Row row = *iter;
+	string path = row[action_columns.path];
+
+	if (path == action_path) {
+		*found = iter;
+		return true;
+	}
+
+	return false;
+}
+
+void
+FPGUI::build_user_action_combo (Gtk::ComboBox& cb, FaderPort::ButtonState bs)
+{
+	cb.set_model (available_action_model);
+	cb.pack_start (action_columns.name);
+	cb.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &FPGUI::action_changed), &cb, FaderPort::User, bs));
+
+	/* set the active "row" to the right value for the current button binding */
+
+	string current_action = fp.get_action (FaderPort::User, false, bs); /* lookup release action */
+
+	if (current_action.empty()) {
+		cb.set_active (0); /* "disabled" */
+		return;
+	}
+
+	TreeModel::iterator iter = available_action_model->children().end();
+
+	available_action_model->foreach_iter (sigc::bind (sigc::mem_fun (*this, &FPGUI::find_action_in_model), current_action, &iter));
+
+	if (iter != available_action_model->children().end()) {
+		cb.set_active (iter);
+	} else {
+		cb.set_active (0);
+	}
+
+}
+
+Glib::RefPtr<Gtk::ListStore>
+FPGUI::build_midi_port_list (vector<string> const & ports, bool for_input)
+{
+	Glib::RefPtr<Gtk::ListStore> store = ListStore::create (midi_port_columns);
+	TreeModel::Row row;
+
+	row = *store->append ();
+	row[midi_port_columns.full_name] = string();
+	row[midi_port_columns.short_name] = _("Disconnected");
+
+	for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
+		row = *store->append ();
+		row[midi_port_columns.full_name] = *p;
+		std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
+		if (pn.empty ()) {
+			pn = (*p).substr ((*p).find (':') + 1);
+		}
+		row[midi_port_columns.short_name] = pn;
+	}
+
+	return store;
+}
+
+void
+FPGUI::active_port_changed (Gtk::ComboBox* combo, bool for_input)
+{
+	if (ignore_active_change) {
+		return;
+	}
+
+	TreeModel::iterator active = combo->get_active ();
+	string new_port = (*active)[midi_port_columns.full_name];
+
+	if (new_port.empty()) {
+		if (for_input) {
+			fp.input_port()->disconnect_all ();
+		} else {
+			fp.output_port()->disconnect_all ();
+		}
+
+		return;
+	}
+
+	if (for_input) {
+		if (!fp.input_port()->connected_to (new_port)) {
+			fp.input_port()->disconnect_all ();
+			fp.input_port()->connect (new_port);
+		}
+	} else {
+		if (!fp.output_port()->connected_to (new_port)) {
+			fp.output_port()->disconnect_all ();
+			fp.output_port()->connect (new_port);
+		}
+	}
+}
diff --git a/libs/surfaces/faderport/gui.h b/libs/surfaces/faderport/gui.h
new file mode 100644
index 0000000..907da73
--- /dev/null
+++ b/libs/surfaces/faderport/gui.h
@@ -0,0 +1,113 @@
+/*
+    Copyright (C) 2015 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_faderport_gui_h__
+#define __ardour_faderport_gui_h__
+
+#include <vector>
+#include <string>
+
+#include <gtkmm/box.h>
+#include <gtkmm/combobox.h>
+#include <gtkmm/image.h>
+#include <gtkmm/table.h>
+#include <gtkmm/treestore.h>
+
+namespace Gtk {
+	class CellRendererCombo;
+	class ListStore;
+}
+
+#include "faderport.h"
+
+namespace ArdourSurface {
+
+class FPGUI : public Gtk::VBox
+{
+public:
+	FPGUI (FaderPort&);
+	~FPGUI ();
+
+private:
+	FaderPort& fp;
+	Gtk::HBox hpacker;
+	Gtk::Table table;
+	Gtk::Table action_table;
+	Gtk::ComboBox input_combo;
+	Gtk::ComboBox output_combo;
+	Gtk::Image    image;
+
+	/* the mix, proj, trns and user buttons have no obvious semantics for
+	 * ardour, mixbus etc., so we allow the user to define their
+	 * functionality from a small, curated set of options.
+	 */
+
+	Gtk::ComboBox mix_combo[3];
+	Gtk::ComboBox proj_combo[3];
+	Gtk::ComboBox trns_combo[3];
+	Gtk::ComboBox user_combo[2];
+
+	void update_port_combos ();
+	PBD::ScopedConnection connection_change_connection;
+	void connection_handler ();
+
+	struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
+		MidiPortColumns() {
+			add (short_name);
+			add (full_name);
+		}
+		Gtk::TreeModelColumn<std::string> short_name;
+		Gtk::TreeModelColumn<std::string> full_name;
+	};
+
+	MidiPortColumns midi_port_columns;
+	bool ignore_active_change;
+
+	Glib::RefPtr<Gtk::ListStore> build_midi_port_list (std::vector<std::string> const & ports, bool for_input);
+	void active_port_changed (Gtk::ComboBox*,bool for_input);
+
+	struct ActionColumns : public Gtk::TreeModel::ColumnRecord {
+		ActionColumns() {
+			add (name);
+			add (path);
+		}
+		Gtk::TreeModelColumn<std::string> name;
+		Gtk::TreeModelColumn<std::string> path;
+	};
+
+	ActionColumns action_columns;
+	Glib::RefPtr<Gtk::TreeStore> available_action_model;
+	std::map<std::string,std::string> action_map; // map from action names to paths
+
+	void build_action_combo (Gtk::ComboBox& cb, std::vector<std::pair<std::string,std::string> > const & actions, FaderPort::ButtonID, FaderPort::ButtonState);
+	void build_mix_action_combo (Gtk::ComboBox&, FaderPort::ButtonState);
+	void build_proj_action_combo (Gtk::ComboBox&, FaderPort::ButtonState);
+	void build_trns_action_combo (Gtk::ComboBox&, FaderPort::ButtonState);
+	void build_user_action_combo (Gtk::ComboBox&, FaderPort::ButtonState);
+
+	void build_available_action_menu ();
+	void action_changed (Gtk::ComboBox*, FaderPort::ButtonID, FaderPort::ButtonState);
+
+	bool find_action_in_model (const Gtk::TreeModel::iterator& iter, std::string const & action_path, Gtk::TreeModel::iterator* found);
+
+};
+
+}
+
+#endif /* __ardour_faderport_gui_h__ */
diff --git a/libs/evoral/src/i18n.h b/libs/surfaces/faderport/i18n.h
similarity index 100%
copy from libs/evoral/src/i18n.h
copy to libs/surfaces/faderport/i18n.h
diff --git a/libs/surfaces/faderport/operations.cc b/libs/surfaces/faderport/operations.cc
new file mode 100644
index 0000000..bb72794
--- /dev/null
+++ b/libs/surfaces/faderport/operations.cc
@@ -0,0 +1,291 @@
+/*
+    Copyright (C) 2015 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "ardour/async_midi_port.h"
+#include "ardour/monitor_processor.h"
+#include "ardour/pannable.h"
+#include "ardour/plugin_insert.h"
+#include "ardour/rc_configuration.h"
+#include "ardour/session.h"
+#include "ardour/track.h"
+#include "ardour/types.h"
+
+#include "faderport.h"
+
+using namespace ARDOUR;
+using namespace ArdourSurface;
+using namespace PBD;
+
+/* this value is chosen to given smooth motion from 0..1.0 in about 270 degrees
+ * of encoder rotation.
+ */
+static const double encoder_divider = 24.0;
+
+void
+FaderPort::left ()
+{
+	access_action ("Editor/select-prev-route");
+
+	//ToDo:  bank by 8?
+	//if ( (button_state & ShiftDown) == ShiftDown )
+
+}
+
+void
+FaderPort::right ()
+{
+	access_action ("Editor/select-next-route");
+
+	//ToDo:  bank by 8?
+	//if ( (button_state & ShiftDown) == ShiftDown )
+}
+
+
+void
+FaderPort::read ()
+{
+	if (_current_route) {
+		boost::shared_ptr<AutomationControl> gain = _current_route->gain_control ();
+		if (gain) {
+			gain->set_automation_state( (ARDOUR::AutoState) ARDOUR::Play );
+		}
+	}
+}
+
+void
+FaderPort::write ()
+{
+	if (_current_route) {
+		boost::shared_ptr<AutomationControl> gain = _current_route->gain_control ();
+		if (gain) {
+			gain->set_automation_state( (ARDOUR::AutoState) ARDOUR::Write );
+		}
+	}
+}
+
+void
+FaderPort::touch ()
+{
+	if (_current_route) {
+		boost::shared_ptr<AutomationControl> gain = _current_route->gain_control ();
+		if (gain) {
+			gain->set_automation_state( (ARDOUR::AutoState) ARDOUR::Touch );
+		}
+	}
+}
+
+void
+FaderPort::off ()
+{
+	if (_current_route) {
+		boost::shared_ptr<AutomationControl> gain = _current_route->gain_control ();
+		if (gain) {
+			gain->set_automation_state( (ARDOUR::AutoState) ARDOUR::Off );
+		}
+	}
+}
+
+
+
+
+void
+FaderPort::undo ()
+{
+	ControlProtocol::Undo (); /* EMIT SIGNAL */
+}
+
+void
+FaderPort::redo ()
+{
+	ControlProtocol::Redo (); /* EMIT SIGNAL */
+}
+
+void
+FaderPort::mute ()
+{
+	if (!_current_route) {
+		return;
+	}
+
+	if (_current_route == session->monitor_out()) {
+		boost::shared_ptr<MonitorProcessor> mp = _current_route->monitor_control();
+		mp->set_cut_all (!mp->cut_all());
+		return;
+	}
+
+	boost::shared_ptr<RouteList> rl (new RouteList);
+	rl->push_back (_current_route);
+	session->set_mute (rl, !_current_route->muted());
+}
+
+void
+FaderPort::solo ()
+{
+	if (!_current_route) {
+		return;
+	}
+
+	boost::shared_ptr<RouteList> rl (new RouteList);
+	rl->push_back (_current_route);
+
+	if (Config->get_solo_control_is_listen_control()) {
+		session->set_listen (rl, !_current_route->listening_via_monitor());
+	} else {
+		session->set_solo (rl, !_current_route->soloed());
+	}
+}
+
+void
+FaderPort::rec_enable ()
+{
+	if (!_current_route) {
+		return;
+	}
+
+	boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_current_route);
+
+	if (!t) {
+		return;
+	}
+
+	boost::shared_ptr<RouteList> rl (new RouteList);
+	rl->push_back (_current_route);
+
+	session->set_record_enabled (rl, !t->record_enabled());
+}
+
+void
+FaderPort::use_master ()
+{
+	boost::shared_ptr<Route> r = session->master_out();
+	if (r) {
+		if (_current_route == r) {
+			r = pre_master_route.lock();
+			set_current_route (r);
+			get_button(Output).set_led_state (_output_port, false);
+			blinkers.remove (Output);
+		} else {
+			if (_current_route != session->master_out() && _current_route != session->monitor_out()) {
+				pre_master_route = boost::weak_ptr<Route> (_current_route);
+			}
+			set_current_route (r);
+			get_button(Output).set_led_state (_output_port, true);
+			blinkers.remove (Output);
+		}
+	}
+}
+
+void
+FaderPort::use_monitor ()
+{
+	boost::shared_ptr<Route> r = session->monitor_out();
+
+	if (r) {
+		if (_current_route == r) {
+			r = pre_monitor_route.lock();
+			set_current_route (r);
+			get_button(Output).set_led_state (_output_port, false);
+			blinkers.remove (Output);
+		} else {
+			if (_current_route != session->master_out() && _current_route != session->monitor_out()) {
+				pre_monitor_route = boost::weak_ptr<Route> (_current_route);
+			}
+			set_current_route (r);
+			get_button(Output).set_led_state (_output_port, true);
+			blinkers.push_back (Output);
+		}
+	} else {
+	}
+}
+
+void
+FaderPort::ardour_pan_azimuth (int delta)
+{
+	if (!_current_route) {
+		return;
+	}
+
+	boost::shared_ptr<Pannable> pannable = _current_route->pannable ();
+
+	if (!pannable) {
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> azimuth = pannable->pan_azimuth_control;
+
+	if (!azimuth) {
+		return;
+	}
+
+	azimuth->set_value (azimuth->interface_to_internal (azimuth->internal_to_interface (azimuth->get_value()) + (delta / encoder_divider)), Controllable::NoGroup);
+}
+
+
+void
+FaderPort::ardour_pan_width(int delta)
+{
+	if (!_current_route) {
+		return;
+	}
+
+	boost::shared_ptr<Pannable> pannable = _current_route->pannable ();
+
+	if (!pannable) {
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> width = pannable->pan_width_control;
+
+	if (!width) {
+		return;
+	}
+
+	width->set_value (width->interface_to_internal (width->internal_to_interface (width->get_value()) + (delta / encoder_divider)), Controllable::NoGroup);
+}
+
+void
+FaderPort::mixbus_pan (int delta)
+{
+#ifdef MIXBUS
+	if (!_current_route) {
+		return;
+	}
+
+	const uint32_t port_channel_post_pan = 2; // gtk2_ardour/mixbus_ports.h
+	boost::shared_ptr<ARDOUR::PluginInsert> plug = _current_route->ch_post();
+
+	if (!plug) {
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> azimuth = boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (plug->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, port_channel_post_pan)));
+
+	if (!azimuth) {
+		return;
+	}
+
+	azimuth->set_value (azimuth->interface_to_internal (azimuth->internal_to_interface (azimuth->get_value()) + (delta / encoder_divider)), Controllable::NoGroup);
+#endif
+}
+
+void
+FaderPort::punch ()
+{
+	access_action ("Transport/TogglePunch");
+}
diff --git a/libs/surfaces/faderport/wscript b/libs/surfaces/faderport/wscript
new file mode 100644
index 0000000..a0c3a2e
--- /dev/null
+++ b/libs/surfaces/faderport/wscript
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+from waflib.extras import autowaf as autowaf
+import os
+
+# Mandatory variables
+top = '.'
+out = 'build'
+
+def options(opt):
+    autowaf.set_options(opt)
+
+def configure(conf):
+    autowaf.configure(conf)
+
+def build(bld):
+    obj = bld(features = 'cxx cxxshlib')
+    obj.source = '''
+            faderport.cc
+            gui.cc
+            faderport_interface.cc
+            operations.cc
+    '''
+    obj.export_includes = ['.']
+    obj.defines      = [ 'PACKAGE="ardour_faderport"' ]
+    obj.defines     += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
+    obj.includes     = [ '.', './faderport']
+    obj.name         = 'libardour_faderport'
+    obj.target       = 'ardour_faderport'
+    obj.uselib       = 'GTKMM GTK GDK'
+    obj.use          = 'libardour libardour_cp libgtkmm2ext libpbd'
+    obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
+
+def shutdown():
+    autowaf.shutdown()
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index 4b59151..e319f65 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -34,6 +34,8 @@
 
 #include "midi++/port.h"
 
+#include "ardour/async_midi_port.h"
+#include "ardour/audioengine.h"
 #include "ardour/audioengine.h"
 #include "ardour/filesystem_paths.h"
 #include "ardour/session.h"
@@ -58,12 +60,13 @@ using namespace std;
 
 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
 	: ControlProtocol (s, _("Generic MIDI"))
+	, connection_state (ConnectionState (0))
 	, _motorised (false)
 	, _threshold (10)
 	, gui (0)
 {
-	_input_port = s.midi_input_port ();
-	_output_port = s.midi_output_port ();
+	_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_input_port ());
+	_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_output_port ());
 
 	do_feedback = false;
 	_feedback_interval = 10000; // microseconds
@@ -94,6 +97,11 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
 
 	Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
 
+	/* Catch port connections and disconnections (cross-thread) */
+	ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR,
+	                                                                      boost::bind (&GenericMidiControlProtocol::connection_handler, this, _1, _2, _3, _4, _5),
+	                                                                      midi_ui_context());
+
 	reload_maps ();
 }
 
@@ -229,7 +237,9 @@ GenericMidiControlProtocol::drop_bindings ()
 int
 GenericMidiControlProtocol::set_active (bool /*yn*/)
 {
-	/* start/stop delivery/outbound thread */
+	/* nothing to do here: the MIDI UI thread in libardour handles all our
+	   I/O needs.
+	*/
 	return 0;
 }
 
@@ -781,6 +791,10 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
 	int intval;
 	bool momentary;
 	MIDIControllable::Encoder encoder = MIDIControllable::No_enc;
+	bool rpn_value = false;
+	bool nrpn_value = false;
+	bool rpn_change = false;
+	bool nrpn_change = false;
 
 	if ((prop = node.property (X_("ctl"))) != 0) {
 		ev = MIDI::controller;
@@ -802,6 +816,14 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
 	} else if ((prop = node.property (X_("enc-b"))) != 0) {
 		encoder = MIDIControllable::Enc_B;
 		ev = MIDI::controller;
+	} else if ((prop = node.property (X_("rpn"))) != 0) {
+		rpn_value = true;
+	} else if ((prop = node.property (X_("nrpn"))) != 0) {
+		nrpn_value = true;
+	} else if ((prop = node.property (X_("rpn-delta"))) != 0) {
+		rpn_change = true;
+	} else if ((prop = node.property (X_("nrpn-delta"))) != 0) {
+		nrpn_change = true;
 	} else {
 		return 0;
 	}
@@ -841,8 +863,18 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
 		return 0;
 	}
 
-	mc->set_encoder (encoder);
-	mc->bind_midi (channel, ev, detail);
+	if (rpn_value) {
+		mc->bind_rpn_value (channel, detail);
+	} else if (nrpn_value) {
+		mc->bind_nrpn_value (channel, detail);
+	} else if (rpn_change) {
+		mc->bind_rpn_change (channel, detail);
+	} else if (nrpn_change) {
+		mc->bind_nrpn_change (channel, detail);
+	} else {
+		mc->set_encoder (encoder);
+		mc->bind_midi (channel, ev, detail);
+	}
 
 	return mc;
 }
@@ -1115,3 +1147,67 @@ GenericMidiControlProtocol::set_threshold (int t)
 {
 	_threshold = t;
 }
+
+bool
+GenericMidiControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
+{
+	if (!_input_port || !_output_port) {
+		return false;
+	}
+
+	string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_input_port)->name());
+	string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_output_port)->name());
+
+	if (ni == name1 || ni == name2) {
+		if (yn) {
+			connection_state |= InputConnected;
+		} else {
+			connection_state &= ~InputConnected;
+		}
+	} else if (no == name1 || no == name2) {
+		if (yn) {
+			connection_state |= OutputConnected;
+		} else {
+			connection_state &= ~OutputConnected;
+		}
+	} else {
+		/* not our ports */
+		return false;
+	}
+
+	if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
+
+		/* XXX this is a horrible hack. Without a short sleep here,
+		   something prevents the device wakeup messages from being
+		   sent and/or the responses from being received.
+		*/
+
+		g_usleep (100000);
+		connected ();
+
+	} else {
+
+	}
+
+	ConnectionChange (); /* emit signal for our GUI */
+
+	return true; /* connection status changed */
+}
+
+void
+GenericMidiControlProtocol::connected ()
+{
+	cerr << "Now connected\n";
+}
+
+boost::shared_ptr<Port>
+GenericMidiControlProtocol::output_port() const
+{
+	return _output_port;
+}
+
+boost::shared_ptr<Port>
+GenericMidiControlProtocol::input_port() const
+{
+	return _input_port;
+}
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
index f09c8e4..a453716 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
@@ -24,6 +24,7 @@
 #include <glibmm/threads.h>
 
 #include "ardour/types.h"
+#include "ardour/port.h"
 
 #include "control_protocol/control_protocol.h"
 
@@ -33,8 +34,9 @@ namespace PBD {
 }
 
 namespace ARDOUR {
-	class Session;
+	class AsyncMIDIPort;
 	class MidiPort;
+	class Session;
 }
 
 namespace MIDI {
@@ -53,8 +55,9 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
 	int set_active (bool yn);
 	static bool probe() { return true; }
 
-        MIDI::Port* input_port () const { return _input_port; }
-        MIDI::Port* output_port () const { return _output_port; }
+	boost::shared_ptr<ARDOUR::Port> input_port () const;
+	boost::shared_ptr<ARDOUR::Port> output_port () const;
+
 	void set_feedback_interval (ARDOUR::microseconds_t);
 
 	int set_feedback (bool yn);
@@ -100,9 +103,12 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
 		return _threshold;
 	}
 
+	PBD::Signal0<void> ConnectionChange;
+
   private:
-        MIDI::Port* _input_port;
-        MIDI::Port* _output_port;
+	boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
+	boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
+
 	ARDOUR::microseconds_t _feedback_interval;
 	ARDOUR::microseconds_t last_feedback_time;
 
@@ -140,6 +146,16 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
 	void reset_controllables ();
 	void drop_all ();
 
+	enum ConnectionState {
+		InputConnected = 0x1,
+		OutputConnected = 0x2
+	};
+
+	int connection_state;
+	bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
+	PBD::ScopedConnection port_connection;
+	void connected();
+
 	std::string _current_binding;
 	uint32_t _bank_size;
 	uint32_t _current_bank;
@@ -153,6 +169,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
 
 	mutable void *gui;
 	void build_gui ();
+
+
 };
 
 #endif /* ardour_generic_midi_control_protocol_h */
diff --git a/libs/surfaces/generic_midi/gmcp_gui.cc b/libs/surfaces/generic_midi/gmcp_gui.cc
index 710b61b..8e861b3 100644
--- a/libs/surfaces/generic_midi/gmcp_gui.cc
+++ b/libs/surfaces/generic_midi/gmcp_gui.cc
@@ -27,8 +27,16 @@
 #include <gtkmm/adjustment.h>
 #include <gtkmm/spinbutton.h>
 #include <gtkmm/table.h>
+#include <gtkmm/liststore.h>
+
+#include "pbd/unwind.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/port.h"
+#include "ardour/midi_port.h"
 
 #include "gtkmm2ext/gtk_ui.h"
+#include "gtkmm2ext/gui_thread.h"
 #include "gtkmm2ext/utils.h"
 
 #include "generic_midi_control_protocol.h"
@@ -50,10 +58,32 @@ private:
 	Gtk::Adjustment threshold_adjustment;
 	Gtk::SpinButton threshold_spinner;
 
+	Gtk::ComboBox input_combo;
+	Gtk::ComboBox output_combo;
+
 	void binding_changed ();
 	void bank_changed ();
 	void motorised_changed ();
 	void threshold_changed ();
+
+	void update_port_combos ();
+	PBD::ScopedConnection connection_change_connection;
+	void connection_handler ();
+
+	struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
+		MidiPortColumns() {
+			add (short_name);
+			add (full_name);
+		}
+		Gtk::TreeModelColumn<std::string> short_name;
+		Gtk::TreeModelColumn<std::string> full_name;
+	};
+
+	MidiPortColumns midi_port_columns;
+	bool ignore_active_change;
+
+	Glib::RefPtr<Gtk::ListStore> build_midi_port_list (std::vector<std::string> const & ports, bool for_input);
+	void active_port_changed (Gtk::ComboBox*,bool for_input);
 };
 
 using namespace PBD;
@@ -101,6 +131,7 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
 	, motorised_button ("Motorised")
 	, threshold_adjustment (p.threshold(), 1, 127, 1, 10)
 	, threshold_spinner (threshold_adjustment)
+	, ignore_active_change (false)
 {
 	vector<string> popdowns;
 	popdowns.push_back (_("Reset All"));
@@ -129,7 +160,29 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
 
 	int n = 0;
 
-	Label* label = manage (new Label (_("MIDI Bindings:")));
+	// MIDI input and output selectors
+	input_combo.pack_start (midi_port_columns.short_name);
+	output_combo.pack_start (midi_port_columns.short_name);
+
+	input_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &GMCPGUI::active_port_changed), &input_combo, true));
+	output_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &GMCPGUI::active_port_changed), &output_combo, false));
+
+	Label* label = manage (new Gtk::Label);
+	label->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Incoming MIDI on:")));
+	label->set_alignment (1.0, 0.5);
+	table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
+	table->attach (input_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
+	n++;
+
+	label = manage (new Gtk::Label);
+	label->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Outgoing MIDI on:")));
+	label->set_alignment (1.0, 0.5);
+	table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
+	table->attach (output_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
+	n++;
+
+	//MIDI binding file selector...
+	label = manage (new Label (_("MIDI Bindings:")));
 	label->set_alignment (0, 0.5);
 	table->attach (*label, 0, 1, n, n + 1);
 	table->attach (map_combo, 1, 2, n, n + 1);
@@ -173,6 +226,14 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
 	pack_start (*table, false, false);
 
 	binding_changed ();
+
+	/* update the port connection combos */
+
+	update_port_combos ();
+
+	/* catch future changes to connection state */
+
+	cp.ConnectionChange.connect (connection_change_connection, invalidator (*this), boost::bind (&GMCPGUI::connection_handler, this), gui_context());
 }
 
 GMCPGUI::~GMCPGUI ()
@@ -216,3 +277,127 @@ GMCPGUI::threshold_changed ()
 {
 	cp.set_threshold (threshold_adjustment.get_value());
 }
+
+void
+GMCPGUI::connection_handler ()
+{
+	/* ignore all changes to combobox active strings here, because we're
+	   updating them to match a new ("external") reality - we were called
+	   because port connections have changed.
+	*/
+
+	PBD::Unwinder<bool> ici (ignore_active_change, true);
+
+	update_port_combos ();
+}
+
+void
+GMCPGUI::update_port_combos ()
+{
+	vector<string> midi_inputs;
+	vector<string> midi_outputs;
+
+	ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsTerminal), midi_inputs);
+	ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsTerminal), midi_outputs);
+
+	Glib::RefPtr<Gtk::ListStore> input = build_midi_port_list (midi_inputs, true);
+	Glib::RefPtr<Gtk::ListStore> output = build_midi_port_list (midi_outputs, false);
+	bool input_found = false;
+	bool output_found = false;
+	int n;
+
+	input_combo.set_model (input);
+	output_combo.set_model (output);
+
+	Gtk::TreeModel::Children children = input->children();
+	Gtk::TreeModel::Children::iterator i;
+	i = children.begin();
+	++i; /* skip "Disconnected" */
+
+
+	for (n = 1;  i != children.end(); ++i, ++n) {
+		string port_name = (*i)[midi_port_columns.full_name];
+		if (cp.input_port()->connected_to (port_name)) {
+			input_combo.set_active (n);
+			input_found = true;
+			break;
+		}
+	}
+
+	if (!input_found) {
+		input_combo.set_active (0); /* disconnected */
+	}
+
+	children = output->children();
+	i = children.begin();
+	++i; /* skip "Disconnected" */
+
+	for (n = 1;  i != children.end(); ++i, ++n) {
+		string port_name = (*i)[midi_port_columns.full_name];
+		if (cp.output_port()->connected_to (port_name)) {
+			output_combo.set_active (n);
+			output_found = true;
+			break;
+		}
+	}
+
+	if (!output_found) {
+		output_combo.set_active (0); /* disconnected */
+	}
+}
+
+Glib::RefPtr<Gtk::ListStore>
+GMCPGUI::build_midi_port_list (vector<string> const & ports, bool for_input)
+{
+	Glib::RefPtr<Gtk::ListStore> store = ListStore::create (midi_port_columns);
+	TreeModel::Row row;
+
+	row = *store->append ();
+	row[midi_port_columns.full_name] = string();
+	row[midi_port_columns.short_name] = _("Disconnected");
+
+	for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
+		row = *store->append ();
+		row[midi_port_columns.full_name] = *p;
+		std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
+		if (pn.empty ()) {
+			pn = (*p).substr ((*p).find (':') + 1);
+		}
+		row[midi_port_columns.short_name] = pn;
+	}
+
+	return store;
+}
+
+void
+GMCPGUI::active_port_changed (Gtk::ComboBox* combo, bool for_input)
+{
+	if (ignore_active_change) {
+		return;
+	}
+
+	TreeModel::iterator active = combo->get_active ();
+	string new_port = (*active)[midi_port_columns.full_name];
+
+	if (new_port.empty()) {
+		if (for_input) {
+			cp.input_port()->disconnect_all ();
+		} else {
+			cp.output_port()->disconnect_all ();
+		}
+
+		return;
+	}
+
+	if (for_input) {
+		if (!cp.input_port()->connected_to (new_port)) {
+			cp.input_port()->disconnect_all ();
+			cp.input_port()->connect (new_port);
+		}
+	} else {
+		if (!cp.output_port()->connected_to (new_port)) {
+			cp.output_port()->disconnect_all ();
+			cp.output_port()->connect (new_port);
+		}
+	}
+}
diff --git a/libs/surfaces/generic_midi/interface.cc b/libs/surfaces/generic_midi/interface.cc
index b7e7b63..04254cb 100644
--- a/libs/surfaces/generic_midi/interface.cc
+++ b/libs/surfaces/generic_midi/interface.cc
@@ -65,7 +65,11 @@ static ControlProtocolDescriptor generic_midi_descriptor = {
 	/*supports_feedback : */   true,
 	/*probe :             */   probe_generic_midi_protocol,
 	/*initialize :        */   new_generic_midi_protocol,
-	/*destroy :           */   delete_generic_midi_protocol
+	/*destroy :           */   delete_generic_midi_protocol,
+	/*request_buffer_factory : */ 0  /* no buffer factory because this runs
+	                                  * in the midiUI event loop (which has
+	                                  * its own request buffer factory.
+	                                  */
 };
 
 extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &generic_midi_descriptor; }
diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc
index 9dca702..8945463 100644
--- a/libs/surfaces/generic_midi/midicontrollable.cc
+++ b/libs/surfaces/generic_midi/midicontrollable.cc
@@ -59,6 +59,8 @@ MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser&
 	last_value = 0; // got a better idea ?
 	last_controllable_value = 0.0f;
 	control_type = none;
+	control_rpn = -1;
+	control_nrpn = -1;
 	_control_description = "MIDI Control: none";
 	control_additional = (MIDI::byte) -1;
 	feedback = true; // for now
@@ -78,6 +80,8 @@ MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser&
 	last_value = 0; // got a better idea ?
 	last_controllable_value = 0.0f;
 	control_type = none;
+	control_rpn = -1;
+	control_nrpn = -1;
 	_control_description = "MIDI Control: none";
 	control_additional = (MIDI::byte) -1;
 	feedback = true; // for now
@@ -113,6 +117,8 @@ void
 MIDIControllable::drop_external_control ()
 {
 	midi_forget ();
+	control_rpn = -1;
+	control_nrpn = -1;
 	control_type = none;
 	control_additional = (MIDI::byte) -1;
 }
@@ -198,20 +204,22 @@ MIDIControllable::control_to_midi (float val)
 float
 MIDIControllable::midi_to_control (int val)
 {
-        /* fiddle with MIDI value so that we get an odd number of integer steps
-           and can thus represent "middle" precisely as 0.5. this maps to
-           the range 0..+1.0 (0 to 126)
-        */
+	/* fiddle with MIDI value so that we get an odd number of integer steps
+		and can thus represent "middle" precisely as 0.5. this maps to
+		the range 0..+1.0 (0 to 126)
+	*/
 
-        float fv = (val == 0 ? 0 : float (val - 1) / (max_value_for_type() - 1));
+	float fv = (val == 0 ? 0 : float (val - 1) / (max_value_for_type() - 1));
 
-        if (controllable->is_gain_like()) {
-                return slider_position_to_gain (fv);
-        }
+	if (controllable->is_gain_like()) {
+		return controllable->interface_to_internal (fv);
+	}
+	DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Raw value %1 float %2\n", val, fv));
 
 	float control_min = controllable->lower ();
 	float control_max = controllable->upper ();
 	float control_range = control_max - control_min;
+	DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Min %1 Max %2 Range %3\n", control_min, control_max, control_range));
 
 	AutomationControl *actl = dynamic_cast<AutomationControl*> (controllable);
 	if (actl) {
@@ -272,13 +280,13 @@ MIDIControllable::midi_sense_note (Parser &, EventTwoBytes *msg, bool /*is_on*/)
 
 	if (!controllable->is_toggle()) {
 		if (control_additional == msg->note_number) {
-			controllable->set_value (midi_to_control (msg->velocity));
+			controllable->set_value (midi_to_control (msg->velocity), Controllable::NoGroup);
 			DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Note %1 value %2  %3\n", (int) msg->note_number, (float) midi_to_control (msg->velocity), current_uri() ));
 		}
 	} else {
 		if (control_additional == msg->note_number) {
 			float new_value = controllable->get_value() > 0.5f ? 0.0f : 1.0f;
-			controllable->set_value (new_value);
+			controllable->set_value (new_value, Controllable::NoGroup);
 			DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Note %1 Value %2  %3\n", (int) msg->note_number, (float) new_value, current_uri()));
 		}
 	}
@@ -323,7 +331,7 @@ MIDIControllable::midi_sense_controller (Parser &, EventTwoBytes *msg)
 				*/
 
 				if (in_sync || _surface->motorised ()) {
-					controllable->set_value (midi_to_control (new_value));
+					controllable->set_value (midi_to_control (new_value), Controllable::NoGroup);
 				}
 				DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("MIDI CC %1 value %2  %3\n", (int) msg->controller_number, (float) midi_to_control(new_value), current_uri() ));
 
@@ -333,30 +341,30 @@ MIDIControllable::midi_sense_controller (Parser &, EventTwoBytes *msg)
 				switch (get_encoder()) {
 					case Enc_L:
 						if (msg->value > 0x40) {
-							controllable->set_value (midi_to_control (last_value - offset + 1));
+							controllable->set_value (midi_to_control (last_value - offset + 1), Controllable::NoGroup);
 						} else {
-							controllable->set_value (midi_to_control (last_value + offset + 1));
+							controllable->set_value (midi_to_control (last_value + offset + 1), Controllable::NoGroup);
 						}
 						break;
 					case Enc_R:
 						if (msg->value > 0x40) {
-							controllable->set_value (midi_to_control (last_value + offset + 1));
+							controllable->set_value (midi_to_control (last_value + offset + 1), Controllable::NoGroup);
 						} else {
-							controllable->set_value (midi_to_control (last_value - offset + 1));
+							controllable->set_value (midi_to_control (last_value - offset + 1), Controllable::NoGroup);
 						}
 						break;
 					case Enc_2:
 						if (msg->value > 0x40) {
-							controllable->set_value (midi_to_control (last_value - (0x7f - msg->value) + 1));
+							controllable->set_value (midi_to_control (last_value - (0x7f - msg->value) + 1), Controllable::NoGroup);
 						} else {
-							controllable->set_value (midi_to_control (last_value + offset + 1));
+							controllable->set_value (midi_to_control (last_value + offset + 1), Controllable::NoGroup);
 						}
 						break;
 					case Enc_B:
 						if (msg->value > 0x40) {
-							controllable->set_value (midi_to_control (last_value + offset + 1));
+							controllable->set_value (midi_to_control (last_value + offset + 1), Controllable::NoGroup);
 						} else {
-							controllable->set_value (midi_to_control (last_value - (0x40 - offset)));
+							controllable->set_value (midi_to_control (last_value - (0x40 - offset)), Controllable::NoGroup);
 						}
 						break;
 					default:
@@ -367,10 +375,10 @@ MIDIControllable::midi_sense_controller (Parser &, EventTwoBytes *msg)
 			}
 		} else {
 			if (msg->value > 64.0f) {
-				controllable->set_value (1);
+				controllable->set_value (1, Controllable::NoGroup);
 				DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Midi CC %1 value 1  %2\n", (int) msg->controller_number, current_uri()));
 			} else {
-				controllable->set_value (0);
+				controllable->set_value (0, Controllable::NoGroup);
 				DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Midi CC %1 value 0  %2\n", (int) msg->controller_number, current_uri()));
 			}
 		}
@@ -390,11 +398,11 @@ MIDIControllable::midi_sense_program_change (Parser &, MIDI::byte msg)
 	if (msg == control_additional) {
 
 		if (!controllable->is_toggle()) {
-			controllable->set_value (1.0);
+			controllable->set_value (1.0, Controllable::NoGroup);
 			DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("MIDI program %1 value 1.0  %3\n", (int) msg, current_uri() ));
 		} else  {
 			float new_value = controllable->get_value() > 0.5f ? 0.0f : 1.0f;
-			controllable->set_value (new_value);
+			controllable->set_value (new_value, Controllable::NoGroup);
 			DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("MIDI program %1 value %2  %3\n", (int) msg, (float) new_value, current_uri()));
 		}
 	}
@@ -412,14 +420,14 @@ MIDIControllable::midi_sense_pitchbend (Parser &, pitchbend_t pb)
 	}
 
 	if (!controllable->is_toggle()) {
-		controllable->set_value (midi_to_control (pb));
+		controllable->set_value (midi_to_control (pb), Controllable::NoGroup);
 		DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("MIDI pitchbend %1 value %2  %3\n", (int) control_channel, (float) midi_to_control (pb), current_uri() ));
 	} else {
 		if (pb > 8065.0f) {
-			controllable->set_value (1);
+			controllable->set_value (1, Controllable::NoGroup);
 			DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Midi pitchbend %1 value 1  %2\n", (int) control_channel, current_uri()));
 		} else {
-			controllable->set_value (0);
+			controllable->set_value (0, Controllable::NoGroup);
 			DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Midi pitchbend %1 value 0  %2\n", (int) control_channel, current_uri()));
 		}
 	}
@@ -445,6 +453,88 @@ MIDIControllable::midi_receiver (Parser &, MIDI::byte *msg, size_t /*len*/)
 }
 
 void
+MIDIControllable::rpn_value_change (Parser&, uint16_t rpn, float val)
+{
+	if (control_rpn == rpn) {
+		if (controllable) {
+			controllable->set_value (val, Controllable::NoGroup);
+		}
+	}
+}
+
+void
+MIDIControllable::nrpn_value_change (Parser&, uint16_t nrpn, float val)
+{
+	if (control_nrpn == nrpn) {
+		if (controllable) {
+			controllable->set_value (val, Controllable::NoGroup);
+		}
+	}
+}
+
+void
+MIDIControllable::rpn_change (Parser&, uint16_t rpn, int dir)
+{
+	if (control_rpn == rpn) {
+		if (controllable) {
+			/* XXX how to increment/decrement ? */
+			// controllable->set_value (val);
+		}
+	}
+}
+
+void
+MIDIControllable::nrpn_change (Parser&, uint16_t nrpn, int dir)
+{
+	if (control_nrpn == nrpn) {
+		if (controllable) {
+			/* XXX how to increment/decrement ? */
+			// controllable->set_value (val);
+		}
+	}
+}
+
+void
+MIDIControllable::bind_rpn_value (channel_t chn, uint16_t rpn)
+{
+	int chn_i = chn;
+	drop_external_control ();
+	control_rpn = rpn;
+	control_channel = chn;
+	_parser.channel_rpn[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::rpn_value_change, this, _1, _2, _3));
+}
+
+void
+MIDIControllable::bind_nrpn_value (channel_t chn, uint16_t nrpn)
+{
+	int chn_i = chn;
+	drop_external_control ();
+	control_nrpn = nrpn;
+	control_channel = chn;
+	_parser.channel_nrpn[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::rpn_value_change, this, _1, _2, _3));
+}
+
+void
+MIDIControllable::bind_nrpn_change (channel_t chn, uint16_t nrpn)
+{
+	int chn_i = chn;
+	drop_external_control ();
+	control_nrpn = nrpn;
+	control_channel = chn;
+	_parser.channel_nrpn_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::rpn_change, this, _1, _2, _3));
+}
+
+void
+MIDIControllable::bind_rpn_change (channel_t chn, uint16_t rpn)
+{
+	int chn_i = chn;
+	drop_external_control ();
+	control_rpn = rpn;
+	control_channel = chn;
+	_parser.channel_rpn_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::nrpn_change, this, _1, _2, _3));
+}
+
+void
 MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
 {
 	char buf[64];
@@ -504,11 +594,76 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
 MIDI::byte*
 MIDIControllable::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool /*force*/)
 {
-	if (!controllable || control_type == none || !feedback || bufsize <= 2) {
+	if (!controllable || !feedback) {
+		return buf;
+	}
+
+	float val = controllable->get_value ();
+
+	/* Note that when sending RPN/NPRN we do two things:
+	 *
+	 * always send MSB first, then LSB
+	 * null/reset the parameter ID after sending.
+	 *
+	 * this follows recommendations found online, eg. http://www.philrees.co.uk/nrpnq.htm
+	 */
+
+	if (control_rpn >= 0) {
+		if (bufsize < 13) {
+			return buf;
+		}
+		int rpn_val = (int) lrintf (val * 16384.0);
+		if (last_value == rpn_val) {
+			return buf;
+		}
+		*buf++ = (0xb0) | control_channel;
+		*buf++ = 0x62;
+		*buf++ = (int) ((control_rpn) >> 7);
+		*buf++ = 0x63;
+		*buf++ = (int) (control_rpn & 0x7f);
+		*buf++ = 0x06;
+		*buf++ = (int) (rpn_val >> 7);
+		*buf++ = 0x26;
+		*buf++ = (int) (rpn_val & 0x7f);
+		*buf++ = 0x62;
+		*buf++ = 0x7f;
+		*buf++ = 0x63;
+		*buf++ = 0x7f;
+		bufsize -= 13;
+		last_value = rpn_val;
+		DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("MIDI out: RPN %1 Channel %2 Value %3\n", control_rpn, (int) control_channel, val));
+		return buf;
+	}
+
+	if (control_nrpn >= 0) {
+		int rpn_val = (int) lrintf (val * 16384.0);
+		if (last_value == rpn_val) {
+			return buf;
+		}
+		*buf++ = (0xb0) | control_channel;
+		*buf++ = 0x64;
+		*buf++ = (int) ((control_rpn) >> 7);
+		*buf++ = 0x65;
+		*buf++ = (int) (control_rpn & 0x7f);
+		*buf++ = 0x06;
+		*buf++ = (int) (rpn_val >> 7);
+		*buf++ = 0x26;
+		*buf++ = (int) (rpn_val & 0x7f);
+		*buf++ = 0x64;
+		*buf++ = 0x7f;
+		*buf++ = 0x65;
+		*buf++ = 0x7f;
+		last_value = rpn_val;
+		bufsize -= 13;
+		DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("MIDI out: NRPN %1 Channel %2 Value %3\n", control_nrpn, (int) control_channel, val));
+		return buf;
+	}
+
+	if (control_type == none || bufsize <= 2) {
 		return buf;
 	}
 
-	int const gm = control_to_midi (controllable->get_value());
+	int const gm = control_to_midi (val);
 
 	if (gm == last_value) {
 		return buf;
diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h
index 2e5d41c..a19e3a1 100644
--- a/libs/surfaces/generic_midi/midicontrollable.h
+++ b/libs/surfaces/generic_midi/midicontrollable.h
@@ -99,6 +99,11 @@ class MIDIControllable : public PBD::Stateful
 	int set_state (const XMLNode&, int version);
 
 	void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
+	void bind_rpn_value (MIDI::channel_t, uint16_t rpn);
+	void bind_nrpn_value (MIDI::channel_t, uint16_t rpn);
+	void bind_rpn_change (MIDI::channel_t, uint16_t rpn);
+	void bind_nrpn_change (MIDI::channel_t, uint16_t rpn);
+
 	MIDI::channel_t get_control_channel () { return control_channel; }
 	MIDI::eventType get_control_type () { return control_type; }
 	MIDI::byte get_control_additional () { return control_additional; }
@@ -130,6 +135,8 @@ class MIDIControllable : public PBD::Stateful
 	MIDI::byte       control_additional;
 	MIDI::channel_t  control_channel;
 	std::string     _control_description;
+	int16_t          control_rpn;
+	int16_t          control_nrpn;
 	bool             feedback;
 	uint32_t        _rid;
 	std::string     _what;
@@ -144,6 +151,12 @@ class MIDIControllable : public PBD::Stateful
 	void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *);
 	void midi_sense_program_change (MIDI::Parser &, MIDI::byte);
 	void midi_sense_pitchbend (MIDI::Parser &, MIDI::pitchbend_t);
+
+	void nrpn_value_change (MIDI::Parser&, uint16_t nrpn, float val);
+	void rpn_value_change (MIDI::Parser&, uint16_t nrpn, float val);
+	void rpn_change (MIDI::Parser&, uint16_t nrpn, int direction);
+	void nrpn_change (MIDI::Parser&, uint16_t nrpn, int direction);
+
 };
 
 #endif // __gm_midicontrollable_h__
diff --git a/libs/surfaces/mackie/button.cc b/libs/surfaces/mackie/button.cc
index ab1e198..ecb3f22 100644
--- a/libs/surfaces/mackie/button.cc
+++ b/libs/surfaces/mackie/button.cc
@@ -101,6 +101,8 @@ Button::name_to_id (const std::string& name)
 	if (!g_ascii_strcasecmp (name.c_str(), "Busses")) { return Busses; }
 	if (!g_ascii_strcasecmp (name.c_str(), "Outputs")) { return Outputs; }
 	if (!g_ascii_strcasecmp (name.c_str(), "User")) { return User; }
+	if (!g_ascii_strcasecmp (name.c_str(), "UserA")) { return UserA; }
+	if (!g_ascii_strcasecmp (name.c_str(), "UserB")) { return UserB; }
 	if (!g_ascii_strcasecmp (name.c_str(), "Shift")) { return Shift; }
 	if (!g_ascii_strcasecmp (name.c_str(), "Option")) { return Option; }
 	if (!g_ascii_strcasecmp (name.c_str(), "Ctrl")) { return Ctrl; }
diff --git a/libs/surfaces/mackie/controls.cc b/libs/surfaces/mackie/controls.cc
index bbe1029..8ed0bad 100644
--- a/libs/surfaces/mackie/controls.cc
+++ b/libs/surfaces/mackie/controls.cc
@@ -81,7 +81,7 @@ void
 Control::set_value (float val)
 {
 	if (normal_ac) {
-		normal_ac->set_value (normal_ac->interface_to_internal (val));
+		normal_ac->set_value (normal_ac->interface_to_internal (val), PBD::Controllable::NoGroup);
 	}
 }
 
diff --git a/libs/surfaces/mackie/gui.cc b/libs/surfaces/mackie/gui.cc
index ac03e41..61ca650 100644
--- a/libs/surfaces/mackie/gui.cc
+++ b/libs/surfaces/mackie/gui.cc
@@ -202,8 +202,6 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
 
 	vector<string> profiles;
 
-	profiles.push_back ("default");
-
 	for (std::map<std::string,DeviceProfile>::iterator i = DeviceProfile::device_profiles.begin(); i != DeviceProfile::device_profiles.end(); ++i) {
 		profiles.push_back (i->first);
 	}
@@ -869,7 +867,11 @@ MackieControlProtocolGUI::build_midi_port_list (vector<string> const & ports, bo
 	for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
 		row = *store->append ();
 		row[midi_port_columns.full_name] = *p;
-		row[midi_port_columns.short_name] = (*p).substr ((*p).find (':') + 1);
+		std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
+		if (pn.empty ()) {
+			pn = (*p).substr ((*p).find (':') + 1);
+		}
+		row[midi_port_columns.short_name] = pn;
 	}
 
 	return store;
diff --git a/libs/surfaces/mackie/interface.cc b/libs/surfaces/mackie/interface.cc
index 1a9760b..3b04770 100644
--- a/libs/surfaces/mackie/interface.cc
+++ b/libs/surfaces/mackie/interface.cc
@@ -74,6 +74,12 @@ probe_mackie_protocol (ControlProtocolDescriptor*)
 	return MackieControlProtocol::probe();
 }
 
+static void*
+mackie_request_buffer_factory (uint32_t num_requests)
+{
+	return MackieControlProtocol::request_factory (num_requests);
+}
+
 // Field names commented out by JE - 06-01-2010
 static ControlProtocolDescriptor mackie_descriptor = {
 	/*name :              */   "Mackie",
@@ -88,8 +94,8 @@ static ControlProtocolDescriptor mackie_descriptor = {
 	/*supports_feedback : */   false,
 	/*probe :             */   probe_mackie_protocol,
 	/*initialize :        */   new_mackie_protocol,
-	/*destroy :           */   delete_mackie_protocol
+	/*destroy :           */   delete_mackie_protocol,
+	/*request_buffer_factory */ mackie_request_buffer_factory
 };
 
-
 extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &mackie_descriptor; }
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index 93b54e7..ea5e43d 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -31,6 +31,7 @@
 #include <errno.h>
 
 #include <boost/shared_array.hpp>
+#include <glibmm/miscutils.h>
 
 #include "midi++/types.h"
 #include "midi++/port.h"
@@ -40,15 +41,19 @@
 #include "pbd/memento_command.h"
 #include "pbd/convert.h"
 
+#include "ardour/audio_track.h"
 #include "ardour/automation_control.h"
 #include "ardour/async_midi_port.h"
 #include "ardour/dB.h"
 #include "ardour/debug.h"
 #include "ardour/location.h"
 #include "ardour/meter.h"
+#include "ardour/midi_track.h"
 #include "ardour/panner.h"
 #include "ardour/panner_shell.h"
+#include "ardour/profile.h"
 #include "ardour/route.h"
+#include "ardour/route_group.h"
 #include "ardour/session.h"
 #include "ardour/tempo.h"
 #include "ardour/track.h"
@@ -100,13 +105,15 @@ bool MackieControlProtocol::probe()
 
 MackieControlProtocol::MackieControlProtocol (Session& session)
 	: ControlProtocol (session, X_("Mackie"))
-	, AbstractUI<MackieControlUIRequest> ("mackie")
+	, AbstractUI<MackieControlUIRequest> (name())
 	, _current_initial_bank (0)
+	, _frame_last (0)
 	, _timecode_type (ARDOUR::AnyTime::BBT)
 	, _gui (0)
 	, _scrub_mode (false)
 	, _flip_mode (Normal)
 	, _view_mode (Mixer)
+	, _subview_mode (None)
 	, _pot_mode (Pan)
 	, _current_selected_track (-1)
 	, _modifier_state (0)
@@ -122,6 +129,12 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
 	DeviceInfo::reload_device_info ();
 	DeviceProfile::reload_device_profiles ();
 
+	for (int i = 0; i < 9; i++) {
+		_last_bank[i] = 0;
+	}
+
+	_last_bank[Mixer] = _current_selected_track;
+
 	TrackSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::gui_track_selection_changed, this, _1, true), this);
 
 	_instance = this;
@@ -170,10 +183,10 @@ MackieControlProtocol::thread_init ()
 {
 	struct sched_param rtparam;
 
-	pthread_set_name (X_("MackieControl"));
+	pthread_set_name (event_loop_name().c_str());
 
-	PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048);
-	ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128);
+	PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
+	ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
 
 	memset (&rtparam, 0, sizeof (rtparam));
 	rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
@@ -282,21 +295,73 @@ MackieControlProtocol::get_sorted_routes()
 
 		switch (_view_mode) {
 		case Mixer:
+			if (route->route_group()) {
+				route->route_group()->set_active (true, this);
+			}
+			sorted.push_back (route);
+			remote_ids.insert (route->remote_control_id());
 			break;
 		case AudioTracks:
+			if (is_audio_track(route)) {
+				if (route->route_group()) {
+					route->route_group()->set_active (true, this);
+				}
+				sorted.push_back (route);
+				remote_ids.insert (route->remote_control_id());
+			}
 			break;
 		case Busses:
+			if (Profile->get_mixbus()) {
+#ifdef MIXBUS
+				if (route->mixbus()) {
+					sorted.push_back (route);
+					remote_ids.insert (route->remote_control_id());
+				}
+#endif				
+			} else {
+				if (!is_track(route)) {
+					if (route->route_group()) {
+						route->route_group()->set_active (true, this);
+					}
+					sorted.push_back (route);
+					remote_ids.insert (route->remote_control_id());
+				}
+			}
 			break;
 		case MidiTracks:
+			if (is_midi_track(route)) {
+				if (route->route_group()) {
+					route->route_group()->set_active (true, this);
+				}
+				sorted.push_back (route);
+				remote_ids.insert (route->remote_control_id());
+			}
 			break;
 		case Plugins:
 			break;
-		case Auxes:
+		case Auxes: // in ardour, for now aux and buss are same. for mixbus, see "Busses" case above
+			if (!is_track(route)) {
+				if (route->route_group()) {
+					route->route_group()->set_active (true, this);
+				}
+				sorted.push_back (route);
+				remote_ids.insert (route->remote_control_id());
+			}
+			break;
+		case Selected: // For example: a group
+			if (selected(route)) {
+				/* Selected may be a group in which case we want to
+				 * control each track separately.
+				 */
+				if (route->route_group()) {
+					route->route_group()->set_active (false, this);
+				}
+				sorted.push_back (route);
+				remote_ids.insert (route->remote_control_id());
+			}
 			break;
 		}
 
-		sorted.push_back (*it);
-		remote_ids.insert (route->remote_control_id());
 	}
 
 	sort (sorted.begin(), sorted.end(), RouteByRemoteId());
@@ -340,7 +405,6 @@ MackieControlProtocol::switch_banks (uint32_t initial, bool force)
 		 */
 		return;
 	}
-	set_flip_mode (Normal);
 	_current_initial_bank = initial;
 	_current_selected_track = -1;
 
@@ -372,12 +436,9 @@ MackieControlProtocol::switch_banks (uint32_t initial, bool force)
 		}
 	}
 
-	/* reset this to get the right display of view mode after the switch */
-	set_view_mode (_view_mode);
-
 	/* make sure selection is correct */
 
-	_gui_track_selection_changed (&_last_selected_routes, false);
+	_gui_track_selection_changed (&_last_selected_routes, false, false);
 
 	/* current bank has not been saved */
 	session->set_dirty();
@@ -590,6 +651,7 @@ MackieControlProtocol::device_ready ()
 
 	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("device ready init (active=%1)\n", active()));
 	update_surfaces ();
+	set_pot_mode (_pot_mode);
 }
 
 // send messages to surface to set controls to correct values
@@ -642,6 +704,7 @@ MackieControlProtocol::connect_session_signals()
 {
 	// receive routes added
 	session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_route_added, this, _1), this);
+	session->RouteAddedOrRemoved.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_route_added_or_removed, this), this);
 	// receive record state toggled
 	session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_record_state_changed, this), this);
 	// receive transport state changed
@@ -665,14 +728,10 @@ MackieControlProtocol::connect_session_signals()
 void
 MackieControlProtocol::set_profile (const string& profile_name)
 {
-	if (profile_name == "default") {
-		/* reset to default */
-		_device_profile = DeviceProfile (profile_name);
-	}
-
 	map<string,DeviceProfile>::iterator d = DeviceProfile::device_profiles.find (profile_name);
 
 	if (d == DeviceProfile::device_profiles.end()) {
+		_device_profile = DeviceProfile (profile_name);
 		return;
 	}
 
@@ -999,7 +1058,17 @@ MackieControlProtocol::set_state (const XMLNode & node, int version)
 	}
 
 	if ((prop = node.property (X_("device-profile"))) != 0) {
-		set_profile (prop->value());
+		if (prop->value().empty()) {
+			string default_profile_name;
+
+			default_profile_name = Glib::get_user_name();
+			default_profile_name += ' ';
+			default_profile_name += _device_info.name();
+
+			set_profile (default_profile_name);
+		} else {
+			set_profile (prop->value());
+		}
 	}
 
 	XMLNode* dnode = node.child (X_("Configurations"));
@@ -1084,6 +1153,13 @@ MackieControlProtocol::update_timecode_display()
 	// do assignment here so current_frame is fixed
 	framepos_t current_frame = session->transport_frame();
 	string timecode;
+	// For large jumps in play head possition do full reset
+	int moved = (current_frame - _frame_last) / session->frame_rate ();
+	if (moved) {
+		DEBUG_TRACE (DEBUG::MackieControl, "Timecode reset\n");
+		_timecode_last = string (10, ' ');
+	}
+	_frame_last = current_frame;
 
 	switch (_timecode_type) {
 	case ARDOUR::AnyTime::BBT:
@@ -1123,6 +1199,15 @@ void MackieControlProtocol::notify_parameter_changed (std::string const & p)
 	}
 }
 
+void
+MackieControlProtocol::notify_route_added_or_removed ()
+{
+	Glib::Threads::Mutex::Lock lm (surfaces_lock);
+	for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
+		(*s)->master_monitor_may_have_changed ();
+	}
+}
+
 // RouteList is the set of routes that have just been added
 void
 MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
@@ -1135,6 +1220,15 @@ MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
 		}
 	}
 
+	/* special case: single route, and it is the monitor or master out */
+
+	if (rl.size() == 1 && (rl.front()->is_monitor() || rl.front()->is_master())) {
+		Glib::Threads::Mutex::Lock lm (surfaces_lock);
+		for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
+			(*s)->master_monitor_may_have_changed ();
+		}
+	}
+
 	// currently assigned banks are less than the full set of
 	// strips, so activate the new strip now.
 
@@ -1224,6 +1318,9 @@ MackieControlProtocol::notify_transport_state_changed()
 	update_global_button (Button::Rewind, session->transport_speed() < 0.0);
 	update_global_button (Button::Ffwd, session->transport_speed() > 1.0);
 
+	// sometimes a return to start leaves time code at old time
+	_timecode_last = string (10, ' ');
+
 	notify_metering_state_changed ();
 }
 
@@ -1397,7 +1494,6 @@ MackieControlProtocol::build_button_map ()
 	DEFINE_BUTTON_HANDLER (Button::UserA, &MackieControlProtocol::user_a_press, &MackieControlProtocol::user_a_release);
 	DEFINE_BUTTON_HANDLER (Button::UserB, &MackieControlProtocol::user_b_press, &MackieControlProtocol::user_b_release);
 	DEFINE_BUTTON_HANDLER (Button::MasterFaderTouch, &MackieControlProtocol::master_fader_touch_press, &MackieControlProtocol::master_fader_touch_release);
-
 }
 
 void
@@ -1528,16 +1624,101 @@ MackieControlProtocol::clear_ports ()
 }
 
 void
+MackieControlProtocol::notify_subview_route_deleted ()
+{
+	/* return to global/mixer view */
+	_subview_route.reset ();
+	set_view_mode (Mixer);
+}
+
+void
+MackieControlProtocol::set_subview_mode (SubViewMode sm, boost::shared_ptr<Route> r)
+{
+	SubViewMode old_mode = _subview_mode;
+	boost::shared_ptr<Route> old_route = _subview_route;
+
+	_subview_mode = sm;
+
+	if (r) {
+		/* retain _subview_route even if it is reset to null implicitly */
+ 		_subview_route = r;
+	}
+
+	if ((_subview_mode != old_mode) || (_subview_route != old_route)) {
+
+		if (r != old_route) {
+			subview_route_connections.drop_connections ();
+			if (_subview_route) {
+				_subview_route->DropReferences.connect (subview_route_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_subview_route_deleted, this), this);
+			}
+		}
+
+		/* subview mode did actually change */
+
+		{
+			Surfaces copy; /* can't hold surfaces lock while calling Strip::subview_mode_changed */
+
+			{
+				Glib::Threads::Mutex::Lock lm (surfaces_lock);
+				copy = surfaces;
+			}
+
+			for (Surfaces::iterator s = copy.begin(); s != copy.end(); ++s) {
+				(*s)->subview_mode_changed ();
+			}
+		}
+
+		if (_subview_mode != old_mode) {
+
+			/* turn buttons related to vpot mode on or off as required */
+
+			switch (_subview_mode) {
+			case MackieControlProtocol::None:
+				pot_mode_globals ();
+				break;
+			case MackieControlProtocol::EQ:
+				update_global_button (Button::Eq, on);
+				update_global_button (Button::Dyn, off);
+				update_global_button (Button::AudioInstruments, off); /* faking up Dyn */
+				update_global_button (Button::Trim, off);
+				update_global_button (Button::Send, off);
+				update_global_button (Button::Pan, off);
+				break;
+			case MackieControlProtocol::Dynamics:
+				update_global_button (Button::Eq, off);
+				update_global_button (Button::Dyn, on);
+				update_global_button (Button::AudioInstruments, on); /* faking up Dyn */
+				update_global_button (Button::Trim, off);
+				update_global_button (Button::Send, off);
+				update_global_button (Button::Pan, off);
+				break;
+			}
+		}
+	}
+}
+
+void
 MackieControlProtocol::set_view_mode (ViewMode m)
 {
-	Glib::Threads::Mutex::Lock lm (surfaces_lock);
+	_last_bank[_view_mode] = _current_initial_bank;
 
 	_view_mode = m;
+	set_subview_mode (None, boost::shared_ptr<Route>());
 
-	for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
-		(*s)->update_view_mode_display ();
-	}
+	switch_banks(_last_bank[_view_mode], true);
+	display_view_mode ();
+}
+
+void
+MackieControlProtocol::display_view_mode ()
+{
+	{
+		Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
+		for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
+			(*s)->update_view_mode_display ();
+		}
+	}
 }
 
 void
@@ -1563,6 +1744,11 @@ MackieControlProtocol::set_flip_mode (FlipMode fm)
 void
 MackieControlProtocol::set_pot_mode (PotMode m)
 {
+	// maybe not in flip mode.
+	if (flip_mode()) {
+		return;
+	}
+
 	_pot_mode = m;
 
 	{
@@ -1574,6 +1760,16 @@ MackieControlProtocol::set_pot_mode (PotMode m)
 		}
 	}
 
+	pot_mode_globals ();
+}
+
+void
+MackieControlProtocol::pot_mode_globals ()
+{
+	update_global_button (Button::Eq, off);
+	update_global_button (Button::Dyn, off);
+	update_global_button (Button::AudioInstruments, off);
+
 	switch (_pot_mode) {
 	case Trim:
 		update_global_button (Button::Track, on);
@@ -1627,11 +1823,11 @@ MackieControlProtocol::force_special_route_to_strip (boost::shared_ptr<Route> r,
 void
 MackieControlProtocol::gui_track_selection_changed (ARDOUR::RouteNotificationListPtr rl, bool save_list)
 {
-	_gui_track_selection_changed (rl.get(), save_list);
+	_gui_track_selection_changed (rl.get(), save_list, true);
 }
 
 void
-MackieControlProtocol::_gui_track_selection_changed (ARDOUR::RouteNotificationList* rl, bool save_list)
+MackieControlProtocol::_gui_track_selection_changed (ARDOUR::RouteNotificationList* rl, bool save_list, bool gui_selection_did_change)
 {
 	/* We need to keep a list of the most recently selected routes around,
 	   but we are not allowed to keep shared_ptr<Route> unless we want to
@@ -1662,6 +1858,11 @@ MackieControlProtocol::_gui_track_selection_changed (ARDOUR::RouteNotificationLi
 	if (save_list) {
 		_last_selected_routes = *rl;
 	}
+
+	if (gui_selection_did_change) {
+		/* actual GUI selection changed */
+		set_subview_mode (_subview_mode, first_selected_route());
+	}
 }
 
 framepos_t
@@ -1984,3 +2185,80 @@ MackieControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port> wp1, st
 		}
 	}
 }
+
+bool
+MackieControlProtocol::is_track (boost::shared_ptr<Route> r) const
+{
+	return boost::dynamic_pointer_cast<Track>(r) != 0;
+}
+
+bool
+MackieControlProtocol::is_audio_track (boost::shared_ptr<Route> r) const
+{
+	return boost::dynamic_pointer_cast<AudioTrack>(r) != 0;
+}
+
+bool
+MackieControlProtocol::is_midi_track (boost::shared_ptr<Route> r) const
+{
+	return boost::dynamic_pointer_cast<MidiTrack>(r) != 0;
+}
+
+bool
+MackieControlProtocol::selected (boost::shared_ptr<Route> r) const
+{
+	const RouteNotificationList* rl = &_last_selected_routes;
+
+	for (ARDOUR::RouteNotificationList::const_iterator i = rl->begin(); i != rl->end(); ++i) {
+		boost::shared_ptr<ARDOUR::Route> rt = (*i).lock();
+		if (rt == r) {
+			return true;
+		}
+	}
+	return false;
+}
+
+boost::shared_ptr<Route>
+MackieControlProtocol::first_selected_route () const
+{
+	if (_last_selected_routes.empty()) {
+		return boost::shared_ptr<Route>();
+	}
+
+	boost::shared_ptr<Route> r = _last_selected_routes.front().lock();
+
+	return r; /* may be null */
+}
+
+boost::shared_ptr<Route>
+MackieControlProtocol::subview_route () const
+{
+	return _subview_route;
+}
+
+uint32_t
+MackieControlProtocol::global_index (Strip& strip)
+{
+	Glib::Threads::Mutex::Lock lm (surfaces_lock);
+	uint32_t global = 0;
+
+	for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
+		if ((*s).get() == strip.surface()) {
+			return global + strip.index();
+		}
+		global += (*s)->n_strips ();
+	}
+
+	return global;
+}
+
+void*
+MackieControlProtocol::request_factory (uint32_t num_requests)
+{
+	/* AbstractUI<T>::request_buffer_factory() is a template method only
+	   instantiated in this source module. To provide something visible for
+	   use in the interface/descriptor, we have this static method that is
+	   template-free.
+	*/
+	return request_buffer_factory (num_requests);
+}
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index 6e58f07..802d5a6 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -58,6 +58,7 @@ namespace Mackie {
 	class Control;
 	class SurfacePort;
 	class Button;
+	class Strip;
 }
 
 gboolean ipmidi_input_handler (GIOChannel*, GIOCondition condition, void *data);
@@ -107,9 +108,16 @@ class MackieControlProtocol
 		MidiTracks,
 		Busses,
 		Auxes,
+		Selected,
 		Plugins,
 	};
 
+	enum SubViewMode {
+		None,
+		EQ,
+		Dynamics,
+	};
+
 	enum PotMode {
 		Trim,
 		Send,
@@ -142,13 +150,24 @@ class MackieControlProtocol
 
 	FlipMode flip_mode () const { return _flip_mode; }
 	ViewMode view_mode () const { return _view_mode; }
+	SubViewMode subview_mode () const { return _subview_mode; }
+	boost::shared_ptr<ARDOUR::Route> subview_route() const;
 	PotMode pot_mode () const { return _pot_mode; }
 	bool zoom_mode () const { return modifier_state() & MODIFIER_ZOOM; }
 	bool     metering_active () const { return _metering_active; }
 
+	bool is_track (boost::shared_ptr<ARDOUR::Route>) const;
+	bool is_audio_track (boost::shared_ptr<ARDOUR::Route>) const;
+	bool is_midi_track (boost::shared_ptr<ARDOUR::Route>) const;
+	bool selected (boost::shared_ptr<ARDOUR::Route>) const;
+	boost::shared_ptr<ARDOUR::Route> first_selected_route () const;
+
 	void set_view_mode (ViewMode);
+	void set_subview_mode (SubViewMode, boost::shared_ptr<ARDOUR::Route>);
 	void set_flip_mode (FlipMode);
 	void set_pot_mode (PotMode);
+	void pot_mode_globals ();
+	void display_view_mode ();
 
 	XMLNode& get_state ();
 	int set_state (const XMLNode&, int version);
@@ -159,6 +178,7 @@ class MackieControlProtocol
 	*/
 
 	static bool probe();
+	static void* request_factory (uint32_t);
 
 	mutable Glib::Threads::Mutex surfaces_lock;
 	typedef std::list<boost::shared_ptr<Mackie::Surface> > Surfaces;
@@ -167,6 +187,8 @@ class MackieControlProtocol
 	boost::shared_ptr<Mackie::Surface> get_surface_by_raw_pointer (void*) const;
 	boost::shared_ptr<Mackie::Surface> nth_surface (uint32_t) const;
 
+	uint32_t global_index (Mackie::Strip&);
+
 	std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
 
 	void set_master_on_surface_strip (uint32_t surface, uint32_t strip);
@@ -180,6 +202,8 @@ class MackieControlProtocol
 
 	void handle_button_event (Mackie::Surface&, Mackie::Button& button, Mackie::ButtonState);
 
+	void notify_subview_route_deleted ();
+	void notify_route_added_or_removed ();
 	void notify_route_added (ARDOUR::RouteList &);
 	void notify_remote_id_changed();
 
@@ -296,11 +320,13 @@ class MackieControlProtocol
 	PBD::ScopedConnectionList audio_engine_connections;
 	PBD::ScopedConnectionList session_connections;
 	PBD::ScopedConnectionList route_connections;
+	PBD::ScopedConnectionList subview_route_connections;
 	PBD::ScopedConnectionList gui_connections;
 	// timer for two quick marker left presses
 	Mackie::Timer            _frm_left_last;
 	// last written timecode string
 	std::string              _timecode_last;
+	framepos_t				 _frame_last;
 	// Which timecode are we displaying? BBT or Timecode
 	ARDOUR::AnyTime::Type    _timecode_type;
 	// Bundle to represent our input ports
@@ -311,6 +337,8 @@ class MackieControlProtocol
 	bool                     _scrub_mode;
 	FlipMode                 _flip_mode;
 	ViewMode                 _view_mode;
+	SubViewMode              _subview_mode;
+	boost::shared_ptr<ARDOUR::Route> _subview_route;
 	PotMode                  _pot_mode;
 	int                      _current_selected_track;
 	int                      _modifier_state;
@@ -322,6 +350,7 @@ class MackieControlProtocol
 	ARDOUR::RouteNotificationList _last_selected_routes;
 	XMLNode*                 configuration_state;
 	int                      state_version;
+	int                      _last_bank[9];
 
 	boost::shared_ptr<ArdourSurface::Mackie::Surface>	_master_surface;
 
@@ -343,7 +372,7 @@ class MackieControlProtocol
 	void force_special_route_to_strip (boost::shared_ptr<ARDOUR::Route> r, uint32_t surface, uint32_t strip_number);
 	void build_button_map ();
 	void gui_track_selection_changed (ARDOUR::RouteNotificationListPtr, bool save_list);
-	void _gui_track_selection_changed (ARDOUR::RouteNotificationList*, bool save_list);
+	void _gui_track_selection_changed (ARDOUR::RouteNotificationList*, bool save_list, bool gui_did_change);
 	int ipmidi_restart ();
         void initialize ();
         int set_device_info (const std::string& device_name);
diff --git a/libs/surfaces/mackie/mcp_buttons.cc b/libs/surfaces/mackie/mcp_buttons.cc
index a2bcdf7..b2fd79b 100644
--- a/libs/surfaces/mackie/mcp_buttons.cc
+++ b/libs/surfaces/mackie/mcp_buttons.cc
@@ -22,6 +22,7 @@
 #include "pbd/memento_command.h"
 
 #include "ardour/debug.h"
+#include "ardour/profile.h"
 #include "ardour/session.h"
 #include "ardour/route.h"
 #include "ardour/location.h"
@@ -97,6 +98,10 @@ MackieControlProtocol::cmd_alt_release (Button &)
 LedState
 MackieControlProtocol::left_press (Button &)
 {
+	if (_subview_mode != None) {
+		return none;
+	}
+
 	Sorted sorted = get_sorted_routes();
 	uint32_t strip_cnt = n_strips ();
 
@@ -121,6 +126,10 @@ MackieControlProtocol::left_release (Button &)
 LedState
 MackieControlProtocol::right_press (Button &)
 {
+	if (_subview_mode != None) {
+		return none;
+	}
+
 	Sorted sorted = get_sorted_routes();
 	uint32_t strip_cnt = n_strips();
 	uint32_t route_cnt = sorted.size();
@@ -265,6 +274,9 @@ MackieControlProtocol::cursor_down_release (Button&)
 LedState
 MackieControlProtocol::channel_left_press (Button &)
 {
+	if (_subview_mode != None) {
+		return none;
+	}
 	Sorted sorted = get_sorted_routes();
 	if (sorted.size() > n_strips()) {
 		prev_track();
@@ -283,6 +295,9 @@ MackieControlProtocol::channel_left_release (Button &)
 LedState
 MackieControlProtocol::channel_right_press (Button &)
 {
+	if (_subview_mode != None) {
+		return none;
+	}
 	Sorted sorted = get_sorted_routes();
 	if (sorted.size() > n_strips()) {
 		next_track();
@@ -408,7 +423,18 @@ MackieControlProtocol::marker_press (Button &)
 {
 	string markername;
 
-	session->locations()->next_available_name (markername,"mcu");
+	/* Don't add another mark if one exists within 1/100th of a second of
+	 * the current position and we're not rolling.
+	 */
+
+
+	framepos_t where = session->audible_frame();
+
+	if (session->transport_stopped() && session->locations()->mark_at (where, session->frame_rate() / 100.0)) {
+		return off;
+	}
+
+	session->locations()->next_available_name (markername,"marker");
 	add_marker (markername);
 
 	return on;
@@ -557,6 +583,10 @@ MackieControlProtocol::enter_release (Button &)
 LedState
 MackieControlProtocol::bank_release (Button& b, uint32_t basic_bank_num)
 {
+	if (_subview_mode != None) {
+		return none;
+	}
+
 	uint32_t bank_num = basic_bank_num;
 
 	if (b.long_press_count() > 0) {
@@ -677,9 +707,15 @@ MackieControlProtocol::plugin_release (Button &)
 LedState
 MackieControlProtocol::eq_press (Button &)
 {
-	//set_view_mode (EQ);
-	// not implemented yet, turn off (see comments for send button)
-	return off;
+	if (Profile->get_mixbus()) {
+		boost::shared_ptr<Route> r = first_selected_route ();
+		if (r && r->eq_band_cnt() > 0) {
+			set_subview_mode (EQ, r);
+			return none; /* led state handled by set_subview_mode() */
+		}
+	}
+	return none;
+
 }
 LedState
 MackieControlProtocol::eq_release (Button &)
@@ -689,10 +725,18 @@ MackieControlProtocol::eq_release (Button &)
 LedState
 MackieControlProtocol::dyn_press (Button &)
 {
-	//set_view_mode (Dynamics);
-	// same as send
-	return off;
+	if (Profile->get_mixbus()) {
+		boost::shared_ptr<Route> r = first_selected_route ();
+
+		if (r) {
+			set_subview_mode (Dynamics, r);
+			return none; /* led state handled by set_subview_mode() */
+		}
+	}
+
+	return none;
 }
+
 LedState
 MackieControlProtocol::dyn_release (Button &)
 {
@@ -839,8 +883,6 @@ MackieControlProtocol::track_release (Mackie::Button&)
 Mackie::LedState
 MackieControlProtocol::send_press (Mackie::Button&)
 {
-	return none;
-	// remove above line when sends implemented
 	set_pot_mode (Send);
 	return none;
 }
@@ -882,14 +924,16 @@ MackieControlProtocol::audiotracks_release (Mackie::Button&)
 	return none;
 }
 Mackie::LedState
-MackieControlProtocol::audioinstruments_press (Mackie::Button&)
+MackieControlProtocol::audioinstruments_press (Mackie::Button& b)
 {
-	return none;
+	return dyn_press (b);
 }
+
 Mackie::LedState
-MackieControlProtocol::audioinstruments_release (Mackie::Button&)
+MackieControlProtocol::audioinstruments_release (Mackie::Button& b)
 {
-	return none;
+	return dyn_release (b);
+
 }
 Mackie::LedState
 MackieControlProtocol::aux_press (Mackie::Button&)
@@ -931,6 +975,7 @@ MackieControlProtocol::user_press (Mackie::Button&)
 Mackie::LedState
 MackieControlProtocol::user_release (Mackie::Button&)
 {
+	set_view_mode (Selected);
 	return none;
 }
 Mackie::LedState
@@ -996,6 +1041,7 @@ MackieControlProtocol::click_release (Mackie::Button&)
 Mackie::LedState
 MackieControlProtocol::view_press (Mackie::Button&)
 {
+	set_view_mode (Mixer);
 	return none;
 }
 Mackie::LedState
diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc
index 7f4cda8..f2c56d8 100644
--- a/libs/surfaces/mackie/strip.cc
+++ b/libs/surfaces/mackie/strip.cc
@@ -18,8 +18,9 @@
 */
 
 #include <sstream>
+#include <vector>
+
 #include <stdint.h>
-#include "strip.h"
 
 #include <sys/time.h>
 
@@ -35,6 +36,7 @@
 #include "ardour/debug.h"
 #include "ardour/midi_ui.h"
 #include "ardour/meter.h"
+#include "ardour/plugin_insert.h"
 #include "ardour/pannable.h"
 #include "ardour/panner.h"
 #include "ardour/panner_shell.h"
@@ -43,11 +45,14 @@
 #include "ardour/session.h"
 #include "ardour/send.h"
 #include "ardour/track.h"
+#include "ardour/midi_track.h"
 #include "ardour/user_bundle.h"
+#include "ardour/profile.h"
 
 #include "mackie_control_protocol.h"
 #include "surface_port.h"
 #include "surface.h"
+#include "strip.h"
 #include "button.h"
 #include "led.h"
 #include "pot.h"
@@ -94,11 +99,15 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::
 	, _metering_active (true)
 	, _block_vpot_mode_redisplay_until (0)
 	, _block_screen_redisplay_until (0)
+	, eq_band (-1)
 	, _pan_mode (PanAzimuthAutomation)
+	, _trim_mode (TrimAutomation)
+	, vpot_parameter (PanAzimuthAutomation)
 	, _last_gain_position_written (-1.0)
 	, _last_pan_azi_position_written (-1.0)
 	, _last_pan_width_position_written (-1.0)
 	, _last_trim_position_written (-1.0)
+	, _current_send (0)
 	, redisplay_requests (256)
 {
 	_fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
@@ -163,6 +172,8 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
 		return;
 	}
 
+	mb_pan_controllable.reset();
+
 	route_connections.drop_connections ();
 
 	_solo->set_control (boost::shared_ptr<AutomationControl>());
@@ -183,6 +194,8 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
 	control_by_parameter[PanLFEAutomation] = (Control*) 0;
 	control_by_parameter[GainAutomation] = (Control*) 0;
 	control_by_parameter[TrimAutomation] = (Control*) 0;
+	control_by_parameter[PhaseAutomation] = (Control*) 0;
+	control_by_parameter[SendAutomation] = (Control*) 0;
 
 	reset_saved_values ();
 
@@ -197,24 +210,30 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
 	_solo->set_control (_route->solo_control());
 	_mute->set_control (_route->mute_control());
 
-	_pan_mode = PanAzimuthAutomation;
-	potmode_changed (true);
-
 	_route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
 	_route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
 
 	_route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
 
-	if (_route->trim()) {
+	if (_route->trim() && route()->trim()->active()) {
 		_route->trim_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_trim_changed, this, false), ui_context());
 	}
 
-	boost::shared_ptr<Pannable> pannable = _route->pannable();
+	if (_route->phase_invert().size()) {
+		_route->phase_invert_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_phase_changed, this, false), ui_context());
+		_route->phase_control()->set_channel(0);
+	}
 
-	if (pannable && _route->panner()) {
-		pannable->pan_azimuth_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
-		pannable->pan_width_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
+	boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control();
+	if (pan_control) {
+		pan_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
 	}
+
+	pan_control = _route->pan_width_control();
+	if (pan_control) {
+		pan_control->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
+	}
+
 	_route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
 	_route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
 
@@ -223,8 +242,6 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
 	if (trk) {
 		_recenable->set_control (trk->rec_enable_control());
 		trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
-
-
 	}
 
 	// TODO this works when a currently-banked route is made inactive, but not
@@ -233,33 +250,50 @@ Strip::set_route (boost::shared_ptr<Route> r, bool /*with_messages*/)
 	_route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
 	_route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
 
-	/* Update */
-
-	notify_all ();
-
 	/* setup legal VPot modes for this route */
 
 	possible_pot_parameters.clear();
 
-	if (pannable) {
-		boost::shared_ptr<Panner> panner = _route->panner();
-		if (panner) {
-			set<Evoral::Parameter> automatable = panner->what_can_be_automated ();
-			set<Evoral::Parameter>::iterator a;
+	if (_route->pan_azimuth_control()) {
+		possible_pot_parameters.push_back (PanAzimuthAutomation);
+	}
+	if (_route->pan_width_control()) {
+		possible_pot_parameters.push_back (PanWidthAutomation);
+	}
+	if (_route->pan_elevation_control()) {
+		possible_pot_parameters.push_back (PanElevationAutomation);
+	}
+	if (_route->pan_frontback_control()) {
+		possible_pot_parameters.push_back (PanFrontBackAutomation);
+	}
+	if (_route->pan_lfe_control()) {
+		possible_pot_parameters.push_back (PanLFEAutomation);
+	}
 
-			if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) {
-				possible_pot_parameters.push_back (PanAzimuthAutomation);
-			}
+	if (_route->trim() && route()->trim()->active()) {
+		possible_pot_parameters.push_back (TrimAutomation);
+	}
 
-			if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) {
-				possible_pot_parameters.push_back (PanWidthAutomation);
-			}
-		}
+	possible_trim_parameters.clear();
+
+	if (_route->trim() && route()->trim()->active()) {
+		possible_trim_parameters.push_back (TrimAutomation);
+		_trim_mode = TrimAutomation;
 	}
 
-	if (_route->trim()) {
-		possible_pot_parameters.push_back (TrimAutomation);
+	if (_route->phase_invert().size()) {
+		possible_trim_parameters.push_back (PhaseAutomation);
+		_route->phase_control()->set_channel(0);
+		if (_trim_mode != TrimAutomation) {
+			_trim_mode = PhaseAutomation;
+		}
 	}
+	_current_send = 0;
+	/* Update */
+	_pan_mode = PanAzimuthAutomation;
+	potmode_changed (false);
+	notify_all ();
+
 }
 
 void
@@ -269,6 +303,10 @@ Strip::notify_all()
 		zero ();
 		return;
 	}
+	// The active V-pot control may not be active for this strip
+	// But if we zero it in the controls function it may erase
+	// the one we do want
+	_surface->write (_vpot->zero());
 
 	notify_solo_changed ();
 	notify_mute_changed ();
@@ -278,6 +316,8 @@ Strip::notify_all()
 	notify_panner_width_changed ();
 	notify_record_enable_changed ();
 	notify_trim_changed ();
+	notify_phase_changed ();
+	notify_processor_changed ();
 }
 
 void
@@ -363,8 +403,7 @@ Strip::notify_trim_changed (bool force_update)
 {
 	if (_route) {
 
-		if (!_route->trim()) {
-			_surface->write (_vpot->zero());
+		if (!_route->trim() || !route()->trim()->active()) {
 			return;
 		}
 		Control* control = 0;
@@ -397,6 +436,74 @@ Strip::notify_trim_changed (bool force_update)
 }
 
 void
+Strip::notify_phase_changed (bool force_update)
+{
+	if (_route) {
+		if (!_route->phase_invert().size()) {
+			return;
+		}
+
+		Control* control = 0;
+		ControlParameterMap::iterator i = control_by_parameter.find (PhaseAutomation);
+
+		if (i == control_by_parameter.end()) {
+			return;
+		}
+
+		control = i->second;
+
+		float normalized_position = _route->phase_control()->get_value();
+
+		if (control == _fader) {
+			if (!_fader->in_use()) {
+				_surface->write (_fader->set_position (normalized_position));
+				queue_parameter_display (PhaseAutomation, normalized_position);
+			}
+		} else if (control == _vpot) {
+			_surface->write (_vpot->set (normalized_position, true, Pot::wrap));
+			queue_parameter_display (PhaseAutomation, normalized_position);
+		}
+	}
+}
+
+void
+Strip::notify_processor_changed (bool force_update)
+{
+	if (_route) {
+		boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
+		if (!p) {
+			return;
+		}
+
+		Control* control = 0;
+		ControlParameterMap::iterator i = control_by_parameter.find (SendAutomation);
+
+		if (i == control_by_parameter.end()) {
+			return;
+		}
+
+		control = i->second;
+
+		boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
+		boost::shared_ptr<Amp> a = s->amp();
+		boost::shared_ptr<AutomationControl> ac = a->gain_control();
+
+		float gain_coefficient = ac->get_value();
+		float normalized_position = ac->internal_to_interface (gain_coefficient);
+
+		if (control == _fader) {
+			if (!_fader->in_use()) {
+				_surface->write (_fader->set_position (normalized_position));
+				queue_parameter_display (SendAutomation, gain_coefficient);
+			}
+		} else if (control == _vpot) {
+			_surface->write (_vpot->set (normalized_position, true, Pot::dot));
+			queue_parameter_display (SendAutomation, gain_coefficient);
+		}
+	}
+}
+
+void
 Strip::notify_property_changed (const PropertyChange& what_changed)
 {
 	if (!what_changed.contains (ARDOUR::Properties::name)) {
@@ -409,11 +516,23 @@ Strip::notify_property_changed (const PropertyChange& what_changed)
 void
 Strip::show_route_name ()
 {
-	if (!_route) {
+	MackieControlProtocol::SubViewMode svm = _surface->mcp().subview_mode();
+
+	if (svm != MackieControlProtocol::None) {
+		/* subview mode is responsible for upper line */
 		return;
 	}
+
+	string fullname = string();
+	if (!_route) {
+		// make sure first three strips get cleared of view mode
+		if (_index > 2) {
+			return;
+		}
+	} else {
+		fullname = _route->name();
+	}
 	string line1;
-	string fullname = _route->name();
 
 	if (fullname.length() <= 6) {
 		line1 = fullname;
@@ -425,90 +544,195 @@ Strip::show_route_name ()
 }
 
 void
+Strip::notify_eq_change (AutomationType type, uint32_t band, bool force_update)
+{
+	boost::shared_ptr<Route> r = _surface->mcp().subview_route();
+
+	if (!r) {
+		/* not in subview mode */
+		return;
+	}
+
+	if (_surface->mcp().subview_mode() != MackieControlProtocol::EQ) {
+		/* no longer in EQ subview mode */
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> control;
+
+	switch (type) {
+	case EQGain:
+		control = r->eq_gain_controllable (band);
+		break;
+	case EQFrequency:
+		control = r->eq_freq_controllable (band);
+		break;
+	case EQQ:
+		control = r->eq_q_controllable (band);
+		break;
+	case EQShape:
+		control = r->eq_shape_controllable (band);
+		break;
+	case EQHPF:
+		control = r->eq_hpf_controllable ();
+		break;
+	case EQEnable:
+		control = r->eq_enable_controllable ();
+		break;
+	default:
+		break;
+	}
+
+	if (control) {
+		float val = control->get_value();
+		queue_parameter_display (type, val);
+		/* update pot/encoder */
+		_surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
+	}
+}
+
+void
+Strip::notify_dyn_change (AutomationType type, bool force_update, bool propagate_mode)
+{
+	boost::shared_ptr<Route> r = _surface->mcp().subview_route();
+
+	if (!r) {
+		/* not in subview mode */
+		return;
+	}
+
+	if (_surface->mcp().subview_mode() != MackieControlProtocol::Dynamics) {
+		/* no longer in EQ subview mode */
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> control;
+	bool reset_all = false;
+
+	switch (type) {
+	case CompThreshold:
+		control = r->comp_threshold_controllable ();
+		break;
+	case CompSpeed:
+		control = r->comp_speed_controllable ();
+		break;
+	case CompMode:
+		control = r->comp_mode_controllable ();
+		reset_all = true;
+		break;
+	case CompMakeup:
+		control = r->comp_makeup_controllable ();
+		break;
+	case CompRedux:
+		control = r->comp_redux_controllable ();
+		break;
+	case CompEnable:
+		control = r->comp_enable_controllable ();
+		break;
+	default:
+		break;
+	}
+
+	if (propagate_mode && reset_all) {
+		_surface->subview_mode_changed ();
+	}
+
+	if (control) {
+		float val = control->get_value();
+		queue_parameter_display (type, val);
+		/* update pot/encoder */
+		_surface->write (_vpot->set (control->internal_to_interface (val), true, Pot::wrap));
+	}
+}
+
+void
 Strip::notify_panner_azi_changed (bool force_update)
 {
-	if (_route) {
+	if (!_route) {
+		return;
+	}
 
-		DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
+	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
 
-		boost::shared_ptr<Pannable> pannable = _route->pannable();
+	boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
 
-		if (!pannable || !_route->panner()) {
-			_surface->write (_vpot->zero());
-			return;
-		}
+	if (!pan_control) {
+		return;
+	}
 
-		Control* control = 0;
-		ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
+	Control* control = 0;
+	ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
 
-		if (i == control_by_parameter.end()) {
-			return;
-		}
+	if (i == control_by_parameter.end()) {
+		return;
+	}
 
-		control = i->second;
+	control = i->second;
 
-		double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value());
+	double normalized_pos = pan_control->internal_to_interface (pan_control->get_value());
+	double internal_pos = pan_control->get_value();
 
-		if (force_update || pos != _last_pan_azi_position_written) {
+	if (force_update || (normalized_pos != _last_pan_azi_position_written)) {
 
-			if (control == _fader) {
-				if (!_fader->in_use()) {
-					_surface->write (_fader->set_position (pos));
-					queue_parameter_display (PanAzimuthAutomation, pos);
-				}
-			} else if (control == _vpot) {
-				_surface->write (_vpot->set (pos, true, Pot::dot));
-				queue_parameter_display (PanAzimuthAutomation, pos);
+		if (control == _fader) {
+			if (!_fader->in_use()) {
+				_surface->write (_fader->set_position (normalized_pos));
+				/* show actual internal value to user */
+				queue_parameter_display (PanAzimuthAutomation, internal_pos);
 			}
-
-			_last_pan_azi_position_written = pos;
+		} else if (control == _vpot) {
+			_surface->write (_vpot->set (normalized_pos, true, Pot::dot));
+			/* show actual internal value to user */
+			queue_parameter_display (PanAzimuthAutomation, internal_pos);
 		}
+
+		_last_pan_azi_position_written = normalized_pos;
 	}
 }
 
 void
 Strip::notify_panner_width_changed (bool force_update)
 {
-	if (_route) {
+	if (!_route) {
+		return;
+	}
 
-		DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
+	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
 
-		boost::shared_ptr<Pannable> pannable = _route->pannable();
+	boost::shared_ptr<AutomationControl> pan_control = _route->pan_width_control ();
 
-		if (!pannable || !_route->panner()) {
-			_surface->write (_vpot->zero());
-			return;
-		}
+	if (!pan_control) {
+		return;
+	}
 
-		Control* control = 0;
-		ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
+	Control* control = 0;
+	ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
 
-		if (i == control_by_parameter.end()) {
-			return;
-		}
+	if (i == control_by_parameter.end()) {
+		return;
+	}
 
-		control = i->second;
+	control = i->second;
 
-		double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
+	double pos = pan_control->internal_to_interface (pan_control->get_value());
 
-		if (force_update || pos != _last_pan_azi_position_written) {
+	if (force_update || pos != _last_pan_width_position_written) {
 
-			if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+		if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
 
-				if (control == _fader) {
-					if (!control->in_use()) {
-						_surface->write (_fader->set_position (pos));
-						queue_parameter_display (PanWidthAutomation, pos);
-					}
+			if (control == _fader) {
+				if (!control->in_use()) {
+					_surface->write (_fader->set_position (pos));
+					queue_parameter_display (PanWidthAutomation, pos);
 				}
-
-			} else if (control == _vpot) {
-				_surface->write (_vpot->set (pos, true, Pot::spread));
-				queue_parameter_display (PanWidthAutomation, pos);
 			}
 
-			_last_pan_azi_position_written = pos;
+		} else if (control == _vpot) {
+			_surface->write (_vpot->set (pos, true, Pot::spread));
+			queue_parameter_display (PanWidthAutomation, pos);
 		}
+
+		_last_pan_width_position_written = pos;
 	}
 }
 
@@ -532,7 +756,7 @@ Strip::select_event (Button&, ButtonState bs)
 			/* reset to default */
 			boost::shared_ptr<AutomationControl> ac = _fader->control ();
 			if (ac) {
-				ac->set_value (ac->normal());
+				ac->set_value (ac->normal(), Controllable::NoGroup);
 			}
 			return;
 		}
@@ -550,6 +774,28 @@ Strip::select_event (Button&, ButtonState bs)
 void
 Strip::vselect_event (Button&, ButtonState bs)
 {
+	if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
+
+		/* subview mode: vpot press acts like a button for toggle parameters */
+
+		if (bs != press) {
+			return;
+		}
+
+		boost::shared_ptr<AutomationControl> control = _vpot->control ();
+		if (!control) {
+			return;
+		}
+
+		if (control->toggled()) {
+			if (control->toggled()) {
+				control->set_value (!control->get_value(), Controllable::NoGroup);
+			}
+		}
+
+		return;
+	}
+
 	if (bs == press) {
 
 		int ms = _surface->mcp().main_modifier_state();
@@ -561,7 +807,7 @@ Strip::vselect_event (Button&, ButtonState bs)
 			if (ac) {
 
 				/* reset to default/normal value */
-				ac->set_value (ac->normal());
+				ac->set_value (ac->normal(), Controllable::NoGroup);
 			}
 
 		}  else {
@@ -584,7 +830,7 @@ Strip::fader_touch_event (Button&, ButtonState bs)
 
 		if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
 			if (ac) {
-				ac->set_value (ac->normal());
+				ac->set_value (ac->normal(), Controllable::NoGroup);
 			}
 		} else {
 
@@ -661,7 +907,7 @@ Strip::handle_button (Button& button, ButtonState bs)
 				/* apply change */
 
 				for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
-					(*c)->set_value (new_value);
+					(*c)->set_value (new_value, Controllable::NoGroup);
 				}
 
 			} else {
@@ -688,13 +934,13 @@ void
 Strip::do_parameter_display (AutomationType type, float val)
 {
 	bool screen_hold = false;
+	char buf[16];
 
 	switch (type) {
 	case GainAutomation:
 		if (val == 0.0) {
 			_surface->write (display (1, " -inf "));
 		} else {
-			char buf[16];
 			float dB = accurate_coefficient_to_dB (val);
 			snprintf (buf, sizeof (buf), "%6.1f", dB);
 			_surface->write (display (1, buf));
@@ -703,19 +949,24 @@ Strip::do_parameter_display (AutomationType type, float val)
 		break;
 
 	case PanAzimuthAutomation:
-		if (_route) {
-			boost::shared_ptr<Pannable> p = _route->pannable();
-			if (p && _route->panner()) {
-				string str =_route->panner()->value_as_string (p->pan_azimuth_control);
-				_surface->write (display (1, str));
-				screen_hold = true;
+		if (Profile->get_mixbus()) {
+			snprintf (buf, sizeof (buf), "%2.1f", val);
+			_surface->write (display (1, buf));
+			screen_hold = true;
+		} else {
+			if (_route) {
+				boost::shared_ptr<Pannable> p = _route->pannable();
+				if (p && _route->panner()) {
+					string str =_route->panner()->value_as_string (p->pan_azimuth_control);
+					_surface->write (display (1, str));
+					screen_hold = true;
+				}
 			}
 		}
 		break;
 
 	case PanWidthAutomation:
 		if (_route) {
-			char buf[16];
 			snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
 			_surface->write (display (1, buf));
 			screen_hold = true;
@@ -724,7 +975,6 @@ Strip::do_parameter_display (AutomationType type, float val)
 
 	case TrimAutomation:
 		if (_route) {
-			char buf[16];
 			float dB = accurate_coefficient_to_dB (val);
 			snprintf (buf, sizeof (buf), "%6.1f", dB);
 			_surface->write (display (1, buf));
@@ -732,6 +982,53 @@ Strip::do_parameter_display (AutomationType type, float val)
 		}
 		break;
 
+	case PhaseAutomation:
+		if (_route) {
+			if (_route->phase_control()->get_value() < 0.5) {
+				_surface->write (display (1, "Normal"));
+			} else {
+				_surface->write (display (1, "Invert"));
+			}
+			screen_hold = true;
+		}
+		break;
+
+	case SendAutomation:
+		if (val == 0.0) {
+			_surface->write (display (1, " -inf "));
+		} else {
+			float dB = accurate_coefficient_to_dB (val);
+			snprintf (buf, sizeof (buf), "%6.1f", dB);
+			_surface->write (display (1, buf));
+			screen_hold = true;
+		}
+		break;
+	case EQGain:
+	case EQFrequency:
+	case EQQ:
+	case EQShape:
+	case EQHPF:
+	case CompThreshold:
+	case CompSpeed:
+	case CompMakeup:
+	case CompRedux:
+		snprintf (buf, sizeof (buf), "%6.1f", val);
+		_surface->write (display (1, buf));
+		screen_hold = true;
+		break;
+	case EQEnable:
+	case CompEnable:
+		if (val >= 0.5) {
+			_surface->write (display (1, "on"));
+		} else {
+			_surface->write (display (1, "off"));
+		}
+		break;
+	case CompMode:
+		if (_surface->mcp().subview_route()) {
+			_surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
+		}
+		break;
 	default:
 		break;
 	}
@@ -755,6 +1052,10 @@ void
 Strip::handle_fader (Fader& fader, float position)
 {
 	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
+	boost::shared_ptr<AutomationControl> ac = fader.control();
+	if (!ac) {
+		return;
+	}
 
 	fader.set_value (position);
 
@@ -779,10 +1080,14 @@ Strip::handle_pot (Pot& pot, float delta)
 	*/
 
 	boost::shared_ptr<AutomationControl> ac = pot.control();
+	if (!ac) {
+		return;
+	}
 	double p = pot.get_value ();
 	p += delta;
-	p = max (ac->lower(), p);
-	p = min (ac->upper(), p);
+	// fader and pot should be the same and fader is hard coded 0 -> 1
+	p = max (0.0, p);
+	p = min (1.0, p);
 	pot.set_value (p);
 }
 
@@ -791,9 +1096,16 @@ Strip::periodic (ARDOUR::microseconds_t now)
 {
 	bool reshow_vpot_mode = false;
 	bool reshow_name = false;
+	bool good_strip = true;
 
 	if (!_route) {
-		return;
+		// view mode may cover as many as 3 strips
+		// needs to be cleared when there are less than 3 routes
+		if (_index > 2) {
+			return;
+		} else {
+			good_strip = false;
+		}
 	}
 
 	if (_block_screen_redisplay_until >= now) {
@@ -808,7 +1120,7 @@ Strip::periodic (ARDOUR::microseconds_t now)
 		/* timeout reached, reset */
 
 		_block_screen_redisplay_until = 0;
-		reshow_vpot_mode = true;
+		reshow_vpot_mode = (true && good_strip);
 		reshow_name = true;
 	}
 
@@ -819,7 +1131,7 @@ Strip::periodic (ARDOUR::microseconds_t now)
 		/* timeout reached, reset */
 
 		_block_vpot_mode_redisplay_until = 0;
-		reshow_vpot_mode = true;
+		reshow_vpot_mode = (true && good_strip);
 	}
 
 	if (reshow_name) {
@@ -828,14 +1140,16 @@ Strip::periodic (ARDOUR::microseconds_t now)
 
 	if (reshow_vpot_mode) {
 		return_to_vpot_mode_display ();
-	} else {
+	} else if (good_strip) {
 		/* no point doing this if we just switched back to vpot mode
 		   display */
 		update_automation ();
 	}
 
   meters:
-	update_meter ();
+	if (good_strip) {
+		update_meter ();
+	}
 }
 
 void
@@ -861,20 +1175,33 @@ Strip::redisplay (ARDOUR::microseconds_t now)
 void
 Strip::update_automation ()
 {
-	ARDOUR::AutoState gain_state = _route->gain_control()->automation_state();
+	if (!_route) {
+		return;
+	}
+
+	ARDOUR::AutoState state = _route->gain_control()->automation_state();
 
-	if (gain_state == Touch || gain_state == Play) {
+	if (state == Touch || state == Play) {
 		notify_gain_changed (false);
 	}
 
-	if (_route->panner()) {
-		ARDOUR::AutoState panner_state = _route->panner()->automation_state();
-		if (panner_state == Touch || panner_state == Play) {
+	boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
+	if (pan_control) {
+		state = pan_control->automation_state ();
+		if (state == Touch || state == Play) {
 			notify_panner_azi_changed (false);
+		}
+	}
+
+	pan_control = _route->pan_width_control ();
+	if (pan_control) {
+		state = pan_control->automation_state ();
+		if (state == Touch || state == Play) {
 			notify_panner_width_changed (false);
 		}
 	}
-	if (_route->trim()) {
+
+	if (_route->trim() && route()->trim()->active()) {
 		ARDOUR::AutoState trim_state = _route->trim_control()->automation_state();
 		if (trim_state == Touch || trim_state == Play) {
 			notify_trim_changed (false);
@@ -885,6 +1212,10 @@ Strip::update_automation ()
 void
 Strip::update_meter ()
 {
+	if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
+		return;
+	}
+
 	if (_meter && _transport_is_rolling && _metering_active) {
 		float dB = const_cast<PeakMeter&> (_route->peak_meter()).meter_level (0, MeterMCP);
 		_meter->send_update (*_surface, dB);
@@ -975,31 +1306,41 @@ Strip::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& rl)
 }
 
 string
-Strip::vpot_mode_string () const
+Strip::vpot_mode_string ()
 {
 	boost::shared_ptr<AutomationControl> ac = _vpot->control();
-
 	if (!ac) {
 		return string();
 	}
 
-	switch (ac->parameter().type()) {
-	case GainAutomation:
+	if (control_by_parameter.find (GainAutomation)->second == _vpot) {
 		return "Fader";
-	case TrimAutomation:
+	} else if (control_by_parameter.find (TrimAutomation)->second == _vpot) {
 		return "Trim";
-	case PanAzimuthAutomation:
+	} else if (control_by_parameter.find (PhaseAutomation)->second == _vpot) {
+		return string_compose ("Phase%1", _route->phase_control()->channel() + 1);
+	} else if (control_by_parameter.find (SendAutomation)->second == _vpot) {
+		// should be bus name
+		boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
+		if (p) {
+			return p->name();
+		}
+	} else if (control_by_parameter.find (PanAzimuthAutomation)->second == _vpot) {
 		return "Pan";
-	case PanWidthAutomation:
+	} else if (control_by_parameter.find (PanWidthAutomation)->second == _vpot) {
 		return "Width";
-	case PanElevationAutomation:
+	} else if (control_by_parameter.find (PanElevationAutomation)->second == _vpot) {
 		return "Elev";
-	case PanFrontBackAutomation:
+	} else if (control_by_parameter.find (PanFrontBackAutomation)->second == _vpot) {
 		return "F/Rear";
-	case PanLFEAutomation:
+	} else if (control_by_parameter.find (PanLFEAutomation)->second == _vpot) {
 		return "LFE";
 	}
 
+	if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
+		return string();
+	}
+
 	return "???";
 }
 
@@ -1010,29 +1351,22 @@ Strip::potmode_changed (bool notify)
 		return;
 	}
 
-	if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
-		/* do not change vpot mode while in flipped mode */
-		DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
-		_surface->write (display (1, "Flip"));
-		block_vpot_mode_display_for (1000);
-		return;
-	}
-
 	// WIP
 	int pm = _surface->mcp().pot_mode();
 	switch (pm) {
 	case MackieControlProtocol::Pan:
 		// This needs to set current pan mode (azimuth or width... or whatever)
-		set_vpot_parameter (_pan_mode);
 		DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Assign pot to Pan mode %1\n", enum_2_string (_pan_mode)));
+		set_vpot_parameter (_pan_mode);
 		break;
 	case MackieControlProtocol::Trim:
 		DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Trim mode.\n");
-		set_vpot_parameter (TrimAutomation);
+		set_vpot_parameter (_trim_mode);
 		break;
 	case MackieControlProtocol::Send:
+		// _current_send has the number of the send we will show
 		DEBUG_TRACE (DEBUG::MackieControl, "Assign pot to Send mode.\n");
-		// set to current send
+		set_vpot_parameter (SendAutomation);
 		break;
 	}
 
@@ -1042,31 +1376,6 @@ Strip::potmode_changed (bool notify)
 }
 
 void
-Strip::flip_mode_changed (bool notify)
-{
-	if (!_route) {
-		return;
-	}
-
-	reset_saved_values ();
-
-	boost::shared_ptr<AutomationControl> fader_controllable = _fader->control ();
-	boost::shared_ptr<AutomationControl> vpot_controllable = _vpot->control ();
-
-	_fader->set_control (vpot_controllable);
-	_vpot->set_control (fader_controllable);
-
-	control_by_parameter[fader_controllable->parameter()] = _vpot;
-	control_by_parameter[vpot_controllable->parameter()] = _fader;
-
-	_surface->write (display (1, vpot_mode_string ()));
-
-	if (notify) {
-		notify_all ();
-	}
-}
-
-void
 Strip::block_screen_display_for (uint32_t msecs)
 {
 	_block_screen_redisplay_until = ARDOUR::get_microseconds() + (msecs * 1000);
@@ -1085,7 +1394,10 @@ Strip::return_to_vpot_mode_display ()
 	   back the mode where it shows what the VPot controls.
 	*/
 
-	if (_route) {
+	if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
+		/* do nothing - second line shows value of current subview parameter */
+		return;
+	} else if (_route) {
 		_surface->write (display (1, vpot_mode_string()));
 	} else {
 		_surface->write (blank_display (1));
@@ -1095,7 +1407,7 @@ Strip::return_to_vpot_mode_display ()
 void
 Strip::next_pot_mode ()
 {
-	vector<Evoral::Parameter>::iterator i;
+	vector<AutomationType>::iterator i;
 
 	if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
 		/* do not change vpot mode while in flipped mode */
@@ -1111,13 +1423,16 @@ Strip::next_pot_mode ()
 	if (!ac) {
 		return;
 	}
+
+
 	if (_surface->mcp().pot_mode() == MackieControlProtocol::Pan) {
-		if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter())) {
+
+		if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter().type())) {
 			return;
 		}
 
 		for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
-			if ((*i) == ac->parameter()) {
+			if ((*i) == ac->parameter().type()) {
 				break;
 			}
 		}
@@ -1133,14 +1448,315 @@ Strip::next_pot_mode ()
 		if (i == possible_pot_parameters.end()) {
 			i = possible_pot_parameters.begin();
 		}
+
 		set_vpot_parameter (*i);
+	} else if (_surface->mcp().pot_mode() == MackieControlProtocol::Trim) {
+		if (possible_trim_parameters.empty() || (possible_trim_parameters.size() == 1 && possible_trim_parameters.front() == ac->parameter().type())) {
+			return;
+		}
+
+		for (i = possible_trim_parameters.begin(); i != possible_trim_parameters.end(); ++i) {
+			if ((*i) == ac->parameter().type()) {
+				break;
+			}
+		}
+		if ((*i) == PhaseAutomation && _route->phase_invert().size() > 1) {
+			// There are more than one channel of phase
+			if ((_route->phase_control()->channel() + 1) < _route->phase_invert().size()) {
+				_route->phase_control()->set_channel(_route->phase_control()->channel() + 1);
+				set_vpot_parameter (*i);
+				return;
+			} else {
+				_route->phase_control()->set_channel(0);
+			}
+		}
+		/* move to the next mode in the list, or back to the start (which will
+		also happen if the current mode is not in the current pot mode list)
+		*/
+
+		if (i != possible_trim_parameters.end()) {
+			++i;
+		}
+
+		if (i == possible_trim_parameters.end()) {
+			i = possible_trim_parameters.begin();
+		}
+		set_vpot_parameter (*i);
+	} else if (_surface->mcp().pot_mode() == MackieControlProtocol::Send) {
+		boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
+		if (!p) {
+			return;
+		}
+		p = _route->nth_send (_current_send + 1);
+		if (p && p->name() != "Monitor 1") {
+			_current_send++;
+		} else {
+			_current_send = 0;
+		}
+		set_vpot_parameter (SendAutomation);
 	}
 }
 
 void
-Strip::set_vpot_parameter (Evoral::Parameter p)
+Strip::subview_mode_changed ()
 {
-	boost::shared_ptr<Pannable> pannable;
+	boost::shared_ptr<Route> r = _surface->mcp().subview_route();
+
+	subview_connections.drop_connections ();
+
+	switch (_surface->mcp().subview_mode()) {
+	case MackieControlProtocol::None:
+		set_vpot_parameter (vpot_parameter);
+		notify_metering_state_changed ();
+		eq_band = -1;
+		break;
+
+	case MackieControlProtocol::EQ:
+		if (r) {
+			setup_eq_vpot (r);
+		} else {
+			/* leave it as it was */
+		}
+		break;
+
+	case MackieControlProtocol::Dynamics:
+		if (r) {
+			setup_dyn_vpot (r);
+		} else {
+			/* leave it as it was */
+		}
+		break;
+	}
+}
+
+void
+Strip::setup_dyn_vpot (boost::shared_ptr<Route> r)
+{
+	if (!r) {
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> tc = r->comp_threshold_controllable ();
+	boost::shared_ptr<AutomationControl> sc = r->comp_speed_controllable ();
+	boost::shared_ptr<AutomationControl> mc = r->comp_mode_controllable ();
+	boost::shared_ptr<AutomationControl> kc = r->comp_makeup_controllable ();
+	boost::shared_ptr<AutomationControl> rc = r->comp_redux_controllable ();
+	boost::shared_ptr<AutomationControl> ec = r->comp_enable_controllable ();
+
+	uint32_t pos = _surface->mcp().global_index (*this);
+
+	/* we will control the pos-th available parameter, from the list in the
+	 * order shown above.
+	 */
+
+	vector<boost::shared_ptr<AutomationControl> > available;
+	vector<AutomationType> params;
+
+	if (tc) { available.push_back (tc); params.push_back (CompThreshold); }
+	if (sc) { available.push_back (sc); params.push_back (CompSpeed); }
+	if (mc) { available.push_back (mc); params.push_back (CompMode); }
+	if (kc) { available.push_back (kc); params.push_back (CompMakeup); }
+	if (rc) { available.push_back (rc); params.push_back (CompRedux); }
+	if (ec) { available.push_back (ec); params.push_back (CompEnable); }
+
+	if (pos >= available.size()) {
+		/* this knob is not needed to control the available parameters */
+		_vpot->set_control (boost::shared_ptr<AutomationControl>());
+		_surface->write (display (0, string()));
+		_surface->write (display (1, string()));
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> pc;
+	AutomationType param;
+
+	pc = available[pos];
+	param = params[pos];
+
+	pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_dyn_change, this, param, false, true), ui_context());
+	_vpot->set_control (pc);
+
+	string pot_id;
+
+	switch (param) {
+	case CompThreshold:
+		pot_id = "Thresh";
+		break;
+	case CompSpeed:
+		if (mc) {
+			pot_id = r->comp_speed_name (mc->get_value());
+		} else {
+			pot_id = "Speed";
+		}
+		break;
+	case CompMode:
+		pot_id = "Mode";
+		break;
+	case CompMakeup:
+		pot_id = "Makeup";
+		break;
+	case CompRedux:
+		pot_id = "Redux";
+		break;
+	case CompEnable:
+		pot_id = "on/off";
+		break;
+	default:
+		break;
+	}
+
+	if (!pot_id.empty()) {
+		_surface->write (display (0, pot_id));
+	}
+
+	notify_dyn_change (param, true, false);
+}
+
+void
+Strip::setup_eq_vpot (boost::shared_ptr<Route> r)
+{
+	uint32_t bands = r->eq_band_cnt ();
+
+	if (bands == 0) {
+		/* should never get here */
+		return;
+	}
+
+	/* figure out how many params per band are available */
+
+	boost::shared_ptr<AutomationControl> pc;
+	uint32_t params_per_band = 0;
+
+	if ((pc = r->eq_gain_controllable (0))) {
+		params_per_band += 1;
+	}
+	if ((pc = r->eq_freq_controllable (0))) {
+		params_per_band += 1;
+	}
+	if ((pc = r->eq_q_controllable (0))) {
+		params_per_band += 1;
+	}
+	if ((pc = r->eq_shape_controllable (0))) {
+		params_per_band += 1;
+	}
+
+	/* pick the one for this strip, based on its global position across
+	 * all surfaces
+	 */
+
+	pc.reset ();
+
+	const uint32_t total_band_parameters = bands * params_per_band;
+	const uint32_t global_pos = _surface->mcp().global_index (*this);
+	AutomationType param = NullAutomation;
+	string band_name;
+
+	eq_band = -1;
+
+	if (global_pos < total_band_parameters) {
+
+		/* show a parameter for an EQ band */
+
+		const uint32_t parameter = global_pos % params_per_band;
+		eq_band = global_pos / params_per_band;
+		band_name = r->eq_band_name (eq_band);
+
+		switch (parameter) {
+		case 0:
+			pc = r->eq_gain_controllable (eq_band);
+			param = EQGain;
+			break;
+		case 1:
+			pc = r->eq_freq_controllable (eq_band);
+			param = EQFrequency;
+			break;
+		case 2:
+			pc = r->eq_q_controllable (eq_band);
+			param = EQQ;
+			break;
+		case 3:
+			pc = r->eq_shape_controllable (eq_band);
+			param = EQShape;
+			break;
+		}
+
+	} else {
+
+		/* show a non-band parameter (HPF or enable)
+		 */
+
+		uint32_t parameter = global_pos - total_band_parameters;
+
+		switch (parameter) {
+		case 0: /* first control after band parameters */
+			pc = r->eq_hpf_controllable();
+			param = EQHPF;
+			break;
+		case 1: /* second control after band parameters */
+			pc = r->eq_enable_controllable();
+			param = EQEnable;
+			break;
+		default:
+			/* nothing to control */
+			_vpot->set_control (boost::shared_ptr<AutomationControl>());
+			_surface->write (display (0, string()));
+			_surface->write (display (1, string()));
+			/* done */
+			return;
+			break;
+		}
+
+	}
+
+	if (pc) {
+		pc->Changed.connect (subview_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_eq_change, this, param, eq_band, false), ui_context());
+		_vpot->set_control (pc);
+
+		string pot_id;
+
+		switch (param) {
+		case EQGain:
+			pot_id = band_name + "Gain";
+			break;
+		case EQFrequency:
+			pot_id = band_name + "Freq";
+			break;
+		case EQQ:
+			pot_id = band_name + " Q";
+			break;
+		case EQShape:
+			pot_id = band_name + " Shp";
+			break;
+		case EQHPF:
+			pot_id = "HPFreq";
+			break;
+		case EQEnable:
+			pot_id = "on/off";
+			break;
+		default:
+			break;
+		}
+
+		if (!pot_id.empty()) {
+			_surface->write (display (0, pot_id));
+		}
+
+		notify_eq_change (param, eq_band, true);
+	}
+}
+
+void
+Strip::set_vpot_parameter (AutomationType p)
+{
+	if (!_route || (p == NullAutomation)) {
+		control_by_parameter[vpot_parameter] = 0;
+		vpot_parameter = NullAutomation;
+		_vpot->set_control (boost::shared_ptr<AutomationControl>());
+		_surface->write (display (1, string()));
+		return;
+	}
+
+	boost::shared_ptr<AutomationControl> pan_control;
 
 	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
 
@@ -1155,17 +1771,17 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
 		}
 	}
 
-	switch (p.type()) {
+	switch (p) {
 	case PanAzimuthAutomation:
-		_pan_mode = PanAzimuthAutomation;
-		pannable = _route->pannable ();
-		if (pannable) {
+		if ((pan_control = _route->pan_azimuth_control ())) {
 			if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
-				/* gain to vpot, pan azi to fader */
-				_vpot->set_control (_route->gain_control());
-				control_by_parameter[GainAutomation] = _vpot;
-				if (pannable) {
-					_fader->set_control (pannable->pan_azimuth_control);
+				_pan_mode = PanAzimuthAutomation;
+				if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+					/* gain to vpot, pan azi to fader */
+					_vpot->set_control (_route->gain_control());
+					vpot_parameter = GainAutomation;
+					control_by_parameter[GainAutomation] = _vpot;
+					_fader->set_control (pan_control);
 					control_by_parameter[PanAzimuthAutomation] = _fader;
 				} else {
 					_fader->set_control (boost::shared_ptr<AutomationControl>());
@@ -1173,28 +1789,28 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
 				}
 			} else {
 				/* gain to fader, pan azi to vpot */
+				vpot_parameter = PanAzimuthAutomation;
 				_fader->set_control (_route->gain_control());
 				control_by_parameter[GainAutomation] = _fader;
-				if (pannable) {
-					_vpot->set_control (pannable->pan_azimuth_control);
-					control_by_parameter[PanAzimuthAutomation] = _vpot;
-				} else {
-					_vpot->set_control (boost::shared_ptr<AutomationControl>());
-					control_by_parameter[PanAzimuthAutomation] = 0;
-				}
+				_vpot->set_control (pan_control);
+				control_by_parameter[PanAzimuthAutomation] = _vpot;
 			}
+		} else {
+			_vpot->set_control (boost::shared_ptr<AutomationControl>());
+			control_by_parameter[PanAzimuthAutomation] = 0;
 		}
 		break;
+
 	case PanWidthAutomation:
-		_pan_mode = PanWidthAutomation;
-		pannable = _route->pannable ();
-		if (pannable) {
+		if ((pan_control = _route->pan_width_control ())) {
 			if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
-				/* gain to vpot, pan width to fader */
-				_vpot->set_control (_route->gain_control());
-				control_by_parameter[GainAutomation] = _vpot;
-				if (pannable) {
-					_fader->set_control (pannable->pan_width_control);
+				_pan_mode = PanWidthAutomation;
+				if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+					/* gain to vpot, pan width to fader */
+					_vpot->set_control (_route->gain_control());
+					vpot_parameter = GainAutomation;
+					control_by_parameter[GainAutomation] = _vpot;
+					_fader->set_control (pan_control);
 					control_by_parameter[PanWidthAutomation] = _fader;
 				} else {
 					_fader->set_control (boost::shared_ptr<AutomationControl>());
@@ -1202,18 +1818,18 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
 				}
 			} else {
 				/* gain to fader, pan width to vpot */
+				vpot_parameter = PanWidthAutomation;
 				_fader->set_control (_route->gain_control());
 				control_by_parameter[GainAutomation] = _fader;
-				if (pannable) {
-					_vpot->set_control (pannable->pan_width_control);
-					control_by_parameter[PanWidthAutomation] = _vpot;
-				} else {
-					_vpot->set_control (boost::shared_ptr<AutomationControl>());
-					control_by_parameter[PanWidthAutomation] = 0;
-				}
+				_vpot->set_control (pan_control);
+				control_by_parameter[PanWidthAutomation] = _vpot;
 			}
+		} else {
+			_vpot->set_control (boost::shared_ptr<AutomationControl>());
+			control_by_parameter[PanWidthAutomation] = 0;
 		}
 		break;
+
 	case PanElevationAutomation:
 		break;
 	case PanFrontBackAutomation:
@@ -1221,23 +1837,111 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
 	case PanLFEAutomation:
 		break;
 	case TrimAutomation:
-		if (_route->trim()) {
-			if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
-				/* gain to vpot, trim to fader */
-				_vpot->set_control (_route->gain_control());
-				control_by_parameter[GainAutomation] = _vpot;
+		_trim_mode = TrimAutomation;
+		vpot_parameter = TrimAutomation;
+		if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+			/* gain to vpot, trim to fader */
+			_vpot->set_control (_route->gain_control());
+			control_by_parameter[GainAutomation] = _vpot;
+			if (_route->trim() && route()->trim()->active()) {
 				_fader->set_control (_route->trim_control());
 				control_by_parameter[TrimAutomation] = _fader;
 			} else {
-				/* gain to fader, trim to vpot */
-				_fader->set_control (_route->gain_control());
-				control_by_parameter[GainAutomation] = _fader;
+				_fader->set_control (boost::shared_ptr<AutomationControl>());
+				control_by_parameter[TrimAutomation] = 0;
+			}
+		} else {
+			/* gain to fader, trim to vpot */
+			_fader->set_control (_route->gain_control());
+			control_by_parameter[GainAutomation] = _fader;
+			if (_route->trim() && route()->trim()->active()) {
 				_vpot->set_control (_route->trim_control());
 				control_by_parameter[TrimAutomation] = _vpot;
+			} else {
+				_vpot->set_control (boost::shared_ptr<AutomationControl>());
+				control_by_parameter[TrimAutomation] = 0;
+			}
+		}
+		break;
+	case PhaseAutomation:
+		_trim_mode = PhaseAutomation;
+		vpot_parameter = PhaseAutomation;
+		if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+			/* gain to vpot, phase to fader */
+			_vpot->set_control (_route->gain_control());
+			control_by_parameter[GainAutomation] = _vpot;
+			if (_route->phase_invert().size()) {
+				_fader->set_control (_route->phase_control());
+				control_by_parameter[PhaseAutomation] = _fader;
+			} else {
+				_fader->set_control (boost::shared_ptr<AutomationControl>());
+				control_by_parameter[PhaseAutomation] = 0;
 			}
 		} else {
-			_vpot->set_control (boost::shared_ptr<AutomationControl>());
-			control_by_parameter[TrimAutomation] = 0;
+			/* gain to fader, phase to vpot */
+			_fader->set_control (_route->gain_control());
+			control_by_parameter[GainAutomation] = _fader;
+			if (_route->phase_invert().size()) {
+				_vpot->set_control (_route->phase_control());
+				control_by_parameter[PhaseAutomation] = _vpot;
+			} else {
+				_vpot->set_control (boost::shared_ptr<AutomationControl>());
+				control_by_parameter[PhaseAutomation] = 0;
+			}
+		}
+		break;
+	case SendAutomation:
+		if (!Profile->get_mixbus()) {
+			if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+				// gain to vpot, send to fader
+				_vpot->set_control (_route->gain_control());
+				control_by_parameter[GainAutomation] = _vpot;
+				// test for send to control
+				boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
+				if (p && p->name() != "Monitor 1") {
+					boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
+					boost::shared_ptr<Amp> a = s->amp();
+					_fader->set_control (a->gain_control());
+					// connect to signal
+					send_connections.drop_connections ();
+					a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
+					control_by_parameter[SendAutomation] = _fader;
+				} else {
+					_fader->set_control (boost::shared_ptr<AutomationControl>());
+					control_by_parameter[SendAutomation] = 0;
+				}
+			} else {
+				// gain to fader, send to vpot
+				_fader->set_control (_route->gain_control());
+				control_by_parameter[GainAutomation] = _fader;
+				boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
+				if (p && p->name() != "Monitor 1") {
+					boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
+					boost::shared_ptr<Amp> a = s->amp();
+					_vpot->set_control (a->gain_control());
+					// connect to signal
+					send_connections.drop_connections ();
+					a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
+					control_by_parameter[SendAutomation] = _vpot;
+				} else {
+					// gain to fader, send to vpot
+					_fader->set_control (_route->gain_control());
+					control_by_parameter[GainAutomation] = _fader;
+					boost::shared_ptr<Processor> p = _route->nth_send (_current_send);
+					if (p && p->name() != "Monitor 1") {
+						boost::shared_ptr<Send> s =  boost::dynamic_pointer_cast<Send>(p);
+						boost::shared_ptr<Amp> a = s->amp();
+						_vpot->set_control (a->gain_control());
+						// connect to signal
+						send_connections.drop_connections ();
+						a->gain_control()->Changed.connect(send_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_processor_changed, this, false), ui_context());
+						control_by_parameter[SendAutomation] = _vpot;
+					} else {
+						_vpot->set_control (boost::shared_ptr<AutomationControl>());
+						control_by_parameter[SendAutomation] = 0;
+					}
+				}
+			}
 		}
 		break;
 	default:
@@ -1249,6 +1953,12 @@ Strip::set_vpot_parameter (Evoral::Parameter p)
 	_surface->write (display (1, vpot_mode_string()));
 }
 
+bool
+Strip::is_midi_track () const
+{
+	return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
+}
+
 void
 Strip::reset_saved_values ()
 {
@@ -1262,6 +1972,10 @@ Strip::reset_saved_values ()
 void
 Strip::notify_metering_state_changed()
 {
+	if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
+		return;
+	}
+
 	if (!_route || !_meter) {
 		return;
 	}
diff --git a/libs/surfaces/mackie/strip.h b/libs/surfaces/mackie/strip.h
index 29920b8..e84a0eb 100644
--- a/libs/surfaces/mackie/strip.h
+++ b/libs/surfaces/mackie/strip.h
@@ -15,6 +15,7 @@
 
 #include "control_group.h"
 #include "types.h"
+#include "mackie_control_protocol.h"
 #include "midi_byte_array.h"
 #include "device_info.h"
 
@@ -56,11 +57,12 @@ public:
 
 	void add (Control & control);
 	int index() const { return _index; } // zero based
+	Surface* surface() const { return _surface; }
 
 	void set_route (boost::shared_ptr<ARDOUR::Route>, bool with_messages = true);
 
 	// call all signal handlers manually
-	void notify_all();
+	void notify_all ();
 
 	void handle_button (Button&, ButtonState bs);
 	void handle_fader (Fader&, float position);
@@ -75,8 +77,8 @@ public:
 
 	void zero ();
 
-	void flip_mode_changed (bool notify=false);
 	void potmode_changed (bool notify=false);
+	void subview_mode_changed ();
 
 	void lock_controls ();
 	void unlock_controls ();
@@ -108,13 +110,19 @@ private:
 	uint64_t _block_screen_redisplay_until;
 	boost::shared_ptr<ARDOUR::Route> _route;
 	PBD::ScopedConnectionList route_connections;
+	PBD::ScopedConnectionList subview_connections;
+	PBD::ScopedConnectionList send_connections;
+	int       eq_band;
 
 	ARDOUR::AutomationType  _pan_mode;
+	ARDOUR::AutomationType  _trim_mode;
+	ARDOUR::AutomationType  vpot_parameter;
 
 	float _last_gain_position_written;
 	float _last_pan_azi_position_written;
 	float _last_pan_width_position_written;
 	float _last_trim_position_written;
+	uint32_t _current_send;
 
 	void notify_solo_changed ();
 	void notify_mute_changed ();
@@ -126,11 +134,13 @@ private:
 	void notify_active_changed ();
 	void notify_route_deleted ();
 	void notify_trim_changed (bool force_update = true);
-
+	void notify_phase_changed (bool force_update = true);
+	void notify_processor_changed (bool force_update = true);
 	void update_automation ();
 	void update_meter ();
+	std::string vpot_mode_string ();
 
-	std::string vpot_mode_string () const;
+	boost::shared_ptr<ARDOUR::AutomationControl> mb_pan_controllable;
 
 	void return_to_vpot_mode_display ();
 
@@ -148,15 +158,24 @@ private:
 	void vselect_event (Button&, ButtonState);
 	void fader_touch_event (Button&, ButtonState);
 
-	std::vector<Evoral::Parameter> possible_pot_parameters;
+	std::vector<ARDOUR::AutomationType> possible_pot_parameters;
+	std::vector<ARDOUR::AutomationType> possible_trim_parameters;
 	void next_pot_mode ();
-	void set_vpot_parameter (Evoral::Parameter);
+	void set_vpot_parameter (ARDOUR::AutomationType);
 	void show_route_name ();
 
 	void reset_saved_values ();
 
-	typedef std::map<Evoral::Parameter,Control*> ControlParameterMap;
+	bool is_midi_track () const;
+
+	typedef std::map<ARDOUR::AutomationType,Control*> ControlParameterMap;
 	ControlParameterMap control_by_parameter;
+
+	void notify_eq_change (ARDOUR::AutomationType, uint32_t band, bool force);
+	void setup_eq_vpot (boost::shared_ptr<ARDOUR::Route>);
+
+	void notify_dyn_change (ARDOUR::AutomationType, bool force, bool propagate_mode_change);
+	void setup_dyn_vpot (boost::shared_ptr<ARDOUR::Route>);
 };
 
 }
diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc
index 9dc0421..7aa047f 100644
--- a/libs/surfaces/mackie/surface.cc
+++ b/libs/surfaces/mackie/surface.cc
@@ -25,6 +25,8 @@
 
 #include <glibmm/convert.h>
 
+#include "pbd/stacktrace.h"
+
 #include "midi++/port.h"
 
 #include "ardour/audioengine.h"
@@ -33,6 +35,7 @@
 #include "ardour/route.h"
 #include "ardour/panner.h"
 #include "ardour/panner_shell.h"
+#include "ardour/profile.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/session.h"
 #include "ardour/utils.h"
@@ -64,7 +67,7 @@ using namespace std;
 using namespace PBD;
 using ARDOUR::Route;
 using ARDOUR::Panner;
-using ARDOUR::Pannable;
+using ARDOUR::Profile;
 using ARDOUR::AutomationControl;
 using namespace ArdourSurface;
 using namespace Mackie;
@@ -364,6 +367,12 @@ Surface::init_strips (uint32_t n)
 }
 
 void
+Surface::master_monitor_may_have_changed ()
+{
+	setup_master ();
+}
+
+void
 Surface::setup_master ()
 {
 	boost::shared_ptr<Route> m;
@@ -373,28 +382,37 @@ Surface::setup_master ()
 	}
 
 	if (!m) {
+		_master_fader->set_control (boost::shared_ptr<AutomationControl>());
+		master_connection.disconnect ();
 		return;
 	}
 
-	_master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *groups["master"]));
+	if (!_master_fader) {
+		_master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *groups["master"]));
+
+		Groups::iterator group_it;
+		group_it = groups.find("master");
+
+		DeviceInfo device_info = _mcp.device_info();
+		GlobalButtonInfo master_button = device_info.get_global_button(Button::MasterFaderTouch);
+		Button* bb = dynamic_cast<Button*> (Button::factory (
+			                                    *this,
+			                                    Button::MasterFaderTouch,
+			                                    master_button.id,
+			                                    master_button.label,
+			                                    *(group_it->second)
+			                                    ));
+
+		DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 Master Fader new button BID %2 id %3\n",
+		                                                   number(), Button::MasterFaderTouch, bb->id()));
+	} else {
+		master_connection.disconnect ();
+	}
 
 	_master_fader->set_control (m->gain_control());
-	m->gain_control()->Changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
-
-	Groups::iterator group_it;
-	group_it = groups.find("master");
-
-	DeviceInfo device_info = _mcp.device_info();
-	GlobalButtonInfo master_button = device_info.get_global_button(Button::MasterFaderTouch);
-	Button* bb = dynamic_cast<Button*> (Button::factory (
-		*this,
-		Button::MasterFaderTouch,
-		master_button.id,
-		master_button.label,
-		*(group_it->second)
-));
-	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 Master Fader new button BID %2 id %3\n",
-		number(), Button::MasterFaderTouch, bb->id()));
+	m->gain_control()->Changed.connect (master_connection, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
+	_last_master_gain_written = FLT_MAX; /* some essentially impossible value */
+	master_gain_changed ();
 }
 
 void
@@ -925,8 +943,6 @@ Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes)
 	for (; s != strips.end(); ++s) {
 		(*s)->set_route (boost::shared_ptr<Route>());
 	}
-
-
 }
 
 static char
@@ -1009,11 +1025,11 @@ void
 Surface::update_flip_mode_display ()
 {
 	for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
-		(*s)->flip_mode_changed (true);
+		(*s)->potmode_changed (true);
 	}
 }
 
- void
+void
 Surface::update_potmode ()
 {
 	for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
@@ -1022,6 +1038,18 @@ Surface::update_potmode ()
 }
 
 void
+Surface::subview_mode_changed ()
+{
+	for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
+		(*s)->subview_mode_changed ();
+	}
+
+	if (_mcp.subview_mode() == MackieControlProtocol::None) {
+		update_view_mode_display ();
+	}
+}
+
+void
 Surface::update_view_mode_display ()
 {
 	string text;
@@ -1034,7 +1062,7 @@ Surface::update_view_mode_display ()
 	switch (_mcp.view_mode()) {
 	case MackieControlProtocol::Mixer:
 		show_two_char_display ("Mx");
-		id = Button::Track;
+		id = Button::View;
 		text = _("Mixer View");
 		break;
 	case MackieControlProtocol::AudioTracks:
@@ -1055,24 +1083,34 @@ Surface::update_view_mode_display ()
 	case MackieControlProtocol::Busses:
 		show_two_char_display ("BS");
 		id = Button::Busses;
-		text = _("Busses");
+		if (Profile->get_mixbus()) {
+			text = _("Mixbusses");
+		} else {
+			text = _("Busses");
+		}
 		break;
 	case MackieControlProtocol::Auxes:
-		show_two_char_display ("AB");
+		show_two_char_display ("Au");
 		id = Button::Aux;
 		text = _("Auxes");
 		break;
+	case MackieControlProtocol::Selected:
+		show_two_char_display ("SE");
+		id = Button::User;
+		text = _("Selected Routes");
+		break;
 	default:
 		break;
 	}
 
 	vector<int> view_mode_buttons;
-	view_mode_buttons.push_back (Button::Track);
+	view_mode_buttons.push_back (Button::View);
 	view_mode_buttons.push_back (Button::Busses);
 	view_mode_buttons.push_back (Button::Plugin);
 	view_mode_buttons.push_back (Button::AudioTracks);
 	view_mode_buttons.push_back (Button::MidiTracks);
 	view_mode_buttons.push_back (Button::Aux);
+	view_mode_buttons.push_back (Button::User);
 
 	if (id >= 0) {
 
diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h
index 166b8ed..5246cf9 100644
--- a/libs/surfaces/mackie/surface.h
+++ b/libs/surfaces/mackie/surface.h
@@ -156,6 +156,7 @@ public:
 	void update_potmode ();
 
 	void gui_selection_changed (const ARDOUR::StrongRouteNotificationList&);
+	void subview_mode_changed ();
 
 	MackieControlProtocol& mcp() const { return _mcp; }
 
@@ -169,6 +170,8 @@ public:
 
 	bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool);
 
+	void master_monitor_may_have_changed ();
+
 	XMLNode& get_state ();
 	int set_state (const XMLNode&, int version);
 
@@ -183,6 +186,7 @@ public:
 	Mackie::JogWheel*      _jog_wheel;
 	Fader*                 _master_fader;
 	float                  _last_master_gain_written;
+	PBD::ScopedConnection   master_connection;
 
 	void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
 	MidiByteArray host_connection_query (MidiByteArray& bytes);
diff --git a/libs/surfaces/osc/interface.cc b/libs/surfaces/osc/interface.cc
index d26a317..35b3139 100644
--- a/libs/surfaces/osc/interface.cc
+++ b/libs/surfaces/osc/interface.cc
@@ -46,6 +46,12 @@ probe_osc_protocol (ControlProtocolDescriptor* /*descriptor*/)
 	return true; // we can always do OSC
 }
 
+static void*
+osc_request_buffer_factory (uint32_t num_requests)
+{
+	return OSC::request_factory (num_requests);
+}
+
 static ControlProtocolDescriptor osc_descriptor = {
 	/*name :              */   "Open Sound Control (OSC)",
 	/*id :                */   "uri://ardour.org/surfaces/osc:0",
@@ -55,7 +61,8 @@ static ControlProtocolDescriptor osc_descriptor = {
 	/*supports_feedback : */   true,
 	/*probe :             */   probe_osc_protocol,
 	/*initialize :        */   new_osc_protocol,
-	/*destroy :           */   delete_osc_protocol
+	/*destroy :           */   delete_osc_protocol,
+	/*request_buffer_factory */ osc_request_buffer_factory
 };
 
 extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &osc_descriptor; }
diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc
index 6a771d9..8ce7969 100644
--- a/libs/surfaces/osc/osc.cc
+++ b/libs/surfaces/osc/osc.cc
@@ -73,7 +73,7 @@ static void error_callback(int, const char *, const char *)
 
 OSC::OSC (Session& s, uint32_t port)
 	: ControlProtocol (s, X_("Open Sound Control (OSC)"))
-	, AbstractUI<OSCUIRequest> ("osc")
+	, AbstractUI<OSCUIRequest> (name())
 	, local_server (0)
 	, remote_server (0)
 	, _port(port)
@@ -96,6 +96,17 @@ OSC::~OSC()
 	_instance = 0;
 }
 
+void*
+OSC::request_factory (uint32_t num_requests)
+{
+	/* AbstractUI<T>::request_buffer_factory() is a template method only
+	   instantiated in this source module. To provide something visible for
+	   use in the interface/descriptor, we have this static method that is
+	   template-free.
+	*/
+	return request_buffer_factory (num_requests);
+}
+
 void
 OSC::do_request (OSCUIRequest* req)
 {
@@ -226,7 +237,7 @@ OSC::start ()
 void
 OSC::thread_init ()
 {
-	pthread_set_name (X_("OSC"));
+	pthread_set_name (event_loop_name().c_str());
 
 	if (_osc_unix_server) {
 		Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
@@ -244,8 +255,8 @@ OSC::thread_init ()
 		g_source_ref (remote_server);
 	}
 
-	PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("OSC"), 2048);
-	SessionEvent::create_per_thread_pool (X_("OSC"), 128);
+	PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
+	SessionEvent::create_per_thread_pool (event_loop_name(), 128);
 }
 
 int
@@ -336,6 +347,8 @@ OSC::register_callbacks()
 		REGISTER_CALLBACK (serv, "/ardour/transport_stop", "", transport_stop);
 		REGISTER_CALLBACK (serv, "/ardour/transport_play", "", transport_play);
 		REGISTER_CALLBACK (serv, "/ardour/transport_frame", "", transport_frame);
+		REGISTER_CALLBACK (serv, "/ardour/transport_speed", "", transport_speed);
+		REGISTER_CALLBACK (serv, "/ardour/record_enabled", "", record_enabled);
 		REGISTER_CALLBACK (serv, "/ardour/set_transport_speed", "f", set_transport_speed);
 		REGISTER_CALLBACK (serv, "/ardour/locate", "ii", locate);
 		REGISTER_CALLBACK (serv, "/ardour/save_state", "", save_state);
@@ -348,6 +361,34 @@ OSC::register_callbacks()
 		REGISTER_CALLBACK (serv, "/ardour/rec_enable_toggle", "", rec_enable_toggle);
 		REGISTER_CALLBACK (serv, "/ardour/toggle_all_rec_enables", "", toggle_all_rec_enables);
 
+		/*
+		 * NOTE: these messages are provided for (arguably broken) apps
+		 *   that MUST send float args ( TouchOSC and Lemur ).
+		 * Normally these ardour transport messages don't require an argument,
+		 * so we're providing redundant calls with vestigial "float" args.
+		 *
+		 * These controls are active on 1.0 only (to prevent duplicate action on
+		 * press "/button 1", and release "/button 0")
+		 * http://hexler.net/docs/touchosc-controls-reference
+		 */
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/loop_toggle", "f", loop_toggle);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/add_marker", "f", add_marker);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/goto_start", "f", goto_start);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/goto_end", "f", goto_end);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/rewind", "f", rewind);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/ffwd", "f", ffwd);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/transport_stop", "f", transport_stop);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/transport_play", "f", transport_play);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/save_state", "f", save_state);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/prev_marker", "f", prev_marker);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/next_marker", "f", next_marker);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/undo", "f", undo);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/redo", "f", redo);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/toggle_punch_in", "f", toggle_punch_in);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/toggle_punch_out", "f", toggle_punch_out);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/rec_enable_toggle", "f", rec_enable_toggle);
+		REGISTER_CALLBACK (serv, "/ardour/pushbutton/toggle_all_rec_enables", "f", toggle_all_rec_enables);
+
 		REGISTER_CALLBACK (serv, "/ardour/routes/mute", "ii", route_mute);
 		REGISTER_CALLBACK (serv, "/ardour/routes/solo", "ii", route_solo);
 		REGISTER_CALLBACK (serv, "/ardour/routes/recenable", "ii", route_recenable);
@@ -725,6 +766,9 @@ OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv
 void
 OSC::routes_list (lo_message msg)
 {
+	if (!session) {
+		return;
+	}
 	for (int n = 0; n < (int) session->nroutes(); ++n) {
 
 		boost::shared_ptr<Route> r = session->route_by_remote_id (n);
@@ -778,6 +822,9 @@ OSC::routes_list (lo_message msg)
 void
 OSC::transport_frame (lo_message msg)
 {
+	if (!session) {
+		return;
+	}
 	framepos_t pos = session->transport_frame ();
 
 	lo_message reply = lo_message_new ();
@@ -788,6 +835,39 @@ OSC::transport_frame (lo_message msg)
 	lo_message_free (reply);
 }
 
+void
+OSC::transport_speed (lo_message msg)
+{
+	if (!session) {
+		return;
+	}
+	double ts = session->transport_speed ();
+
+	lo_message reply = lo_message_new ();
+	lo_message_add_double (reply, ts);
+
+	lo_send_message (lo_message_get_source (msg), "/ardour/transport_speed", reply);
+
+	lo_message_free (reply);
+}
+
+void
+OSC::record_enabled (lo_message msg)
+{
+	if (!session) {
+		return;
+	}
+	int re = (int)session->get_record_enabled ();
+
+	lo_message reply = lo_message_new ();
+	lo_message_add_int32 (reply, re);
+
+	lo_send_message (lo_message_get_source (msg), "/ardour/record_enabled", reply);
+
+	lo_message_free (reply);
+}
+
+
 int
 OSC::route_mute (int rid, int yn)
 {
@@ -1023,7 +1103,7 @@ OSC::route_plugin_parameter (int rid, int piid, int par, float val)
 
 		boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
 		// cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
-		c->set_value (val);
+		c->set_value (val, PBD::Controllable::NoGroup);
 	} else {
 		PBD::warning << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << rid << "' is out of range" << endmsg;
 		PBD::info << "OSC: Valid range min=" << pd.lower << " max=" << pd.upper << endmsg;
diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h
index 38aad29..c19a8d0 100644
--- a/libs/surfaces/osc/osc.h
+++ b/libs/surfaces/osc/osc.h
@@ -79,6 +79,8 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
 	int start ();
 	int stop ();
 
+	static void* request_factory (uint32_t);
+
   protected:
         void thread_init ();
 	void do_request (OSCUIRequest*);
@@ -121,7 +123,9 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
 	static int _catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data);
 
 	void routes_list (lo_message msg);
-	void transport_frame(lo_message msg);
+	void transport_frame (lo_message msg);
+	void transport_speed (lo_message msg);
+	void record_enabled (lo_message msg);
 
 #define PATH_CALLBACK_MSG(name)					\
         static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \
@@ -134,12 +138,15 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
 
 	PATH_CALLBACK_MSG(routes_list);
 	PATH_CALLBACK_MSG(transport_frame);
+	PATH_CALLBACK_MSG(transport_speed);
+	PATH_CALLBACK_MSG(record_enabled);
 
 #define PATH_CALLBACK(name) \
         static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \
 		return static_cast<OSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \
         } \
-        int cb_ ## name (const char *, const char *, lo_arg **, int, void *) { \
+        int cb_ ## name (const char *, const char *types, lo_arg ** argv, int argc, void *) { \
+		if (argc > 0 && !strcmp (types, "f") && argv[0]->f != 1.0) { return 0; } \
 		name (); \
 		return 0; \
 	}
diff --git a/libs/surfaces/wiimote/interface.cc b/libs/surfaces/wiimote/interface.cc
index 9a704e4..6998374 100644
--- a/libs/surfaces/wiimote/interface.cc
+++ b/libs/surfaces/wiimote/interface.cc
@@ -48,6 +48,12 @@ probe_wiimote_protocol (ControlProtocolDescriptor*)
 {
 	return WiimoteControlProtocol::probe ();
 }
+static void*
+wiimote_request_buffer_factory (uint32_t num_requests)
+{
+	return WiimoteControlProtocol::request_factory (num_requests);
+}
+
 
 static ControlProtocolDescriptor wiimote_descriptor = {
 	name : "Wiimote",
@@ -58,7 +64,8 @@ static ControlProtocolDescriptor wiimote_descriptor = {
 	supports_feedback : false,
 	probe : probe_wiimote_protocol,
 	initialize : new_wiimote_protocol,
-	destroy : delete_wiimote_protocol
+	destroy : delete_wiimote_protocol,
+	request_buffer_factory : wiimote_request_buffer_factory
 };
 
 extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &wiimote_descriptor; }
diff --git a/libs/surfaces/wiimote/wiimote.cc b/libs/surfaces/wiimote/wiimote.cc
index aa36cdf..d86dbbc 100644
--- a/libs/surfaces/wiimote/wiimote.cc
+++ b/libs/surfaces/wiimote/wiimote.cc
@@ -164,7 +164,7 @@ WiimoteControlProtocol::thread_init ()
 	pthread_set_name (X_("wiimote"));
 
 	// allow to make requests to the GUI and RT thread(s)
-	PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self (), X_("wiimote"), 2048);
+	PBD::notify_event_loops_about_thread_creation (pthread_self (), X_("wiimote"), 2048);
 	BasicUI::register_thread ("wiimote");
 
 	// connect a Wiimote
@@ -455,3 +455,15 @@ wiimote_control_protocol_mesg_callback (cwiid_wiimote_t *wiimote, int mesg_count
 
 	DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::mesg_callback done\n");
 }
+
+
+void*
+WiimoteControlProtocol::request_factory (uint32_t num_requests)
+{
+	/* AbstractUI<T>::request_buffer_factory() is a template method only
+	   instantiated in this source module. To provide something visible for
+	   use in the interface/descriptor, we have this static method that is
+	   template-free.
+	*/
+	return request_buffer_factory (num_requests);
+}
diff --git a/libs/surfaces/wiimote/wiimote.h b/libs/surfaces/wiimote/wiimote.h
index 6edadf6..c1fbcfd 100644
--- a/libs/surfaces/wiimote/wiimote.h
+++ b/libs/surfaces/wiimote/wiimote.h
@@ -43,6 +43,8 @@ public:
 	virtual ~WiimoteControlProtocol ();
 
 	static bool probe ();
+	static void* request_factory (uint32_t);
+
 	int set_active (bool yn);
 
 	XMLNode& get_state ();
diff --git a/libs/surfaces/wscript b/libs/surfaces/wscript
index 71bb35d..bc72446 100644
--- a/libs/surfaces/wscript
+++ b/libs/surfaces/wscript
@@ -21,6 +21,7 @@ out = 'build'
 
 children = [
         'control_protocol',
+        'faderport',
         'generic_midi',
         'mackie',
 ]
@@ -37,7 +38,7 @@ def configure(conf):
 
     autowaf.set_recursive()
     autowaf.configure(conf)
-    
+
     #autowaf.check_pkg(conf, 'libusb-1.0', uselib_store='USB', mandatory=False)
     #if Options.options.tranzport and conf.is_defined('HAVE_USB'):
     #    conf.define('BUILD_TRANZPORT', 1)
@@ -67,6 +68,7 @@ def configure(conf):
 def build(bld):
     bld.recurse('control_protocol')
     bld.recurse('generic_midi')
+    bld.recurse('faderport')
     bld.recurse('mackie')
 
     if bld.is_defined ('HAVE_LO'):
diff --git a/libs/vamp-plugins/EBUr128.cpp b/libs/vamp-plugins/EBUr128.cpp
new file mode 100644
index 0000000..1a3b9a4
--- /dev/null
+++ b/libs/vamp-plugins/EBUr128.cpp
@@ -0,0 +1,170 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include "EBUr128.h"
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+
+VampEBUr128::VampEBUr128(float inputSampleRate)
+    : Plugin(inputSampleRate)
+    , m_stepSize(0)
+{
+}
+
+VampEBUr128::~VampEBUr128()
+{
+}
+
+string
+VampEBUr128::getIdentifier() const
+{
+    return "ebur128";
+}
+
+string
+VampEBUr128::getName() const
+{
+    return "EBU R128 Loudness";
+}
+
+string
+VampEBUr128::getDescription() const
+{
+    return "Loudness measurements according to the EBU Recommendation 128";
+}
+
+string
+VampEBUr128::getMaker() const
+{
+    return "Harrison Consoles";
+}
+
+int
+VampEBUr128::getPluginVersion() const
+{
+    return 2;
+}
+
+string
+VampEBUr128::getCopyright() const
+{
+    return "GPL version 2 or later";
+}
+
+bool
+VampEBUr128::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (channels < getMinChannelCount() ||
+	channels > getMaxChannelCount()) return false;
+
+    m_stepSize = std::min(stepSize, blockSize);
+    m_channels = channels;
+
+    ebu.init (m_channels, m_inputSampleRate);
+
+    return true;
+}
+
+void
+VampEBUr128::reset()
+{
+    ebu.reset ();
+}
+
+VampEBUr128::OutputList
+VampEBUr128::getOutputDescriptors() const
+{
+    OutputList list;
+
+    OutputDescriptor zc;
+    zc.identifier = "loundless";
+    zc.name = "Integrated loudness";
+    zc.description = "Integrated loudness";
+    zc.unit = "LUFS";
+    zc.hasFixedBinCount = true;
+    zc.binCount = 0;
+    zc.hasKnownExtents = false;
+    zc.isQuantized = false;
+    zc.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(zc);
+
+    zc.identifier = "range";
+    zc.name = "Integrated loudness Range";
+    zc.description = "Dynamic Range of the audio";
+    zc.unit = "LU";
+    zc.hasFixedBinCount = true;
+    zc.binCount = 0;
+    zc.hasKnownExtents = false;
+    zc.isQuantized = false;
+    zc.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(zc);
+
+    return list;
+}
+
+VampEBUr128::FeatureSet
+VampEBUr128::process(const float *const *inputBuffers,
+                      Vamp::RealTime timestamp)
+{
+    if (m_stepSize == 0) {
+	cerr << "ERROR: VampEBUr128::process: "
+	     << "VampEBUr128 has not been initialised"
+	     << endl;
+	return FeatureSet();
+    }
+
+    ebu.integr_start (); // noop if already started
+    ebu.process (m_stepSize, inputBuffers);
+
+    return FeatureSet();
+}
+
+VampEBUr128::FeatureSet
+VampEBUr128::getRemainingFeatures()
+{
+    FeatureSet returnFeatures;
+
+    Feature loudness;
+    loudness.hasTimestamp = false;
+    loudness.values.push_back(ebu.integrated());
+    returnFeatures[0].push_back(loudness);
+
+    Feature range;
+    range.hasTimestamp = false;
+    range.values.push_back(ebu.range_max () - ebu.range_min ());
+    returnFeatures[1].push_back(range);
+
+    return returnFeatures;
+}
diff --git a/libs/vamp-plugins/EBUr128.h b/libs/vamp-plugins/EBUr128.h
new file mode 100644
index 0000000..026aa40
--- /dev/null
+++ b/libs/vamp-plugins/EBUr128.h
@@ -0,0 +1,73 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _EBUR128_PLUGIN_H_
+#define _EBUR128_PLUGIN_H_
+
+#include <vamp-sdk/Plugin.h>
+#include "ebu_r128_proc.h"
+
+class VampEBUr128 : public Vamp::Plugin
+{
+public:
+    VampEBUr128(float inputSampleRate);
+    virtual ~VampEBUr128();
+
+    size_t getMinChannelCount() const { return 1; }
+    size_t getMaxChannelCount() const { return 2; }
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void reset();
+
+    InputDomain getInputDomain() const { return TimeDomain; }
+
+    std::string getIdentifier() const;
+    std::string getName() const;
+    std::string getDescription() const;
+    std::string getMaker() const;
+    int getPluginVersion() const;
+    std::string getCopyright() const;
+
+    OutputList getOutputDescriptors() const;
+
+    FeatureSet process(const float *const *inputBuffers,
+                       Vamp::RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+protected:
+    size_t m_stepSize;
+    size_t m_channels;
+
+private:
+    Fons::Ebu_r128_proc ebu;
+};
+
+
+#endif
diff --git a/libs/vamp-plugins/ebu_r128_proc.cc b/libs/vamp-plugins/ebu_r128_proc.cc
new file mode 100644
index 0000000..5675171
--- /dev/null
+++ b/libs/vamp-plugins/ebu_r128_proc.cc
@@ -0,0 +1,340 @@
+// ------------------------------------------------------------------------
+//
+//  Copyright (C) 2010-2011 Fons Adriaensen <fons at linuxaudio.org>
+//  Copyright (C) 2015 Robin Gareus <robin at gareus.org>
+//    
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// ------------------------------------------------------------------------
+
+
+#include <string.h>
+#include <math.h>
+#include "ebu_r128_proc.h"
+
+namespace Fons {
+
+float Ebu_r128_hist::_bin_power [100] = { 0.0f };
+float Ebu_r128_proc::_chan_gain [5] = { 1.0f, 1.0f, 1.0f, 1.41f, 1.41f };
+
+
+Ebu_r128_hist::Ebu_r128_hist (void)
+{
+    _histc = new int [751];
+    initstat ();
+    reset ();
+}
+
+
+Ebu_r128_hist::~Ebu_r128_hist (void)
+{
+    delete[] _histc;
+}
+
+
+void Ebu_r128_hist::reset (void)
+{
+    memset (_histc, 0, 751 * sizeof (float));
+    _count = 0;
+    _error = 0;
+}
+
+
+void Ebu_r128_hist::initstat (void)
+{
+    int i;
+
+    if (_bin_power [0]) return;
+    for (i = 0; i < 100; i++)
+    {
+	_bin_power [i] = powf (10.0f, i / 100.0f);
+    }
+}
+
+
+void Ebu_r128_hist::addpoint (float v)
+{
+    int k;
+
+    k = (int) floorf (10 * v + 700.5f);
+    if (k < 0) return;
+    if (k > 750)
+    {
+	k = 750;
+	_error++;
+    }
+    _histc [k]++;
+    _count++;
+}
+
+
+float Ebu_r128_hist::integrate (int i)
+{
+    int   j, k, n;
+    float s;
+
+    j = i % 100;
+    n = 0;
+    s = 0;
+    while (i <= 750)
+    {
+	k = _histc [i++];
+	n += k;
+	s += k * _bin_power [j++];
+	if (j == 100)
+	{
+	    j = 0;
+	    s /= 10.0f;
+	}
+    }	
+    return s / n;
+}
+
+
+void Ebu_r128_hist::calc_integ (float *vi, float *th)
+{
+    int   k;
+    float s;
+
+    if (_count < 50)
+    {
+        *vi = -200.0f;
+	return;
+    }
+    s = integrate (0);
+//  Original threshold was -8 dB below result of first integration
+//    if (th) *th = 10 * log10f (s) - 8.0f;
+//    k = (int)(floorf (100 * log10f (s) + 0.5f)) + 620;
+//  Threshold redefined to -10 dB below result of first integration
+    if (th) *th = 10 * log10f (s) - 10.0f;
+    k = (int)(floorf (100 * log10f (s) + 0.5f)) + 600;
+    if (k < 0) k = 0;
+    s = integrate (k);
+    *vi = 10 * log10f (s);
+}
+
+
+void Ebu_r128_hist::calc_range (float *v0, float *v1, float *th)
+{
+    int   i, j, k, n;
+    float a, b, s;
+
+    if (_count < 20)
+    {
+	*v0 = -200.0f;
+	*v1 = -200.0f;
+        return;
+    }
+    s = integrate (0);
+    if (th) *th = 10 * log10f (s) - 20.0f;
+    k = (int)(floorf (100 * log10f (s) + 0.5)) + 500;
+    if (k < 0) k = 0;
+    for (i = k, n = 0; i <= 750; i++) n += _histc [i]; 
+    a = 0.10f * n;
+    b = 0.95f * n;
+    for (i =   k, s = 0; s < a; i++) s += _histc [i];
+    for (j = 750, s = n; s > b; j--) s -= _histc [j];
+    *v0 = (i - 701) / 10.0f;
+    *v1 = (j - 699) / 10.0f;
+}
+
+
+
+
+Ebu_r128_proc::Ebu_r128_proc (void)
+{
+    reset ();
+}
+
+
+Ebu_r128_proc::~Ebu_r128_proc (void)
+{
+}
+
+
+void Ebu_r128_proc::init (int nchan, float fsamp)
+{
+    _nchan = nchan;
+    _fsamp = fsamp;
+    _fragm = (int) fsamp / 20;
+    detect_init (_fsamp);
+    reset ();
+}
+
+
+void Ebu_r128_proc::reset (void)
+{
+    _integr = false;
+    _frcnt = _fragm;
+    _frpwr = 1e-30f;
+    _wrind  = 0;
+    _div1 = 0;
+    _div2 = 0;
+    _loudness_M = -200.0f;
+    _loudness_S = -200.0f;
+    memset (_power, 0, 64 * sizeof (float));
+    integr_reset ();
+    detect_reset ();
+}
+
+
+void Ebu_r128_proc::integr_reset (void)
+{
+    _hist_M.reset ();
+    _hist_S.reset ();
+    _maxloudn_M = -200.0f;
+    _maxloudn_S = -200.0f;
+    _integrated = -200.0f;
+    _integ_thr  = -200.0f;
+    _range_min  = -200.0f;
+    _range_max  = -200.0f;
+    _range_thr  = -200.0f;
+    _div1 = _div2 = 0;
+}
+
+
+void Ebu_r128_proc::process (int nfram, const float *const *input)
+{
+    int  i, k;
+    
+    for (i = 0; i < _nchan; i++) _ipp [i] = input [i];
+    while (nfram)
+    {
+	k = (_frcnt < nfram) ? _frcnt : nfram;
+	_frpwr += detect_process (k);
+        _frcnt -= k;
+	if (_frcnt == 0)
+	{
+	    _power [_wrind++] = _frpwr / _fragm;
+	    _frcnt = _fragm;
+	    _frpwr = 1e-30f;
+	    _wrind &= 63;
+	    _loudness_M = addfrags (8);
+	    _loudness_S = addfrags (60);
+	    if (!isfinite(_loudness_M) || _loudness_M < -200.f) _loudness_M = -200.0f;
+	    if (!isfinite(_loudness_S) || _loudness_S < -200.f) _loudness_S = -200.0f;
+            if (_loudness_M > _maxloudn_M) _maxloudn_M = _loudness_M;
+            if (_loudness_S > _maxloudn_S) _maxloudn_S = _loudness_S;
+	    if (_integr)
+	    {
+	        if (++_div1 == 2)
+  	        {
+		    _hist_M.addpoint (_loudness_M);
+		    _div1 = 0;
+	        }
+	        if (++_div2 == 10)
+	        {
+		    _hist_S.addpoint (_loudness_S);
+		    _div2 = 0;
+		    _hist_M.calc_integ (&_integrated, &_integ_thr);
+		    _hist_S.calc_range (&_range_min, &_range_max, &_range_thr);
+		}
+	    }
+	}
+	for (i = 0; i < _nchan; i++) _ipp [i] += k;
+	nfram -= k;
+    }
+}
+
+
+float Ebu_r128_proc::addfrags (int nfrag)
+{
+    int    i, k;
+    float  s;
+
+    s = 0;
+    k = (_wrind - nfrag) & 63;
+    for (i = 0; i < nfrag; i++) s += _power [(i + k) & 63];
+    return -0.6976f + 10 * log10f (s / nfrag);
+}
+
+
+void Ebu_r128_proc::detect_init (float fsamp)
+{
+    float a, b, c, d, r, u1, u2, w1, w2;
+
+    r = 1 / tan (4712.3890f / fsamp);
+    w1 = r / 1.12201f; 
+    w2 = r * 1.12201f;
+    u1 = u2 = 1.4085f + 210.0f / fsamp;
+    a = u1 * w1;
+    b = w1 * w1;
+    c = u2 * w2;
+    d = w2 * w2;
+    r = 1 + a + b;
+    _a0 = (1 + c + d) / r;
+    _a1 = (2 - 2 * d) / r;
+    _a2 = (1 - c + d) / r;
+    _b1 = (2 - 2 * b) / r;
+    _b2 = (1 - a + b) / r;
+    r = 48.0f / fsamp;
+    a = 4.9886075f * r;
+    b = 6.2298014f * r * r;
+    r = 1 + a + b;
+    a *= 2 / r;
+    b *= 4 / r;
+    _c3 = a + b;
+    _c4 = b;
+    r = 1.004995f / r;
+    _a0 *= r;
+    _a1 *= r;
+    _a2 *= r;
+}
+
+
+void Ebu_r128_proc::detect_reset (void)
+{
+    for (int i = 0; i < MAXCH; i++) _fst [i].reset ();
+}
+
+
+float Ebu_r128_proc::detect_process (int nfram)
+{
+    int   i, j;
+    float si, sj;
+    float x, y, z1, z2, z3, z4;
+    float const *p;
+    Ebu_r128_fst *S;
+
+    si = 0;
+    for (i = 0, S = _fst; i < _nchan; i++, S++)
+    {
+	z1 = S->_z1;
+	z2 = S->_z2;
+	z3 = S->_z3;
+	z4 = S->_z4;
+	p = _ipp [i];
+	sj = 0;
+	for (j = 0; j < nfram; j++)
+	{
+	    x = p [j] - _b1 * z1 - _b2 * z2 + 1e-15f;
+	    y = _a0 * x + _a1 * z1 + _a2 * z2 - _c3 * z3 - _c4 * z4;
+	    z2 = z1;
+	    z1 = x;
+	    z4 += z3;
+	    z3 += y;
+	    sj += y * y;
+	}
+	if (_nchan == 1) si = 2 * sj;
+	else si += _chan_gain [i] * sj;
+	S->_z1 = !isfinite(z1) ? 0 : z1;
+	S->_z2 = !isfinite(z2) ? 0 : z2;
+	S->_z3 = !isfinite(z3) ? 0 : z3;
+	S->_z4 = !isfinite(z4) ? 0 : z4;
+    }
+    return si;
+}
+
+};
diff --git a/libs/vamp-plugins/ebu_r128_proc.h b/libs/vamp-plugins/ebu_r128_proc.h
new file mode 100644
index 0000000..126be8b
--- /dev/null
+++ b/libs/vamp-plugins/ebu_r128_proc.h
@@ -0,0 +1,137 @@
+// ------------------------------------------------------------------------
+//
+//  Copyright (C) 2010-2011 Fons Adriaensen <fons at linuxaudio.org>
+//    
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// ------------------------------------------------------------------------
+
+
+#ifndef _EBU_R128_PROC_H
+#define _EBU_R128_PROC_H
+
+#define MAXCH 5
+
+namespace Fons {
+
+class Ebu_r128_fst
+{
+private:
+
+    friend class Ebu_r128_proc;
+
+    void reset (void) { _z1 = _z2 = _z3 = _z4 = 0; }
+
+    float _z1, _z2, _z3, _z4;
+};
+
+
+class Ebu_r128_hist
+{
+private:
+
+    Ebu_r128_hist (void);
+    ~Ebu_r128_hist (void);
+
+    friend class Ebu_r128_proc;
+
+    void  reset (void);
+    void  initstat (void);
+    void  addpoint (float v);
+    float integrate (int ind);
+    void  calc_integ (float *vi, float *th);
+    void  calc_range (float *v0, float *v1, float *th);
+
+    int  *_histc;
+    int   _count;
+    int   _error;
+
+    static float _bin_power [100];
+};
+
+
+
+class Ebu_r128_proc
+{
+public:
+
+    Ebu_r128_proc (void);
+    ~Ebu_r128_proc (void);
+
+    void  init (int nchan, float fsamp);
+    void  reset (void);
+    void  process (int nfram, const float *const *input);
+    void  integr_reset (void);
+    void  integr_pause (void) { _integr = false; }
+    void  integr_start (void) { _integr = true; }
+
+    float loudness_M (void) const { return _loudness_M; }
+    float maxloudn_M (void) const { return _maxloudn_M; }
+    float loudness_S (void) const { return _loudness_S; }
+    float maxloudn_S (void) const { return _maxloudn_S; }
+    float integrated (void) const { return _integrated; }
+    float integ_thr (void) const { return _integ_thr; }
+    float range_min (void) const { return _range_min; }
+    float range_max (void) const { return _range_max; }
+    float range_thr (void) const { return _range_thr; }
+
+    const int *histogram_M (void) const { return _hist_M._histc; }
+    const int *histogram_S (void) const { return _hist_S._histc; }
+    int hist_M_count (void) const { return _hist_M._count; }
+    int hist_S_count (void) const { return _hist_S._count; }
+
+private:
+
+    float addfrags (int nfrag);
+    void  detect_init (float fsamp);
+    void  detect_reset (void);
+    float detect_process (int nfram);
+
+    bool              _integr;       // Integration on/off.
+    int               _nchan;        // Number of channels, 2 or 5.
+    float             _fsamp;        // Sample rate.
+    int               _fragm;        // Fragmenst size, 1/20 second.
+    int               _frcnt;        // Number of samples remaining in current fragment.
+    float             _frpwr;        // Power accumulated for current fragment.
+    float             _power [64];   // Array of fragment powers.
+    int               _wrind;        // Write index into _frpwr 
+    int               _div1;         // M period counter, 200 ms;
+    int               _div2;         // S period counter, 1s;
+    float             _loudness_M;
+    float             _maxloudn_M;
+    float             _loudness_S;
+    float             _maxloudn_S;
+    float             _integrated;
+    float             _integ_thr;
+    float             _range_min;
+    float             _range_max;
+    float             _range_thr;
+    
+    // Filter coefficients and states.
+    float             _a0, _a1, _a2;
+    float             _b1, _b2;
+    float             _c3, _c4;
+    float const      *_ipp [MAXCH];
+    Ebu_r128_fst      _fst [MAXCH];
+    Ebu_r128_hist     _hist_M;
+    Ebu_r128_hist     _hist_S;
+
+    // Default channel gains.
+    static float      _chan_gain [5];
+};
+
+};
+
+#endif
diff --git a/libs/vamp-plugins/plugins.cpp b/libs/vamp-plugins/plugins.cpp
index d7db2d9..b12a278 100644
--- a/libs/vamp-plugins/plugins.cpp
+++ b/libs/vamp-plugins/plugins.cpp
@@ -46,6 +46,7 @@
 #include "PercussionOnsetDetector.h"
 #include "AmplitudeFollower.h"
 #include "OnsetDetect.h"
+#include "EBUr128.h"
 #ifdef HAVE_AUBIO
 #include "Onset.h"
 #endif
@@ -55,6 +56,7 @@ static Vamp::PluginAdapter<SpectralCentroid> spectralCentroidAdapter;
 static Vamp::PluginAdapter<PercussionOnsetDetector> percussionOnsetAdapter;
 static Vamp::PluginAdapter<AmplitudeFollower> amplitudeAdapter;
 static Vamp::PluginAdapter<OnsetDetector> onsetDetectorAdapter;
+static Vamp::PluginAdapter<VampEBUr128> VampEBUr128Adapter;
 #ifdef HAVE_AUBIO
 static Vamp::PluginAdapter<Onset> onsetAdapter;
 #endif
@@ -70,8 +72,9 @@ const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
     case  2: return percussionOnsetAdapter.getDescriptor();
     case  3: return amplitudeAdapter.getDescriptor();
     case  4: return onsetDetectorAdapter.getDescriptor();
+    case  5: return VampEBUr128Adapter.getDescriptor();
 #ifdef HAVE_AUBIO
-    case  5: return onsetAdapter.getDescriptor();
+    case  6: return onsetAdapter.getDescriptor();
 #endif
     default: return 0;
     }
diff --git a/libs/vamp-plugins/wscript b/libs/vamp-plugins/wscript
index 06d440f..131ec03 100644
--- a/libs/vamp-plugins/wscript
+++ b/libs/vamp-plugins/wscript
@@ -38,6 +38,8 @@ def build(bld):
     obj.source = '''
             plugins.cpp
             AmplitudeFollower.cpp
+            EBUr128.cpp
+            ebu_r128_proc.cc
             OnsetDetect.cpp
             PercussionOnsetDetector.cpp
             SpectralCentroid.cpp
diff --git a/mcp/faderport.device b/mcp/faderport.device
new file mode 100644
index 0000000..eb4d73a
--- /dev/null
+++ b/mcp/faderport.device
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<MackieProtocolDevice>
+  <Name value="Presonus Faderport"/>
+  <DeviceType value="HUI"/>
+  <Strips value="1"/>
+  <MasterFader value="no"/>
+  <TimecodeDisplay value="no"/>
+  <TwoCharacterDisplay value="no"/>
+  <Extenders value="0"/>
+  <MasterPosition value="0"/>
+  <GlobalControls value="yes"/>
+  <JogWheel value="no"/>
+  <TouchSenseFaders value="yes"/>
+</MackieProtocolDevice>
diff --git a/mcp/midikbd.device b/mcp/midikbd.device
new file mode 100644
index 0000000..9212623
--- /dev/null
+++ b/mcp/midikbd.device
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<MackieProtocolDevice>
+  <Name value="midikbd5"/>
+  <Strips value="5"/>
+  <MasterFader value="yes"/>
+  <TimecodeDisplay value="yes"/>
+  <TwoCharacterDisplay value="yes"/>
+  <Extenders value="0"/>
+  <MasterPosition value="0"/>
+  <GlobalControls value="yes"/>
+  <JogWheel value="yes"/>
+  <TouchSenseFaders value="no"/>
+  <HasSeparateMeters value="yes"/>
+  <NoHandShake value="yes"/>
+  <HasMeters value="yes"/>
+</MackieProtocolDevice>
diff --git a/midi_maps/Novation Impulse 49.map b/midi_maps/Novation Impulse 49.map
new file mode 100644
index 0000000..a6a10f3
--- /dev/null
+++ b/midi_maps/Novation Impulse 49.map	
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ArdourMIDIBindings version="1.0.0" name="Novation Impulse 49">
+
+<!-- This mapping relies on the Basic MIDI preset in the Impulse 49. -->
+
+<!-- Transport Control -->
+
+  <Binding channel="1" ctl="112" function="transport-start"/>
+  <Binding channel="1" ctl="113" function="transport-end"/>
+  <Binding channel="1" ctl="114" function="transport-stop"/>
+  <Binding channel="1" ctl="115" function="transport-roll"/>
+  <Binding channel="1" ctl="116" function="loop-toggle"/>
+  <Binding channel="1" ctl="117" function="rec-enable"/>
+  <Binding channel="1" ctl="117" function="rec-disable"/>
+
+<!-- Gain controls. Faders are mapped to faders. -->
+
+  <Binding channel="1" ctl="108" uri="/route/gain 1"/>
+  <Binding channel="1" ctl="109" uri="/route/gain 2"/>
+  <Binding channel="1" ctl="110" uri="/route/gain 3"/>
+  <Binding channel="1" ctl="111" uri="/route/gain 4"/>
+  <Binding channel="1" ctl="112" uri="/route/gain 5"/>
+  <Binding channel="1" ctl="114" uri="/route/gain 6"/>
+  <Binding channel="1" ctl="115" uri="/route/gain 7"/>
+  <Binding channel="1" ctl="116" uri="/route/gain 8"/>
+  <Binding channel="1" ctl="117" uri="/bus/gain master"/>
+
+<!-- Pan controls. Encoders are mapped to pan direction. -->
+<!-- There doesn't seem to be a way to map encoders to pan width. -->
+
+  <Binding channel="1" ctl="105" uri="/route/pandirection 1"/>
+  <Binding channel="1" ctl="106" uri="/route/pandirection 2"/>
+  <Binding channel="1" ctl="104" uri="/route/pandirection 3"/>
+  <Binding channel="1" ctl="107" uri="/route/pandirection 4"/>
+  <Binding channel="1" ctl="72" uri="/route/pandirection 5"/>
+  <Binding channel="1" ctl="40" uri="/route/pandirection 6"/>
+  <Binding channel="1" ctl="73" uri="/route/pandirection 7"/>
+  <Binding channel="1" ctl="48" uri="/route/pandirection 8"/>
+
+<!-- Status controls -->
+<!-- Status buttons are mapped to mute toggles. -->
+<!-- Apparently Solo toggle only works when Automap is used. Sad but true. -->
+
+</ArdourMIDIBindings>
\ No newline at end of file
diff --git a/midi_maps/Yamaha_KX25.map b/midi_maps/Yamaha_KX25.map
new file mode 100644
index 0000000..0a06675
--- /dev/null
+++ b/midi_maps/Yamaha_KX25.map
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ArdourMIDIBindings version="1.0.0" name="Yamaha KX25 Transport Controls">
+
+<!-- Map file created at 09-09-2013 by Gerard Aberkrom -->
+
+<!-- The KX25 uses 3 midiports. The first one are the control knobs and the keyboard itself, -->
+<!-- The second port is used by the DAW REMOTE buttons, (except for the esc,return, and cursor keys, -->
+<!-- those work the same as the ones on your typing keyboard!) and the third are the  midiconnections on the back of the KX. -->
+<!-- Ergo, make sure you connect the 2nd midiport to your Ardour Control In port -->
+
+
+
+<!-- Transport Controls. function="rec-enable" (or rec-disable, or both with the same note value)
+     didn't toggle the record state on/off, while the OSC parameter "action=" did.      -->
+  <Binding channel="1" note="85" function="loop-toggle"/>
+  <Binding channel="1" note="91" action="Transport/Rewind"/>
+  <Binding channel="1" note="92" action="Transport/Forward"/>
+  <Binding channel="1" note="93" action="Transport/Stop"/>
+  <Binding channel="1" note="94" action="Transport/Roll"/>
+  <Binding channel="1" note="95" action="Transport/Record"/>
+
+<!-- Extra keys-->
+
+<!-- keys Assign 1, Assign 2, Mute and Solo" . Since I didn't find a way to
+     get the solo and mute working while selecting a track with action="Editor/select-prev( or next)-route"
+     I assigned those keys to transport keys. A better solution for this solo/mute riddle is much appreciated! -->
+
+
+<Binding channel="1" note="56" action="Editor/playhead-to-previous-region-boundary"/>
+<Binding channel="1" note="57" action="Editor/playhead-to-next-region-boundary"/>
+ <Binding channel="1" note="58" action="Transport/TransitionToReverse"/>
+ <Binding channel="1" note="59" action="Transport/TransitionToRoll"/>
+<!-- keys VSTi Window, Add Instrument Track, Cubase Function A & B -->
+  <Binding channel="1" note="61" action="Editor/track-record-enable-toggle"/>
+  <Binding channel="1" note="60" action="Main/AddTrackBus"/>
+  <Binding channel="1" note="54" action="Editor/select-prev-route"/>
+  <Binding channel="1" note="55" action="Editor/select-next-route"/>
+
+</ArdourMIDIBindings>
diff --git a/msvc32-fixup.pl b/msvc32-fixup.pl
new file mode 100644
index 0000000..c72a689
--- /dev/null
+++ b/msvc32-fixup.pl
@@ -0,0 +1,103 @@
+#! e:/program files/perl/bin/perl.exe
+#  version info can be found in 'TO BE CONFIRMED'
+
+require "../gnu-windows/src/local-paths.lib";
+
+$msvc_mixbus_version = "3.00.0";
+$major = 3;
+$minor = 0;
+$micro = 0;
+$interface_age = 0;
+$scanner_app_version = "2.00.0";
+$scanner_major = 2;
+$scanner_minor = 0;
+$scanner_micro = 0;
+$scanner_interface_age = 0;
+$binary_age = 3000;
+$current_minus_age = 0;
+$exec_prefix = "lib";
+$dll_suffix = "32";
+$lib_ext = ".dll";
+$monospace = "ArdourMono";
+$font_small = 9;
+$font_smaller = 8;
+$font_normal = 10;
+$font_big = 14;
+$font_large = 18;
+$font_larger = 24;
+$font_huger = 34;
+$font_massive = 60;
+
+sub process_file
+{
+        my $outfilename = shift;
+	my $infilename = $outfilename . ".in";
+	
+	open (INPUT, "< $infilename") || exit 1;
+	open (OUTPUT, "> $outfilename") || exit 1;
+	
+	while (<INPUT>) {
+	    s/\@GLIB_API_VERSION@/$glib_api_version/g;
+	    s/\@GTK_API_VERSION@/$gtk_api_version/g;
+	    s/\@ATK_API_VERSION@/$atk_api_version/g;
+	    s/\@PANGO_API_VERSION@/$pango_api_version/g;
+	    s/\@GDK_PIXBUF_API_VERSION@/$gdk_pixbuf_api_version/g;
+	    s/\@MSVC_MIXBUS_VERSION@/$msvc_mixbus_version/g;
+	    s/\@MSVC_MIXBUS_MAJOR\@/$major/g;
+	    s/\@MSVC_MIXBUS_MINOR\@/$minor/g;
+	    s/\@MSVC_MIXBUS_MICRO\@/$micro/g;
+	    s/\@MSVC_MIXBUS_INTERFACE_AGE\@/$interface_age/g;
+	    s/\@MSVC_SCANNER_APP_VERSION@/$scanner_app_version/g;
+	    s/\@MSVC_SCANNER_APP_MAJOR\@/$scanner_major/g;
+	    s/\@MSVC_SCANNER_APP_MINOR\@/$scanner_minor/g;
+	    s/\@MSVC_SCANNER_APP_MICRO\@/$scanner_micro/g;
+	    s/\@MSVC_SCANNER_APP_INTERFACE_AGE\@/$scanner_interface_age/g;
+	    s/\@LT_CURRENT_MINUS_AGE@/$current_minus_age/g;
+	    s/\@VERSION@/$msvc_mixbus_version/g;
+	    s/\@DLL_SUFFIX\@/$dll_suffix/g;
+	    s/\@LIB_EXT\@/$lib_ext/g;
+	    s/\@MONOSPACE\@/$monospace/g;
+	    s/\@FONT_SMALL\@/$font_small/g;
+	    s/\@FONT_SMALLER\@/$font_smaller/g;
+	    s/\@FONT_NORMAL\@/$font_normal/g;
+	    s/\@FONT_BIG\@/$font_big/g;
+	    s/\@FONT_LARGE\@/$font_large/g;
+	    s/\@FONT_LARGER\@/$font_larger/g;
+	    s/\@FONT_HUGER\@/$font_huger/g;
+	    s/\@FONT_MASSIVE\@/$font_massive/g;
+	    s/\@GETTEXT_PACKAGE\@/$gettext_package/g;
+	    s/\@PERL_PATH@/$perl_path/g;
+	    s/\@PackagerFolderLocal@/$packager_folder_local/g;
+	    s/\@JackBuildRootFolder@/$jack_build_root_folder/g;
+	    s/\@GlibBuildRootFolder@/$glib_build_root_folder/g;
+	    s/\@GdkPixbufBuildRootFolder@/$gdk_pixbuf_build_root_folder/g;
+	    s/\@GtkBuildProjectFolder@/$gtk_build_project_folder/g;
+	    s/\@GenericIncludeFolder@/$generic_include_folder/g;
+	    s/\@GenericLibraryFolder@/$generic_library_folder/g;
+	    s/\@GenericWin32LibraryFolder@/$generic_win32_library_folder/g;
+	    s/\@GenericWin32BinaryFolder@/$generic_win32_binary_folder/g;
+	    s/\@Debug32TestSuiteFolder@/$debug32_testsuite_folder/g;
+	    s/\@Release32TestSuiteFolder@/$release32_testsuite_folder/g;
+	    s/\@Debug32TargetFolder@/$debug32_target_folder/g;
+	    s/\@Release32TargetFolder@/$release32_target_folder/g;
+	    s/\@Debug32PixbufLoadersFolder@/$debug32_pixbuf_loaders_folder/g;
+	    s/\@Release32PixbufLoadersFolder@/$release32_pixbuf_loaders_folder/g;
+	    s/\@TargetSxSFolder@/$target_sxs_folder/g;
+	    s/\@prefix@/$prefix/g;
+	    s/\@exec_prefix@/$exec_prefix/g;
+	    s/\@includedir@/$generic_include_folder/g;
+	    s/\@libdir@/$generic_library_folder/g;
+	    print OUTPUT;
+	}
+}
+
+process_file ("libs/plugins/reasonablesynth.lv2/manifest.ttl");
+process_file ("gtk2_ardour/default_ui_config");
+
+my $command=join(' ', at ARGV);
+if ($command eq -buildall) {
+	process_file ("MSVCardour3/MSVCArdour3.vsprops");
+	process_file ("MSVCMixbus3/MSVCMixbus3.vsprops");
+	process_file ("MSVCvst_scan/vst_scan.rc");
+	process_file ("icons/win32/msvc_resources.rc");
+}
diff --git a/session_utils/README b/session_utils/README
new file mode 100644
index 0000000..510e3a4
--- /dev/null
+++ b/session_utils/README
@@ -0,0 +1,29 @@
+Ardour Session Utilities
+========================
+
+This folder contains some tools which directly use libardour to access ardour
+sessions.
+
+The overall goal it to provide some non-interactive unix-style commandline
+tools, which are installed along with DAW.
+
+
+Adding new tools
+----------------
+
+One c++ source per tool, see "example.cc" and "export.cc"
+
+  cp session_utils/example.cc session_utils/your_new_tool_name.cc
+  edit session_utils/new_tool_name.cc
+	./waf
+
+The tool is automatically compiled and deployed when installing, using the
+program-name as prefix.  e.g.  "export.cc" becomes "ardour4-export".
+(or "mixbus3-export", depending on the project configuration)
+
+
+Test run from the source
+------------------------
+
+  cd session_utils
+  ./run ardour4-your_new_tool_name
diff --git a/session_utils/ardour-util.sh.in b/session_utils/ardour-util.sh.in
new file mode 100644
index 0000000..3ffc53d
--- /dev/null
+++ b/session_utils/ardour-util.sh.in
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# This is a wrapper script for using the ardour-session utilities
+# it is intended to be symlinked into $PATH for every session-tool
+
+export GTK_PATH=@CONFDIR@:@LIBDIR@${GTK_PATH:+:$GTK_PATH}
+export LD_LIBRARY_PATH=@LIBDIR@${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
+
+# Running Ardour requires these 3 variables to be set
+
+export ARDOUR_DATA_PATH=@DATADIR@
+export ARDOUR_CONFIG_PATH=@CONFDIR@
+export ARDOUR_DLL_PATH=@LIBDIR@
+export VAMP_PATH=@LIBDIR@/vamp
+
+SELF=`basename $0`
+exec "@LIBDIR@/utils/$SELF" "$@"
diff --git a/session_utils/common.cc b/session_utils/common.cc
new file mode 100644
index 0000000..9353c76
--- /dev/null
+++ b/session_utils/common.cc
@@ -0,0 +1,178 @@
+#include <iostream>
+#include <cstdlib>
+#include <glibmm.h>
+
+#include "pbd/debug.h"
+#include "pbd/event_loop.h"
+#include "pbd/error.h"
+#include "pbd/failed_constructor.h"
+#include "pbd/pthread_utils.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/filename_extensions.h"
+#include "ardour/types.h"
+
+#include "common.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+static const char* localedir = LOCALEDIR;
+TestReceiver test_receiver;
+
+void
+TestReceiver::receive (Transmitter::Channel chn, const char * str)
+{
+	const char *prefix = "";
+
+	switch (chn) {
+	case Transmitter::Error:
+		prefix = ": [ERROR]: ";
+		break;
+	case Transmitter::Info:
+		/* ignore */
+		return;
+	case Transmitter::Warning:
+		prefix = ": [WARNING]: ";
+		break;
+	case Transmitter::Fatal:
+		prefix = ": [FATAL]: ";
+		break;
+	case Transmitter::Throw:
+		/* this isn't supposed to happen */
+		abort ();
+	}
+
+	/* note: iostreams are already thread-safe: no external
+	   lock required.
+	*/
+
+	std::cout << prefix << str << std::endl;
+
+	if (chn == Transmitter::Fatal) {
+		::exit (9);
+	}
+}
+
+/* temporarily required due to some code design confusion (Feb 2014) */
+
+#include "ardour/vst_types.h"
+
+int vstfx_init (void*) { return 0; }
+void vstfx_exit () {}
+void vstfx_destroy_editor (VSTState*) {}
+
+class MyEventLoop : public sigc::trackable, public EventLoop
+{
+	public:
+		MyEventLoop (std::string const& name) : EventLoop (name) {
+			run_loop_thread = Glib::Threads::Thread::self();
+		}
+
+		void call_slot (InvalidationRecord*, const boost::function<void()>& f) {
+			if (Glib::Threads::Thread::self() == run_loop_thread) {
+				f ();
+			}
+		}
+
+		Glib::Threads::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
+
+	private:
+		Glib::Threads::Thread* run_loop_thread;
+		Glib::Threads::Mutex   request_buffer_map_lock;
+};
+
+static MyEventLoop *event_loop;
+
+void
+SessionUtils::init ()
+{
+	if (!ARDOUR::init (false, true, localedir)) {
+		cerr << "Ardour failed to initialize\n" << endl;
+		::exit (EXIT_FAILURE);
+	}
+
+	event_loop = new MyEventLoop ("util");
+	EventLoop::set_event_loop_for_thread (event_loop);
+	SessionEvent::create_per_thread_pool ("util", 512);
+
+	test_receiver.listen_to (error);
+	test_receiver.listen_to (info);
+	test_receiver.listen_to (fatal);
+	test_receiver.listen_to (warning);
+}
+
+// TODO return NULL, rather than exit() ?!
+static Session * _load_session (string dir, string state)
+{
+	AudioEngine* engine = AudioEngine::create ();
+
+	if (!engine->set_backend ("None (Dummy)", "Unit-Test", "")) {
+		std::cerr << "Cannot create Audio/MIDI engine\n";
+		::exit (EXIT_FAILURE);
+	}
+
+	float sr;
+	SampleFormat sf;
+
+	std::string s = Glib::build_filename (dir, state + statefile_suffix);
+	if (Session::get_info_from_path (s, sr, sf) == 0) {
+		if (engine->set_sample_rate (sr)) {
+			std::cerr << "Cannot set session's samplerate.\n";
+			::exit (EXIT_FAILURE);
+		}
+	} else {
+		std::cerr << "Cannot get samplerate from session.\n";
+		::exit (EXIT_FAILURE);
+	}
+
+	init_post_engine ();
+
+	if (engine->start () != 0) {
+		std::cerr << "Cannot start Audio/MIDI engine\n";
+		::exit (EXIT_FAILURE);
+	}
+
+	Session* session = new Session (*engine, dir, state);
+	engine->set_session (session);
+	return session;
+}
+
+Session *
+SessionUtils::load_session (string dir, string state)
+{
+	Session* s = 0;
+	try {
+		s = _load_session (dir, state);
+	} catch (failed_constructor& e) {
+		cerr << "failed_constructor: " << e.what() << "\n";
+		::exit (EXIT_FAILURE);
+	} catch (AudioEngine::PortRegistrationFailure& e) {
+		cerr << "PortRegistrationFailure: " << e.what() << "\n";
+		::exit (EXIT_FAILURE);
+	} catch (exception& e) {
+		cerr << "exception: " << e.what() << "\n";
+		::exit (EXIT_FAILURE);
+	} catch (...) {
+		cerr << "unknown exception.\n";
+		::exit (EXIT_FAILURE);
+	}
+	return s;
+}
+
+void
+SessionUtils::unload_session (Session *s)
+{
+	delete s;
+	AudioEngine::instance()->stop ();
+	AudioEngine::destroy ();
+}
+
+void
+SessionUtils::cleanup ()
+{
+	ARDOUR::cleanup ();
+	delete event_loop;
+	pthread_cancel_all ();
+}
diff --git a/session_utils/common.h b/session_utils/common.h
new file mode 100644
index 0000000..5263e84
--- /dev/null
+++ b/session_utils/common.h
@@ -0,0 +1,38 @@
+#ifndef _session_utils_common_h_
+#define _session_utils_common_h_
+
+#include "pbd/transmitter.h"
+#include "pbd/receiver.h"
+
+#include "ardour/ardour.h"
+#include "ardour/session.h"
+
+class TestReceiver : public Receiver
+{
+  protected:
+    void receive (Transmitter::Channel chn, const char * str);
+};
+
+namespace SessionUtils {
+
+	/** initialize libardour */
+	void init ();
+
+	/** clean up, stop Processing Engine
+	 * @param s Session to close (may me NULL)
+	 */
+	void cleanup ();
+
+	/** @param dir Session directory.
+	 *  @param state Session state file, without .ardour suffix.
+	 */
+	ARDOUR::Session * load_session (std::string dir, std::string state);
+
+	/** close session and stop engine
+	 * @param s Session to close (may me NULL)
+	 */
+	void unload_session (ARDOUR::Session *s);
+
+};
+
+#endif /* _session_utils_misc_h_ */
diff --git a/session_utils/debug b/session_utils/debug
new file mode 100755
index 0000000..6182ef2
--- /dev/null
+++ b/session_utils/debug
@@ -0,0 +1,14 @@
+#!/bin/sh
+TOP=`dirname "$0"`/..
+. "$TOP/build/gtk2_ardour/ardev_common_waf.sh"
+SELF=$1
+shift
+
+export ARDOUR_INSIDE_GDB=1
+
+if test -n "`which gdb`"; then
+	exec gdb --args "$TOP/build/session_utils/$SELF" "$@"
+fi
+if test -n "`which lldb`"; then
+	exec lldb -- "$TOP/build/session_utils/$SELF" "$@"
+fi
diff --git a/session_utils/example.cc b/session_utils/example.cc
new file mode 100644
index 0000000..044d40e
--- /dev/null
+++ b/session_utils/example.cc
@@ -0,0 +1,30 @@
+#include <iostream>
+#include <cstdlib>
+
+#include "common.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace SessionUtils;
+
+int main (int argc, char* argv[])
+{
+	SessionUtils::init();
+	Session* s = 0;
+
+	s = SessionUtils::load_session (
+			"/home/rgareus/Documents/ArdourSessions/TestA/",
+			"TestA"
+			);
+
+	printf ("SESSION INFO: routes: %lu\n", s->get_routes()->size ());
+
+	sleep(2);
+
+	//s->save_state ("");
+
+	SessionUtils::unload_session(s);
+	SessionUtils::cleanup();
+
+	return 0;
+}
diff --git a/session_utils/export.cc b/session_utils/export.cc
new file mode 100644
index 0000000..e7d169a
--- /dev/null
+++ b/session_utils/export.cc
@@ -0,0 +1,235 @@
+#include <iostream>
+#include <cstdlib>
+#include <getopt.h>
+#include <glibmm.h>
+
+#include "common.h"
+
+#include "pbd/basename.h"
+
+#include "ardour/export_handler.h"
+#include "ardour/export_status.h"
+#include "ardour/export_timespan.h"
+#include "ardour/export_channel_configuration.h"
+#include "ardour/export_format_specification.h"
+#include "ardour/export_filename.h"
+#include "ardour/route.h"
+#include "ardour/session_metadata.h"
+#include "ardour/broadcast_info.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace SessionUtils;
+
+static int export_session (Session *session,
+		std::string outfile,
+		std::string samplerate,
+		bool normalize)
+{
+	ExportTimespanPtr tsp = session->get_export_handler()->add_timespan();
+	boost::shared_ptr<ExportChannelConfiguration> ccp = session->get_export_handler()->add_channel_config();
+	boost::shared_ptr<ARDOUR::ExportFilename> fnp = session->get_export_handler()->add_filename();
+	boost::shared_ptr<AudioGrapher::BroadcastInfo> b;
+
+	XMLTree tree;
+
+	tree.read_buffer(std::string(
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+"<ExportFormatSpecification name=\"UTIL-WAV-16\" id=\"14792644-44ab-4209-a4f9-7ce6c2910cac\">"
+"  <Encoding id=\"F_WAV\" type=\"T_Sndfile\" extension=\"wav\" name=\"WAV\" has-sample-format=\"true\" channel-limit=\"256\"/>"
+"  <SampleRate rate=\""+ samplerate +"\"/>"
+"  <SRCQuality quality=\"SRC_SincBest\"/>"
+"  <EncodingOptions>"
+"    <Option name=\"sample-format\" value=\"SF_16\"/>"
+"    <Option name=\"dithering\" value=\"D_None\"/>"
+"    <Option name=\"tag-metadata\" value=\"true\"/>"
+"    <Option name=\"tag-support\" value=\"false\"/>"
+"    <Option name=\"broadcast-info\" value=\"false\"/>"
+"  </EncodingOptions>"
+"  <Processing>"
+"    <Normalize enabled=\""+ (normalize ? "true" : "false") +"\" target=\"0\"/>"
+"    <Silence>"
+"      <Start>"
+"        <Trim enabled=\"false\"/>"
+"        <Add enabled=\"false\">"
+"          <Duration format=\"Timecode\" hours=\"0\" minutes=\"0\" seconds=\"0\" frames=\"0\"/>"
+"        </Add>"
+"      </Start>"
+"      <End>"
+"        <Trim enabled=\"false\"/>"
+"        <Add enabled=\"false\">"
+"          <Duration format=\"Timecode\" hours=\"0\" minutes=\"0\" seconds=\"0\" frames=\"0\"/>"
+"        </Add>"
+"      </End>"
+"    </Silence>"
+"  </Processing>"
+"</ExportFormatSpecification>"
+));
+
+	boost::shared_ptr<ExportFormatSpecification> fmp = session->get_export_handler()->add_format(*tree.root());
+
+	/* set up range */
+	framepos_t start, end;
+	start = session->current_start_frame();
+	end   = session->current_end_frame();
+	tsp->set_range (start, end);
+	tsp->set_range_id ("session");
+
+	/* add master outs as default */
+	IO* master_out = session->master_out()->output().get();
+	if (!master_out) {
+		PBD::warning << _("Export Util: No Master Out Ports to Connect for Audio Export") << endmsg;
+		return -1;
+	}
+
+	for (uint32_t n = 0; n < master_out->n_ports().n_audio(); ++n) {
+		PortExportChannel * channel = new PortExportChannel ();
+		channel->add_port (master_out->audio (n));
+		ExportChannelPtr chan_ptr (channel);
+		ccp->register_channel (chan_ptr);
+	}
+
+	/* output filename */
+	if (outfile.empty ()) {
+		tsp->set_name ("session");
+	} else {
+		std::string dirname = Glib::path_get_dirname (outfile);
+		std::string basename = Glib::path_get_basename (outfile);
+
+		if (basename.size() > 4 && !basename.compare (basename.size() - 4, 4, ".wav")) {
+			basename = PBD::basename_nosuffix (basename);
+		}
+
+		fnp->set_folder(dirname);
+		tsp->set_name (basename);
+	}
+
+	cout << "* Writing " << Glib::build_filename (fnp->get_folder(), tsp->name() + ".wav") << endl;
+
+
+	/* output */
+	fnp->set_timespan(tsp);
+	fnp->include_label = false;
+
+	/* do audio export */
+	fmp->set_soundcloud_upload(false);
+	session->get_export_handler()->add_export_config (tsp, ccp, fmp, fnp, b);
+	session->get_export_handler()->do_export();
+
+	boost::shared_ptr<ARDOUR::ExportStatus> status = session->get_export_status ();
+
+	// TODO trap SIGINT -> status->abort();
+
+	while (status->running) {
+		if (status->normalizing) {
+			double progress = ((float) status->current_normalize_cycle) / status->total_normalize_cycles;
+			printf ("* Normalizing %.1f%%      \r", 100. * progress); fflush (stdout);
+		} else {
+			double progress = ((float) status->processed_frames_current_timespan) / status->total_frames_current_timespan;
+			printf ("* Exporting Audio %.1f%%  \r", 100. * progress); fflush (stdout);
+		}
+		Glib::usleep (1000000);
+	}
+	printf("\n");
+
+	status->finish ();
+
+	printf ("* Done.\n");
+	return 0;
+}
+
+static void usage (int status) {
+	// help2man compatible format (standard GNU help-text)
+	printf ("export - export an ardour session from the commandline.\n\n");
+	printf ("Usage: export [ OPTIONS ] <session-dir> <session-name>\n\n");
+	printf ("Options:\n\
+  -h, --help                 display this help and exit\n\
+  -n, --normalize            normalize signal level (to 0dBFS)\n\
+  -o, --output  <file>       set expected [initial] framerate\n\
+  -s, --samplerate <rate>    samplerate to use (default: 48000)\n\
+  -V, --version              print version information and exit\n\
+\n");
+	printf ("\n\
+The session is exported as 16bit wav.\n\
+If the no output file is given, the session's export dir is used.\n\
+\n");
+
+	printf ("Report bugs to <http://tracker.ardour.org/>\n"
+	        "Website: <http://ardour.org/>\n");
+	::exit (status);
+}
+
+int main (int argc, char* argv[])
+{
+	std::string rate = "48000";
+	std::string outfile;
+	bool normalize = false;
+
+	const char *optstring = "hno:r:V";
+
+	const struct option longopts[] = {
+		{ "help",       0, 0, 'h' },
+		{ "normalize",  0, 0, 'n' },
+		{ "output",     1, 0, 'o' },
+		{ "samplerate", 1, 0, 'r' },
+		{ "version",    0, 0, 'V' },
+	};
+
+	int c = 0;
+	while (EOF != (c = getopt_long (argc, argv,
+					optstring, longopts, (int *) 0))) {
+		switch (c) {
+
+			case 'n':
+				normalize = true;
+				break;
+
+			case 'o':
+				outfile = optarg;
+				break;
+
+			case 's':
+				{
+					const int sr = atoi (optarg);
+					if (sr >= 8000 && sr <= 192000) {
+						stringstream ss;
+						ss << sr;
+						rate = ss.str();
+					} else {
+						fprintf(stderr, "Invalid Samplerate\n");
+					}
+				}
+				break;
+
+			case 'V':
+				printf ("ardour-utils version %s\n\n", VERSIONSTRING);
+				printf ("Copyright (C) GPL 2015 Robin Gareus <robin at gareus.org>\n");
+				exit (0);
+				break;
+
+			case 'h':
+				usage (0);
+				break;
+
+			default:
+					usage (EXIT_FAILURE);
+					break;
+		}
+	}
+
+	if (optind + 2 > argc) {
+		usage (EXIT_FAILURE);
+	}
+
+	SessionUtils::init();
+	Session* s = 0;
+
+	s = SessionUtils::load_session (argv[optind], argv[optind+1]);
+
+	export_session (s, outfile, rate, normalize);
+
+	SessionUtils::unload_session(s);
+	SessionUtils::cleanup();
+
+	return 0;
+}
diff --git a/session_utils/run b/session_utils/run
new file mode 100755
index 0000000..1abec31
--- /dev/null
+++ b/session_utils/run
@@ -0,0 +1,6 @@
+#!/bin/sh
+TOP=`dirname "$0"`/..
+. "$TOP/build/gtk2_ardour/ardev_common_waf.sh"
+SELF=$1
+shift
+exec "$TOP/build/session_utils/$SELF" "$@"
diff --git a/session_utils/wscript b/session_utils/wscript
new file mode 100644
index 0000000..a001fb9
--- /dev/null
+++ b/session_utils/wscript
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+from waflib.extras import autowaf as autowaf
+from waflib import Options, TaskGen
+import waflib.Logs as Logs, waflib.Utils as Utils
+import os
+import shutil
+import sys
+import re
+import time
+from waflib.Task import Task
+
+# Mandatory variables
+top = '.'
+out = 'build'
+
+def options(opt):
+    autowaf.set_options(opt)
+
+def configure(conf):
+    if not "dummy" in conf.env['BACKENDS']:
+        print ('session-utils depend on the dummy backend.')
+        autowaf.display_msg(conf, 'build session-utils', 'no')
+        return
+    # no wine
+    if Options.options.windows_vst and Options.options.dist_target != 'mingw':
+        autowaf.display_msg(conf, 'build session-utils', 'no')
+        return
+    autowaf.display_msg(conf, 'build session-utils', 'yes')
+    conf.load('misc')
+    conf.load('compiler_cxx')
+    autowaf.configure(conf)
+
+def build_ardour_util(bld, util):
+    pgmprefix = bld.env['PROGRAM_NAME'].lower() + str(bld.env['MAJOR'])
+
+    # just the normal executable version of the GTK GUI
+    obj = bld (features = 'cxx c cxxprogram')
+    # this program does not do the whole hidden symbols thing
+    obj.cxxflags = [ '-fvisibility=default' ]
+    obj.source   = ['common.cc', util + '.cc' ]
+    obj.target   = pgmprefix + '-' + util
+    obj.includes = ['.']
+    obj.use      = [ 'libpbd',
+                     'libardour',
+                     'libardour_cp',
+                     'libtimecode',
+                     'libmidipp',
+                     ]
+    obj.defines = [
+        'VERSIONSTRING="' + str(bld.env['VERSION']) + '"',
+        'DATA_DIR="'   + os.path.normpath(bld.env['DATADIR']) + '"',
+        'CONFIG_DIR="' + os.path.normpath(bld.env['SYSCONFDIR']) + '"',
+        'LOCALEDIR="'  + os.path.join(os.path.normpath(bld.env['DATADIR']), 'locale') + '"',
+        'PACKAGE="'    + "ARDOURUTILS" + '"',
+        ]
+    obj.install_path = bld.env['LIBDIR'] + '/utils'
+    obj.uselib       = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD OGG CURL DL'
+    obj.uselib       += ' FFTW3F'
+    obj.uselib       += ' AUDIOUNITS OSX LO '
+    obj.uselib       += ' TAGLIB '
+
+    if sys.platform == 'darwin':
+        obj.uselib += ' AUDIOUNITS OSX'
+        obj.use    += ' libappleutility'
+    obj.includes += ['../libs']
+
+    if bld.env['build_target'] == 'mingw':
+        if bld.env['DEBUG'] == False:
+            obj.linkflags = ['-mwindows']
+
+    if bld.is_defined('NEED_INTL'):
+        obj.linkflags = ' -lintl'
+
+
+def build(bld):
+    VERSION = "%s.%s" % (bld.env['MAJOR'], bld.env['MINOR'])
+    # session-utils depend on the dummy backend
+    if not "dummy" in bld.env['BACKENDS']:
+        return
+    # no wine
+    if bld.is_defined('WINDOWS_VST_SUPPORT') and bld.env['build_target'] != 'mingw':
+        return
+
+    # don't build/install windows version just yet.
+    # tools/x-win/package.sh uses 'waf install'. The symlinks
+    # and shell wrapper script won't work on windows.
+    if bld.env['build_target'] == 'mingw':
+        return
+
+    pgmprefix = bld.env['PROGRAM_NAME'].lower() + str(bld.env['MAJOR'])
+
+    utils = bld.path.ant_glob('*.cc', excl=['example.cc', 'common.cc'])
+
+    for util in utils:
+        fn = str(util)[:-3]
+        build_ardour_util(bld, fn)
+        bld.symlink_as(bld.env['BINDIR'] + '/' + pgmprefix + "-" + fn, bld.env['LIBDIR'] + '/utils/ardour-util.sh')
+
+    obj              = bld(features = 'subst')
+    obj.source       = 'ardour-util.sh.in'
+    obj.target       = 'ardour-util.sh'
+    obj.chmod        = Utils.O755
+    obj.install_path = bld.env['LIBDIR']  + '/utils'
+    obj.LIBDIR       = os.path.normpath(bld.env['DLLDIR'])
+    obj.DATADIR      = os.path.normpath(bld.env['DATADIR'])
+    obj.CONFDIR      = os.path.normpath(bld.env['CONFDIR'])
diff --git a/templates/wscript b/templates/wscript
index 3ea6c4a..ab7e8d0 100644
--- a/templates/wscript
+++ b/templates/wscript
@@ -8,9 +8,9 @@
 # the user's hardware configuration. This makes any pre-existing
 # templates potentially wrong/useless/annoying for anyone who
 # uses a different hardware input configuration than was used
-# to create the templates. 
+# to create the templates.
 #
-# Templates should be created by the user, not by us. 
+# Templates should be created by the user, not by us.
 #
 # I modified the code below, but have not tested it. For now
 # this directory will be removed from the top level wscript's
diff --git a/tools/as-metainfo.its b/tools/as-metainfo.its
new file mode 100644
index 0000000..d2530d4
--- /dev/null
+++ b/tools/as-metainfo.its
@@ -0,0 +1,8 @@
+<its:rules
+  xmlns:its="http://www.w3.org/2005/11/its"
+  version="1.0">
+  <its:translateRule translate="no" selector="/component"/>
+  <its:translateRule translate="yes"
+    selector="/component/name | /component/summary |
+              /component/description | /component/screenshots/screenshot/caption | /component/developer_name"/>
+</its:rules>
diff --git a/tools/gccabicheck/wscript b/tools/gccabicheck/wscript
index 43eb705..ecef5c6 100644
--- a/tools/gccabicheck/wscript
+++ b/tools/gccabicheck/wscript
@@ -20,3 +20,4 @@ def build(bld):
     obj.target = 'gcc-glibmm-abi-check'
     obj.name = 'gcc-glibmm-abi-check'
     obj.lib = 'dl'
+    obj.install_path = None
diff --git a/tools/linux_packaging/ardour.sh.in b/tools/linux_packaging/ardour.sh.in
index 4402fd4..a6bd679 100644
--- a/tools/linux_packaging/ardour.sh.in
+++ b/tools/linux_packaging/ardour.sh.in
@@ -2,19 +2,18 @@
 
 # This is Linux-specific startup script for a bundled version of Ardour
 
-ARGS=""
+checkdebug(){
+    for arg in "$@"
+        do
+            case "$arg" in
+                --gdb )
+                    DEBUG="T"
+            esac
+        done
+}
 
-while [ $# -gt 0 ] ; do
-	case $1 in
+checkdebug "$@"
 
-	--debug)
-		DEBUG="T";
-		shift ;;
-	*)
-		ARGS=$ARGS$1" ";
-		shift; ;;
-	esac
-done
 
 # LD_LIBRARY_PATH needs to be set here so that epa can swap between the original and the bundled version
 # (the original one will be stored in PREBUNDLE_ENV)
@@ -48,8 +47,5 @@ if [ "T" = "$DEBUG" ]; then
 	export ARDOUR_INSIDE_GDB=1
 	exec gdb $INSTALL_DIR/bin/%EXENAME%-%VER%
 else
-	exec $INSTALL_DIR/bin/%EXENAME%-%VER% $ARGS
+	exec %WINE% $INSTALL_DIR/bin/%EXENAME%-%VER% "$@"
 fi
-
-
-
diff --git a/tools/linux_packaging/build b/tools/linux_packaging/build
index ff78849..f25cd2f 100755
--- a/tools/linux_packaging/build
+++ b/tools/linux_packaging/build
@@ -33,6 +33,7 @@ EXTERNAL_JACK=
 VENDOR=Ardour ;
 EXENAME=ardour
 GCC5ABI=false
+USEWINE=false
 BUILDTYPE=""
 NOSTRIP="libsuil|libserd|libsord|liblilv|libsratom|liblrdf|libardour|libpbd|libevoral"
 
@@ -237,12 +238,25 @@ fi
 echo export 'PATH=/usr/local/bin:/opt/bin:$PATH' >> $ENVIRONMENT
 
 # create startup helper script
+if test -d $BUILD_ROOT/vst; then
+	WINEEXE=wine
+	USEWINE=true
+	echo export INSTALL_DIR >> $ENVIRONMENT
+else
+	WINEEXE=
+fi
 
-sed -e "/^%ENV%/r $ENVIRONMENT" -e '/^%ENV%/d' -e 's/%VER%/'"${release_version}"'/;s/%EXENAME%/'"${EXENAME}"'/' < ardour.sh.in > $APPBIN/${EXENAME}${major_version}
+sed -e "/^%ENV%/r $ENVIRONMENT" -e '/^%ENV%/d' -e 's/%VER%/'"${release_version}"'/;s/%EXENAME%/'"${EXENAME}"'/;s/%WINE%/'"$WINEEXE"'/' < ardour.sh.in > $APPBIN/${EXENAME}${major_version}
 rm $ENVIRONMENT && chmod 775 $APPBIN/${EXENAME}${major_version}
 
 echo "Copying ardour executable ...."
-cp -v $BUILD_ROOT/gtk2_ardour/ardour-${release_version} $APPBIN/${EXENAME}-${release_version}
+if test -d $BUILD_ROOT/vst; then
+	#cp -v $BUILD_ROOT/gtk2_ardour/libgtk2_ardour.so $APPLIB/
+	cp -v $BUILD_ROOT/gtk2_ardour/ardour-${release_version}-vst.exe.so $APPBIN/${EXENAME}-${release_version}
+else
+	cp -v $BUILD_ROOT/gtk2_ardour/ardour-${release_version}* $APPBIN/${EXENAME}-${release_version}
+fi
+
 if test x$STRIP = xall ; then
 	strip -s $APPBIN/${EXENAME}-${release_version}
 fi
@@ -426,7 +440,7 @@ if test -f $BUILD_ROOT/libs/ardouralsautil/ardour-request-device; then
 fi
 
 OURLIBDIR=$BUILD_ROOT/libs
-OURLIBS=$OURLIBDIR/vamp-sdk:$OURLIBDIR/surfaces/control_protocol:$OURLIBDIR/ardour:$OURLIBDIR/midi++2:$OURLIBDIR/pbd:$OURLIBDIR/rubberband:$OURLIBDIR/soundtouch:$OURLIBDIR/gtkmm2ext:$OURLIBDIR/sigc++2:$OURLIBDIR/glibmm2:$OURLIBDIR/gtkmm2/atk:$OURLIBDIR/gtkmm2/pango:$OURLIBDIR/gtkmm2/gdk:$OURLIBDIR/gtkmm2/gtk:$OURLIBDIR/canvas:$OURLIBDIR/libsndfile:$OURLIBDIR/evoral:$OURLIBDIR/evoral/src/libsmf:$OURLIBDIR/audiographer:$OURLIBDIR/timecode:$OURLIBDIR/taglib:$OURLIBDIR/libltc:$OURLIBDIR/qm-dsp:$OURLIBDIR/ardouralsautil:$OURLIBDIR/ptformat
+OURLIBS=$OURLIBDIR/vamp-sdk:$OURLIBDIR/surfaces/control_protocol:$OURLIBDIR/ardour:$OURLIBDIR/midi++2:$OURLIBDIR/pbd:$OURLIBDIR/rubberband:$OURLIBDIR/soundtouch:$OURLIBDIR/gtkmm2ext:$OURLIBDIR/sigc++2:$OURLIBDIR/glibmm2:$OURLIBDIR/gtkmm2/atk:$OURLIBDIR/gtkmm2/pango:$OURLIBDIR/gtkmm2/gdk:$OURLIBDIR/gtkmm2/gtk:$OURLIBDIR/canvas:$OURLIBDIR/libsndfile:$OURLIBDIR/evoral:$OURLIBDIR/evoral/src/libsmf:$OURLIBDIR/audiographer:$OURLIBDIR/timecode:$OURLIBDIR/taglib:$OURLIBDIR/libltc:$OURLIBDIR/qm-dsp:$OURLIBDIR/ardouralsautil:$OURLIBDIR/ptformat:$BUILD_ROOT/gtk2_ardour
 
 echo $OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
 
@@ -455,8 +469,8 @@ while [ true ] ; do
 		# ignore suil/qt wrappers - the plugin will pull in QT4.
 		if echo $file | grep -qs 'libsuil_.*qt4' ; then continue; fi
 
-		# do not include libjack
-		deps=`LD_LIBRARY_PATH=$OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} ldd $file | awk '{print $3}'`
+		# do not include libjack, nor libwine
+		deps=`LD_LIBRARY_PATH=$OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} ldd $file | grep -v libwine.so | awk '{print $3}'`
 
 		echo -n "."
 		for dep in $deps ; do
@@ -596,7 +610,7 @@ if test x$WITH_HARRISON_LV2 != x ; then
 	curl -s -S --fail -# \
 		-z "${CACHEDIR}/harrison_lv2s.${HARCH}.zip" \
 		-o "${CACHEDIR}/harrison_lv2s.${HARCH}.zip" \
-		http://www.harrisonconsoles.com/mixbus/mb3/${HARCH}/harrison_lv2s.zip
+		"http://www.harrisonconsoles.com/mixbus/mb3/beta/harrison-dsp/harrison_lv2s.${HARCH}.zip"
 	unzip -q -d "$APPLIB/LV2/" "${CACHEDIR}/harrison_lv2s.${HARCH}.zip"
 fi
 
@@ -607,7 +621,7 @@ if test -n "$MIXBUS"; then
 	curl -s -S --fail -# \
 		-z "${CACHEDIR}/harrison_channelstrip.${HARCH}.so" \
 		-o "${CACHEDIR}/harrison_channelstrip.${HARCH}.so" \
-		http://www.harrisonconsoles.com/mixbus/mb3/${HARCH}/harrison_channelstrip.so
+		"http://www.harrisonconsoles.com/mixbus/mb3/beta/harrison-dsp/harrison_channelstrip.${HARCH}.so"
 
 	cp "${CACHEDIR}/harrison_channelstrip.${HARCH}.so" \
 		$APPLIB/ladspa/strip/harrison_channelstrip.so
@@ -670,7 +684,7 @@ chmod a+x $APPBIN/${APP_VER_NAME}.uninstall.sh
 #
 # Add the stage2.run script
 #
-sed -e "s/%REPLACE_MAJOR_VERSION%/${major_version}/;s/%REPLACE_PGM%/${APPNAME}/;s/%REPLACE_VENDOR%/${VENDOR}/;s/%REPLACE_EXE%/${EXENAME}/;s/%REPLACE_GCC5%/${GCC5ABI}/" < stage2.run.in > stage2.run
+sed -e "s/%REPLACE_MAJOR_VERSION%/${major_version}/;s/%REPLACE_PGM%/${APPNAME}/;s/%REPLACE_VENDOR%/${VENDOR}/;s/%REPLACE_EXE%/${EXENAME}/;s/%REPLACE_GCC5%/${GCC5ABI}/;s/%REPLACE_WINE%/${USEWINE}/" < stage2.run.in > stage2.run
 chmod a+x stage2.run
 
 
diff --git a/tools/linux_packaging/package b/tools/linux_packaging/package
index a32de23..3614df1 100755
--- a/tools/linux_packaging/package
+++ b/tools/linux_packaging/package
@@ -9,6 +9,7 @@ BUILDTYPE=""
 SINGLE_ARCH="F"
 X86_BUNDLE_OK="F"
 X86_64_BUNDLE_OK="F"
+GCC5ABI="F"
 MAKESELF=""
 BUILD_ROOT=../../build
 
@@ -45,7 +46,7 @@ while [ $# -gt 0 ] ; do
 
 	--singlearch) SINGLE_ARCH="T" ; shift ;;
 
-	--gcc5abi) shift ;;
+	--gcc5abi) GCC5ABI="T" ; shift ;;
 
 	*)
 		#catch all for unknown arguments
@@ -138,6 +139,9 @@ else
 	fi
 fi 
 
+if [ "$GCC5ABI" = "T" ]; then
+	PACKAGE="${PACKAGE}-gcc5"
+fi
 
 echo "Cleaning up any old package files for this build"
 #Get rid of any old packages of this same name.
diff --git a/tools/linux_packaging/stage2.run.in b/tools/linux_packaging/stage2.run.in
index 4b6cb72..0d93f77 100755
--- a/tools/linux_packaging/stage2.run.in
+++ b/tools/linux_packaging/stage2.run.in
@@ -229,42 +229,6 @@ case `uname -m` in
 		;;
 esac
 
-#############################
-# Determine C11 stdlibc++ ABI
-#############################
-
-if %REPLACE_GCC5%; then
-	# Ardour was compiled with gcc5, warn on gcc4 systems
-	if ! ${NORM_USER} "${PKG_PATH}/.gcc-glibmm-abi-check --gcc5 > /dev/null"; then
-		echo ""
-		echo "WARNING: GCC4/5 libstdc++ ABI Mismatch"
-		echo ""
-		echo "Ardour was compiled with gcc5, your system uses an older version of the"
-		echo "standard c++ library. Plugins on your system may not load or plugin-UIs"
-		echo "may cause crashes."
-		echo ""
-		ANSWER=$(VaildateYesNoQuestion "Continue anyway?")
-		if test "n" = $ANSWER; then
-			exit 1
-		fi
-	fi
-else
-	# Ardour was compiled with gcc4, warn on gcc5 systems
-	if ! ${NORM_USER} "${PKG_PATH}/.gcc-glibmm-abi-check --gcc4 > /dev/null"; then
-		echo ""
-		echo "WARNING: GCC4/5 libstdc++ ABI Mismatch"
-		echo ""
-		echo "Ardour was compiled with gcc4, your system uses a newer version of the"
-		echo "standard c++ library. Plugins on your system may not load or plugin-UIs"
-		echo "may cause crashes."
-		echo ""
-		ANSWER=$(VaildateYesNoQuestion "Continue anyway?")
-		if test "n" = $ANSWER; then
-			exit 1
-		fi
-	fi
-fi
-
 ####################
 # Check disk space
 ####################
@@ -313,13 +277,62 @@ else
 	fi
 fi
 
-FILESYSTEM_TYPE=$(df -P -T "${PKG_PATH}" | grep / | awk '{print $2}')
-echo "Bundle is on ${FILESYSTEM_TYPE} filesystem"
+#############################
+# Determine C11 stdlibc++ ABI
+#############################
+
+if %REPLACE_GCC5%; then
+	# Ardour was compiled with gcc5, warn on gcc4 systems
+	if ! ${NORM_USER} "${PKG_PATH}/.gcc-glibmm-abi-check --gcc5 > /dev/null"; then
+		echo ""
+		echo "WARNING: GCC4/5 libstdc++ ABI Mismatch"
+		echo ""
+		echo "${PGM_NAME} was compiled with gcc5, your system uses an older version of the"
+		echo "standard c++ library. Plugins on your system may not load or plugin-UIs"
+		echo "may cause crashes."
+		echo ""
+		ANSWER=$(VaildateYesNoQuestion "Continue anyway?")
+		if test "n" = $ANSWER; then
+			exit 1
+		fi
+	fi
+else
+	# Ardour was compiled with gcc4, warn on gcc5 systems
+	if ! ${NORM_USER} "${PKG_PATH}/.gcc-glibmm-abi-check --gcc4 > /dev/null"; then
+		echo ""
+		echo "WARNING: GCC4/5 libstdc++ ABI Mismatch"
+		echo ""
+		echo "${PGM_NAME} was compiled with gcc4, your system uses a newer version of the"
+		echo "standard c++ library. Plugins on your system may not load or plugin-UIs"
+		echo "may cause crashes."
+		echo ""
+		ANSWER=$(VaildateYesNoQuestion "Continue anyway?")
+		if test "n" = $ANSWER; then
+			exit 1
+		fi
+	fi
+fi
+
+if %REPLACE_WINE%; then
+	if test -z "`which wine`"; then
+		echo ""
+		echo "!!! ERROR !!! - 'wine' was not found."
+		echo ""
+		echo "This version of ${PGM_NAME} with Windows VST support requires wine."
+		echo "https://www.winehq.org/"
+		echo ""
+		read -p "Press ENTER to exit installer:" BLAH
+		exit 1
+	fi
+fi
 
 #####################
 # Unpack the bundle
 #####################
 
+FILESYSTEM_TYPE=$(df -P -T "${PKG_PATH}" | grep / | awk '{print $2}')
+echo "Bundle is on ${FILESYSTEM_TYPE} filesystem"
+
 # untar the correct bundle for us to install
 echo "Unpacking bundle for $ARCH"
 
@@ -376,6 +389,46 @@ then
 fi
 
 #################################################
+# Set up libwine.so
+#################################################
+if %REPLACE_WINE%; then
+	echo ""
+	echo "Searching libwine.so (Windows VST support)"
+	# we need to add libwine to ardour's LD_LIBRARY_PATH
+	# libwine itself includes paths to the various system-components
+	# which may be different on each platform.
+	#
+	# There's some chicken/egg here: ardour.exe.so is linked against libwine.so
+	# at build-time. wine/wineloader assumes a windows-application (which does not use libwine
+	# directly) and does not set up the LD path to libwine itself. the application terminates
+	# (missing libs) before it even starts..
+	#
+	# wine itself does not provide means to find the location of libwine.
+	# /usr/bin/wine is usually shell-script and libwine.so can be found in
+	# various places on different distros.
+	#
+	# if this check were quick and easy.. it should be done in the startup-script, but it's not
+	# so here we go... (updating wine may require re-installing ardour)
+	#
+	LIBWINE=$(
+		LD_DEBUG=files wine `pwd`/${BUNDLE_DIR}/lib/ardour-vst-scanner.exe.so 2>&1 \
+						 | grep -e "calling init:.*libwine" \
+						 | sed 's/^.*calling init: //' \
+						 | uniq \
+			)
+	if ! test -f "$LIBWINE"; then
+		echo ""
+		echo "!!! ERROR !!! - 'libwine.so*' was not found."
+		echo ""
+		read -p "Press ENTER to exit installer:" BLAH
+		exit 1
+	fi
+	echo "Using: $LIBWINE"
+  # this replaces/overwrites the bundled libwine
+	cp -L "$LIBWINE" `pwd`/${BUNDLE_DIR}/lib/libwine.so.1
+fi
+
+#################################################
 # Check if system libs are OK (libc, etc)
 #################################################
 
diff --git a/tools/linux_packaging/uninstall.sh.in b/tools/linux_packaging/uninstall.sh.in
index 20aa1b6..606a28f 100644
--- a/tools/linux_packaging/uninstall.sh.in
+++ b/tools/linux_packaging/uninstall.sh.in
@@ -148,6 +148,7 @@ then
 		${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}
+		${SUPER} xdg-icon-resource uninstall --size 256 ${ICON_NAME}
 
 		if [ -e /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg ]; 
 		then
diff --git a/tools/osx_packaging/osx_build b/tools/osx_packaging/osx_build
index 7d21eb4..5e4a1a6 100755
--- a/tools/osx_packaging/osx_build
+++ b/tools/osx_packaging/osx_build
@@ -594,7 +594,7 @@ if test x$WITH_HARRISON_LV2 != x ; then
 	curl -s -S --fail -#  \
 		-z "${CACHEDIR}/harrison_lv2s.${OSX_BENSID}.zip" \
 		-o "${CACHEDIR}/harrison_lv2s.${OSX_BENSID}.zip" \
-		http://www.harrisonconsoles.com/mixbus/mb3/${OSX_BENSID}/harrison_lv2s.zip
+		"http://www.harrisonconsoles.com/mixbus/mb3/beta/harrison-dsp/harrison_lv2s.${OSX_BENSID}.zip"
 
 	mkdir -p "${PRODUCT_PKG_DIR}/${APPROOT}/lib/LV2"
 	bsdtar -C "${PRODUCT_PKG_DIR}/${APPROOT}/lib/LV2/" -xf \
@@ -680,7 +680,7 @@ if test -n "$MIXBUS"; then
 	curl -s -S --fail -#  \
 		-z "${CACHEDIR}/harrison_channelstrip.${OSX_BENSID}.so" \
 		-o "${CACHEDIR}/harrison_channelstrip.${OSX_BENSID}.so" \
-		http://www.harrisonconsoles.com/mixbus/mb3/${OSX_BENSID}/harrison_channelstrip.so
+		"http://www.harrisonconsoles.com/mixbus/mb3/beta/harrison-dsp/harrison_channelstrip.${OSX_BENSID}.so"
 
 	cp "${CACHEDIR}/harrison_channelstrip.${OSX_BENSID}.so" \
 		"${PRODUCT_PKG_DIR}/${APPROOT}/lib/ladspa/strip/harrison_channelstrip.so"
diff --git a/tools/run-threadreadtest.sh b/tools/run-threadreadtest.sh
new file mode 100755
index 0000000..76e177a
--- /dev/null
+++ b/tools/run-threadreadtest.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+dir=/tmp
+filesize=100 # megabytes
+numfiles=128
+nocache=
+interleave=
+needfiles=1
+write_blocksize=262144
+args=
+
+if uname -a | grep --silent arwin ; then
+    ddmega=m
+else
+    ddmega=M
+fi
+
+while [ $# -gt 1 ] ; do
+    case $1 in
+	-d) dir=$2; shift; shift ;;
+	-f) filesize=$2; shift; shift ;;
+	-n) numfiles=$2; shift; shift ;;
+	-M) args="$args -M"; shift ;;
+	-D) args="$args -D"; shift ;;
+	-R) args="$args -R"; shift ;;
+        *) break ;;
+    esac
+done
+
+if [ -d $dir -a -f $dir/testfile_1 ] ; then
+    # dir exists and has a testfile within it - reuse to avoid
+    # recreating files
+    echo "# Re-using files in $dir"
+    needfiles=
+else
+    dir=$dir/readtest_$$
+    mkdir $dir
+    
+    if [ $? != 0 ] ; then
+	echo "Cannot create testfile directory $dir"
+	exit 1
+    fi
+fi
+
+if [ x$needfiles != x ] ; then
+    echo "# Building files for test..."
+    if [ x$interleave = x ] ; then
+	
+	#
+	# Create all files sequentially
+	#
+	
+	for i in `seq 1 $numfiles` ; do
+	    dd of=$dir/testfile_$i if=/dev/zero bs=1$ddmega count=$filesize >/dev/null 2>&1
+	done
+    else
+	
+	#
+	# Create files interleaved, adding $write_blocksize to each
+	# file in turn.
+	#
+	
+	size=0
+	limit=`expr $filesize * 1048576`
+	while [ $size -lt $limit ] ; do
+	    for i in `seq 1 $numfiles` ; do
+		dd if=/dev/zero bs=$write_blocksize count=1 >> $dir/testfile_$i 2>/dev/null
+	    done
+	    size=`expr $size + $write_blocksize`
+	done
+    fi
+fi
+
+for bs in $@ ; do
+
+    if uname -a | grep --silent arwin ; then
+        # clears cache on OS X
+        sudo purge
+    elif [ -f /proc/sys/vm/drop_caches ] ; then
+        # Linux cache clearing
+        echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null
+    else       
+        # need an alternative for other operating systems
+        :
+    fi
+    
+    echo "# Blocksize $bs"
+    ./thread_readtest $args -b $bs -q $dir/testfile_%d
+done
diff --git a/tools/thread_readtest.cc b/tools/thread_readtest.cc
new file mode 100644
index 0000000..82e461b
--- /dev/null
+++ b/tools/thread_readtest.cc
@@ -0,0 +1,386 @@
+/* g++ -o thread_readtest thread_readtest.cc `pkg-config --cflags --libs glibmm-2.4` -lm */
+
+#ifndef _WIN32
+#  define HAVE_MMAP
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <math.h>
+
+#undef HAVE_MMAP
+#ifdef HAVE_MMAP
+#  include <sys/stat.h>
+#  include <sys/mman.h>
+#endif
+
+#include <glibmm.h>
+
+char* data = 0;
+
+void
+usage ()
+{
+	fprintf (stderr, "thread_readtest [ -b BLOCKSIZE ] [ -l FILELIMIT] [ -n NTHREADS ] [ -D ] [ -R ] [ -M ] filename-template\n");
+}
+
+Glib::Threads::Cond pool_run;
+Glib::Threads::Cond pool_done;
+Glib::Threads::Mutex pool_lock;
+std::list<int> pool_work;
+std::vector<Glib::Threads::Thread*> thread_pool;
+int pool_errors = 0;
+bool thread_pool_lives = true;
+
+struct ThreadData {
+	int id;
+	char *data;
+	size_t block_size;
+};
+
+void
+thread_pool_work (ThreadData* td)
+{
+	Glib::Threads::Mutex::Lock lm (pool_lock);
+
+	while (thread_pool_lives) {
+		pool_run.wait (pool_lock);
+
+		if (!thread_pool_lives) {
+			return;
+		}
+
+		/* we're awake ... get some work */
+
+		while (!pool_work.empty()) {
+
+			int file_descriptor = pool_work.front ();
+			pool_work.pop_front ();
+
+			/* release the lock while we do work */
+
+			lm.release ();
+
+			/* do the work */
+
+			int err = 0;
+
+			ssize_t nread;
+
+		  again:
+			if ((nread = ::read (file_descriptor, td->data, td->block_size)) != td->block_size) {
+				if (nread != 0 && errno == EAGAIN) {
+					fprintf (stderr, "read requires retry\n");
+					goto again;
+				}
+				if (nread != 0) {
+					fprintf (stderr, "thread %d has error = %s\n", td->id, strerror (errno));
+				}
+				err++;
+			}
+
+			/* reacquire lock so that we can check the status of
+			 * things and possibly wake the master.
+			 */
+
+			lm.acquire ();
+			pool_errors += err;
+
+			if (pool_work.empty()) {
+				/* work is finished, tell the master */
+				pool_done.signal ();
+			}
+		}
+
+	}
+
+	return;
+}
+
+void
+stop_thread_pool ()
+{
+	{
+		Glib::Threads::Mutex::Lock lm (pool_lock);
+		thread_pool_lives = false;
+		pool_work.clear ();
+		pool_run.broadcast ();
+	}
+
+	/* XXX wait for each thread to finish */
+}
+
+void
+build_thread_pool (int nthreads, size_t block_size)
+{
+	for (int n = 0; n < nthreads; ++n) {
+		ThreadData* td = new ThreadData;
+		td->data = (char*) malloc (sizeof (char) * block_size);
+		td->block_size = block_size;
+		td->id = n;
+
+		thread_pool.push_back (Glib::Threads::Thread::create (sigc::bind (sigc::ptr_fun (thread_pool_work), td)));
+	}
+}
+
+int
+run_thread_pool (int* files, int nfiles)
+{
+	Glib::Threads::Mutex::Lock lm (pool_lock);
+
+	/* Queue up all the files */
+	for (int n = 0; n < nfiles; ++n) {
+		pool_work.push_back (files[n]);
+	}
+
+	pool_errors = 0;
+
+	/* wake everybody up */
+	pool_run.broadcast ();
+
+	/* wait for everyone to finish */
+
+	pool_done.wait (pool_lock);
+
+	if (pool_errors) {
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+main (int argc, char* argv[])
+{
+	int* files;
+	char optstring[] = "b:DRMl:q";
+	uint32_t block_size = 64 * 1024 * 4;
+	int max_files = -1;
+	int nthreads = 16;
+#ifdef __APPLE__
+	int direct = 0;
+	int noreadahead = 0;
+#endif
+#ifdef HAVE_MMAP
+	int use_mmap = 0;
+	void  **addr;
+	size_t *flen;
+#endif
+	const struct option longopts[] = {
+		{ "blocksize", 1, 0, 'b' },
+		{ "direct", 0, 0, 'D' },
+		{ "mmap", 0, 0, 'M' },
+		{ "noreadahead", 0, 0, 'R' },
+		{ "limit", 1, 0, 'l' },
+		{ "nthreads", 16, 0, 'n' },
+		{ 0, 0, 0, 0 }
+	};
+
+	int option_index = 0;
+	int c = 0;
+	char const * name_template = 0;
+	int flags = O_RDONLY;
+	int n = 0;
+	int nfiles = 0;
+	int quiet = 0;
+
+	while (1) {
+		if ((c = getopt_long (argc, argv, optstring, longopts, &option_index)) == -1) {
+			break;
+		}
+
+		switch (c) {
+		case 'b':
+			block_size = atoi (optarg);
+			break;
+		case 'l':
+			max_files = atoi (optarg);
+			break;
+		case 'D':
+#ifdef __APPLE__
+			direct = 1;
+#endif
+			break;
+		case 'M':
+#ifdef HAVE_MMAP
+			use_mmap = 1;
+#endif
+			break;
+		case 'R':
+#ifdef __APPLE__
+			noreadahead = 1;
+#endif
+			break;
+		case 'q':
+			quiet = 1;
+			break;
+		case 'n':
+			nthreads = atoi (optarg);
+			break;
+		default:
+			usage ();
+			return 0;
+		}
+	}
+
+	if (optind < argc) {
+		name_template = argv[optind];
+	} else {
+		usage ();
+		return 1;
+	}
+
+	while (1) {
+		char path[PATH_MAX+1];
+
+		snprintf (path, sizeof (path), name_template, n+1);
+
+		if (access (path, R_OK) != 0) {
+			break;
+		}
+
+		++n;
+
+		if (max_files > 0 &&  n >= max_files) {
+			break;
+		}
+	}
+
+	if (n == 0) {
+		fprintf (stderr, "No matching files found for %s\n", name_template);
+		return 1;
+	}
+
+	if (!quiet) {
+		printf ("# Discovered %d files using %s\n", n, name_template);
+	}
+
+	nfiles = n;
+	files = (int *) malloc (sizeof (int) * nfiles);
+#ifdef HAVE_MMAP
+	if (use_mmap) {
+		if (!quiet) {
+			printf ("# Using mmap().\n");
+		}
+		addr = malloc (sizeof (void*) * nfiles);
+		flen = (size_t*) malloc (sizeof (size_t) * nfiles);
+	}
+#endif
+
+	for (n = 0; n < nfiles; ++n) {
+
+		char path[PATH_MAX+1];
+		int fd;
+
+		snprintf (path, sizeof (path), name_template, n+1);
+
+		if ((fd = open (path, flags, 0644)) < 0) {
+			fprintf (stderr, "Could not open file #%d @ %s (%s)\n", n, path, strerror (errno));
+			return 1;
+		}
+
+#ifdef __APPLE__
+		if (direct) {
+			/* Apple man pages say only that it returns "a value other than -1 on success",
+				 which probably means zero, but you just can't be too careful with
+				 those guys.
+				 */
+			if (fcntl (fd, F_NOCACHE, 1) == -1) {
+				fprintf (stderr, "Cannot set F_NOCACHE on file #%d\n", n);
+			}
+		}
+
+		if (noreadahead) {
+			if (fcntl (fd, F_RDAHEAD, 0) == -1) {
+				fprintf (stderr, "Cannot set F_READAHED on file #%d\n", n);
+			}
+		}
+#endif
+
+		files[n] = fd;
+
+#ifdef HAVE_MMAP
+		if (use_mmap) {
+			struct stat s;
+			if (fstat (fd, & s)) {
+				fprintf (stderr, "Could not stat fd #%d @ %s\n", n, path);
+				return 1;
+			}
+			if (s.st_size < block_size) {
+				fprintf (stderr, "file is shorter than blocksize #%d @ %s\n", n, path);
+				return 1;
+			}
+			flen[n] = s.st_size;
+			addr[n] = mmap (0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+			if (addr[n] == MAP_FAILED) {
+				fprintf (stderr, "Could not mmap file #%d @ %s (%s)\n", n, path, strerror (errno));
+				return 1;
+			}
+		}
+#endif
+	}
+
+	data = (char*) malloc (sizeof (char) * block_size);
+	uint64_t _read = 0;
+	double max_elapsed = 0;
+	double total_time = 0;
+	double var_m = 0;
+	double var_s = 0;
+	uint64_t cnt = 0;
+
+	build_thread_pool (nthreads, block_size);
+
+	while (1) {
+		gint64 before;
+		before = g_get_monotonic_time();
+
+		if (run_thread_pool (files, nfiles)) {
+			fprintf (stderr, "thread pool error\n");
+			goto out;
+		}
+
+		_read += block_size;
+		gint64 elapsed = g_get_monotonic_time() - before;
+		double bandwidth = ((nfiles * block_size)/1048576.0) / (elapsed/1000000.0);
+
+		if (!quiet) {
+			printf ("# BW @ %lu %.3f seconds bandwidth %.4f MB/sec\n", (long unsigned int)_read, elapsed/1000000.0, bandwidth);
+		}
+
+		total_time += elapsed;
+
+		++cnt;
+		if (max_elapsed == 0) {
+			var_m = elapsed;
+		} else {
+			const double var_m1 = var_m;
+			var_m = var_m + (elapsed - var_m) / (double)(cnt);
+			var_s = var_s + (elapsed - var_m) * (elapsed - var_m1);
+		}
+
+		if (elapsed > max_elapsed) {
+			max_elapsed = elapsed;
+		}
+
+	}
+
+out:
+	if (max_elapsed > 0 && total_time > 0) {
+		double stddev = cnt > 1 ? sqrt(var_s / ((double)(cnt-1))) : 0;
+		double bandwidth = ((nfiles * _read)/1048576.0) / (total_time/1000000.0);
+		double min_throughput = ((nfiles * block_size)/1048576.0) / (max_elapsed/1000000.0);
+		printf ("# Min: %.4f MB/sec Avg: %.4f MB/sec  || Max: %.3f sec \n", min_throughput, bandwidth, max_elapsed/1000000.0);
+		printf ("# Max Track count: %d @ 48000SPS\n", (int) floor(1048576.0 * bandwidth / (4 * 48000.)));
+		printf ("# Sus Track count: %d @ 48000SPS\n", (int) floor(1048576.0 * min_throughput / (4 * 48000.)));
+		printf ("# seeks: %llu: bytes: %llu total_time: %f\n", cnt * nfiles, (nfiles * _read), total_time/1000000.0);
+		printf ("%d %.4f %.4f %.4f %.5f\n", block_size, min_throughput, bandwidth, max_elapsed/1000000.0, stddev/1000000.0);
+	}
+
+	return 0;
+}
diff --git a/tools/x-win/package.sh b/tools/x-win/package.sh
index 4088cd8..b16c454 100755
--- a/tools/x-win/package.sh
+++ b/tools/x-win/package.sh
@@ -15,7 +15,7 @@ test -f gtk2_ardour/wscript || exit 1
 : ${ROOT=/home/ardour}
 : ${MAKEFLAGS=-j4}
 : ${TMPDIR=/var/tmp}
-: ${SRCDIR=/var/tmp/winsrc}  # source-code tgz cache
+: ${SRCCACHE=/var/tmp/winsrc}  # source-code tgz cache
 
 # TODO: grep from build/config.log instead
 while [ $# -gt 0 ] ; do
@@ -23,6 +23,8 @@ while [ $# -gt 0 ] ; do
 	case $1 in
 		--mixbus)
 			MIXBUS=1
+			WITH_HARRISON_LV2=1 ;
+			WITH_X42_LV2=1 ;
 			shift ;;
 	esac
 done
@@ -61,7 +63,7 @@ else
 fi
 
 : ${PREFIX=${ROOT}/win-stack-$WARCH}
-export SRCDIR
+export SRCCACHE
 
 if [ "$(id -u)" = "0" ]; then
 	apt-get -y install nsis curl
@@ -70,7 +72,7 @@ fi
 
 function download {
 echo "--- Downloading.. $2"
-test -f ${SRCDIR}/$1 || curl -k -L -o ${SRCDIR}/$1 $2
+test -f ${SRCCACHE}/$1 || curl -k -L -o ${SRCCACHE}/$1 $2
 }
 
 ################################################################################
@@ -186,15 +188,15 @@ if test -z "$NOVIDEOTOOLS"; then
 
 	rsync -a -q --partial \
 		rsync://ardour.org/video-tools/harvid_win-${HARVID_VERSION}.tar.xz \
-		"${SRCDIR}/harvid_win-${HARVID_VERSION}.tar.xz"
+		"${SRCCACHE}/harvid_win-${HARVID_VERSION}.tar.xz"
 
 	rsync -a -q --partial \
 		rsync://ardour.org/video-tools/xjadeo_win-${XJADEO_VERSION}.tar.xz \
-		"${SRCDIR}/xjadeo_win-${XJADEO_VERSION}.tar.xz"
+		"${SRCCACHE}/xjadeo_win-${XJADEO_VERSION}.tar.xz"
 
 	mkdir $DESTDIR/video
-	tar -xf "${SRCDIR}/harvid_win-${HARVID_VERSION}.tar.xz" -C "$DESTDIR/video/"
-	tar -xf "${SRCDIR}/xjadeo_win-${XJADEO_VERSION}.tar.xz" -C "$DESTDIR/video/"
+	tar -xf "${SRCCACHE}/harvid_win-${HARVID_VERSION}.tar.xz" -C "$DESTDIR/video/"
+	tar -xf "${SRCCACHE}/xjadeo_win-${XJADEO_VERSION}.tar.xz" -C "$DESTDIR/video/"
 
 	echo " === unzipped"
 	du -sh $DESTDIR/video
@@ -207,12 +209,12 @@ fi
 ### http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.1/threads-win32/sjlj/x86_64-4.9.1-release-win32-sjlj-rt_v3-rev1.7z
 if ! grep " using ./waf configure" build/config.log | grep -q -- "--optimize"; then
 	download gdb-static-win3264.tar.xz http://robin.linuxaudio.org/gdb-static-win3264.tar.xz
-	cd ${SRCDIR}
+	cd ${SRCCACHE}
 	tar xf gdb-static-win3264.tar.xz
 	cd - > /dev/null
 
 	echo " === Creating debug.bat"
-	cp -r ${SRCDIR}/gdb_$WARCH $DESTDIR/gdb
+	cp -r ${SRCCACHE}/gdb_$WARCH $DESTDIR/gdb
 	cat > $DESTDIR/debug.bat << EOF
 cd bin
 START ..\\gdb\\bin\\gdb.exe -iex "set logging overwrite on" -iex "set height 0" -iex "set logging on %UserProfile%\\${PRODUCT_NAME}-debug.log" -iex "target exec ${PRODUCT_EXE}" -iex "run"
@@ -226,7 +228,7 @@ fi
 
 ################################################################################
 ### Mixbus plugins, etc
-if test -n "$MIXBUS"; then # TODO use separate variable
+if test x$WITH_X42_LV2 != x ; then
 	mkdir -p $ALIBDIR/LV2
 
 	echo "Adding x42 Plugins"
@@ -234,32 +236,32 @@ if test -n "$MIXBUS"; then # TODO use separate variable
 	METERS_VERSION=$(curl -s -S http://x42-plugins.com/x42/win/x42-meters.latest.txt)
 	rsync -a -q --partial \
 		rsync://x42-plugins.com/x42/win/x42-meters-lv2-${WARCH}-${METERS_VERSION}.zip \
-		"${SRCDIR}/x42-meters-lv2-${WARCH}-${METERS_VERSION}.zip"
-	unzip -q -d "$ALIBDIR/LV2/" "${SRCDIR}/x42-meters-lv2-${WARCH}-${METERS_VERSION}.zip"
+		"${SRCCACHE}/x42-meters-lv2-${WARCH}-${METERS_VERSION}.zip"
+	unzip -q -d "$ALIBDIR/LV2/" "${SRCCACHE}/x42-meters-lv2-${WARCH}-${METERS_VERSION}.zip"
 
 	SETBFREE_VERSION=$(curl -s -S http://x42-plugins.com/x42/win/setBfree.latest.txt)
 	rsync -a -q --partial \
 		rsync://x42-plugins.com/x42/win/setBfree-lv2-${WARCH}-${SETBFREE_VERSION}.zip \
-		"${SRCDIR}/setBfree-lv2-${WARCH}-${SETBFREE_VERSION}.zip"
-	unzip -q -d "$ALIBDIR/LV2/" "${SRCDIR}/setBfree-lv2-${WARCH}-${SETBFREE_VERSION}.zip"
+		"${SRCCACHE}/setBfree-lv2-${WARCH}-${SETBFREE_VERSION}.zip"
+	unzip -q -d "$ALIBDIR/LV2/" "${SRCCACHE}/setBfree-lv2-${WARCH}-${SETBFREE_VERSION}.zip"
 
 	MIDIFILTER_VERSION=$(curl -s -S http://x42-plugins.com/x42/win/x42-midifilter.latest.txt)
 	rsync -a -q --partial \
 		rsync://x42-plugins.com/x42/win/x42-midifilter-lv2-${WARCH}-${MIDIFILTER_VERSION}.zip \
-		"${SRCDIR}/x42-midifilter-lv2-${WARCH}-${MIDIFILTER_VERSION}.zip"
-	unzip -q -d "$ALIBDIR/LV2/" "${SRCDIR}/x42-midifilter-lv2-${WARCH}-${MIDIFILTER_VERSION}.zip"
+		"${SRCCACHE}/x42-midifilter-lv2-${WARCH}-${MIDIFILTER_VERSION}.zip"
+	unzip -q -d "$ALIBDIR/LV2/" "${SRCCACHE}/x42-midifilter-lv2-${WARCH}-${MIDIFILTER_VERSION}.zip"
 fi
 
-if test -n "$MIXBUS"; then # TODO use separate variable
+if test x$WITH_HARRISON_LV2 != x ; then
 	mkdir -p $ALIBDIR/LV2
 
 	echo "Including Harrison LV2s"
 
 	curl -s -S --fail -# \
-		-z "${SRCDIR}/harrison_lv2s.${WARCH}.zip" \
-		-o "${SRCDIR}/harrison_lv2s.${WARCH}.zip" \
-		http://www.harrisonconsoles.com/mixbus/mb3/${WARCH}/harrison_lv2s.zip
-	unzip -q -d "$ALIBDIR/LV2/" "${SRCDIR}/harrison_lv2s.${WARCH}.zip"
+		-z "${SRCCACHE}/harrison_lv2s.${WARCH}.zip" \
+		-o "${SRCCACHE}/harrison_lv2s.${WARCH}.zip" \
+		"http://www.harrisonconsoles.com/mixbus/mb3/beta/harrison-dsp/harrison_lv2s.${WARCH}.zip"
+	unzip -q -d "$ALIBDIR/LV2/" "${SRCCACHE}/harrison_lv2s.${WARCH}.zip"
 fi
 
 if test -n "$MIXBUS"; then
@@ -267,11 +269,11 @@ if test -n "$MIXBUS"; then
 
 	mkdir -p $ALIBDIR/ladspa/strip
 	curl -s -S --fail -# \
-		-z "${SRCDIR}/harrison_channelstrip.${WARCH}.dll" \
-		-o "${SRCDIR}/harrison_channelstrip.${WARCH}.dll" \
-		http://www.harrisonconsoles.com/mixbus/mb3/${WARCH}/harrison_channelstrip.dll
+		-z "${SRCCACHE}/harrison_channelstrip.${WARCH}.dll" \
+		-o "${SRCCACHE}/harrison_channelstrip.${WARCH}.dll" \
+		"http://www.harrisonconsoles.com/mixbus/mb3/beta/harrison-dsp/harrison_channelstrip.${WARCH}.dll"
 
-	cp "${SRCDIR}/harrison_channelstrip.${WARCH}.dll" \
+	cp "${SRCCACHE}/harrison_channelstrip.${WARCH}.dll" \
 		"$ALIBDIR/ladspa/strip/harrison_channelstrip.dll"
 fi
 
diff --git a/wscript b/wscript
index 14d6602..db1a3dd 100644
--- a/wscript
+++ b/wscript
@@ -35,13 +35,15 @@ Context.Context.is_tracks_build = is_tracks_build
 compiler_flags_dictionaries= {
     'gcc' : {
         # Flags required when building a debug build
-        'debuggable' : [ '-O0', '-g' ],
+        'debuggable' : [ '-g' ],
         # Flags required for the linker (if any) when building a debug build
         'linker-debuggable' : '',
         # Flags required when building a non-debug optimized build
         'nondebuggable' : '-DNDEBUG',
-        # Flags required to enable profiling at runtime
-        'profile' : '-pg',
+        # Flags required to enable profiling at runtime with optimized builds
+        'profile' : [ '-fno-omit-frame-pointer' ],
+        # Flags required to enable gprofile profiling
+        'gprofile' : '-pg',
         # Flags required to disable warnings about unused arguments to function calls
         'silence-unused-arguments' : '',
         # Flags required to use SSE unit for general math
@@ -89,7 +91,7 @@ compiler_flags_dictionaries= {
         'debuggable' : ['/DDEBUG', '/Od', '/Zi', '/MDd', '/Gd', '/EHsc'],
         'linker-debuggable' : ['/DEBUG', '/INCREMENTAL' ],
         'nondebuggable' : ['/DNDEBUG', '/Ob1', '/MD', '/Gd', '/EHsc'],
-        'profile' : '',
+        'profile' : '/Oy-',
         'sse' : '/arch:SSE',
         'silence-unused-arguments' : '',
         'sse' : '',
@@ -221,6 +223,7 @@ children = [
         'mcp',
         'patchfiles',
         'headless',
+        'session_utils',
         # shared helper binaries (plugin-scanner, exec-wrapper)
         'libs/fst',
         'libs/vfork',
@@ -332,7 +335,7 @@ int main() { return 0; }''',
         linker_flags.append('-fsanitize=address')
 
     if opt.gprofile:
-        debug_flags = [ flags_dict['profile'] ]
+        debug_flags = [ flags_dict['gprofile'] ]
 
     # OSX
     if platform == 'darwin':
@@ -340,6 +343,8 @@ int main() { return 0; }''',
             conf.env['build_host'] = 'mavericks'
         elif re.search ("^14[.]", version) != None:
             conf.env['build_host'] = 'yosemite'
+        elif re.search ("^15[.]", version) != None:
+            conf.env['build_host'] = 'el_capitan'
         else:
             conf.env['build_host'] = 'irrelevant'
 
@@ -361,8 +366,10 @@ int main() { return 0; }''',
                 conf.env['build_target'] = 'mountainlion'
             elif re.search ("^13[.]", version) != None:
                 conf.env['build_target'] = 'mavericks'
-            else:
+            elif re.search ("^14[.]", version) != None:
                 conf.env['build_target'] = 'yosemite'
+            else:
+                conf.env['build_target'] = 'el_capitan'
         else:
             match = re.search(
                     "(?P<cpu>i[0-6]86|x86_64|powerpc|ppc|ppc64|arm|s390x?)",
@@ -383,21 +390,28 @@ int main() { return 0; }''',
         #
         compiler_flags.append ('-U__STRICT_ANSI__')
 
-    if conf.options.cxx11 or conf.env['build_host'] in [ 'mavericks', 'yosemite' ]:
+    if opt.use_libcpp:
+       cxx_flags.append('--stdlib=libc++')
+       linker_flags.append('--stdlib=libc++')
+
+    if conf.options.cxx11 or conf.env['build_host'] in [ 'mavericks', 'yosemite', 'el_capitan' ]:
         conf.check_cxx(cxxflags=["-std=c++11"])
         cxx_flags.append('-std=c++11')
         if platform == "darwin":
-            cxx_flags.append('--stdlib=libstdc++')
             # Mavericks and later changed the syntax to be used when including Carbon headers,
             # from requiring a full path to requiring just the header name.
             cxx_flags.append('-DCARBON_FLAT_HEADERS')
-            linker_flags.append('--stdlib=libstdc++')
+
+            if not opt.use_libcpp:
+                cxx_flags.append('--stdlib=libstdc++')
+                linker_flags.append('--stdlib=libstdc++')
             # Prevents visibility issues in standard headers
             conf.define("_DARWIN_C_SOURCE", 1)
         else:
             cxx_flags.append('-DBOOST_NO_AUTO_PTR')
 
-    if (is_clang and platform == "darwin") or conf.env['build_host'] in ['mavericks', 'yosemite']:
+
+    if (is_clang and platform == "darwin") or conf.env['build_host'] in ['mavericks', 'yosemite', 'el_capitan']:
         # Silence warnings about the non-existing osx clang compiler flags
         # -compatibility_version and -current_version.  These are Waf
         # generated and not needed with clang
@@ -476,10 +490,9 @@ int main() { return 0; }''',
 
     if conf.env['build_target'] == 'x86_64' and opt.windows_vst:
         print("\n\n==================================================")
-        print("You cannot use VST plugins with a 64 bit host. Please run waf with --windows-vst=0")
-        print("\nIt is theoretically possible to build a 32 bit host on a 64 bit system.")
-        print("However, this is tricky and not recommended for beginners.")
-        sys.exit (-1)
+        print("64bit Windows VST support on 64bit Linux is experimental.")
+        print("(This version of ardour will not load 32bit VSTs)")
+        print("==================================================\n\n")
 
     if conf.env['LXVST_SUPPORT'] == True:
         if conf.env['build_target'] == 'x86_64':
@@ -509,7 +522,7 @@ int main() { return 0; }''',
                 ("-DMAC_OS_X_VERSION_MIN_REQUIRED=1070",
                  '-mmacosx-version-min=10.7'))
 
-    elif conf.env['build_target'] in [ 'mavericks', 'yosemite' ]:
+    elif conf.env['build_target'] in [ 'mavericks', 'yosemite', 'el_capitan' ]:
         compiler_flags.extend(
                 ("-DMAC_OS_X_VERSION_MAX_ALLOWED=1090",
                  "-mmacosx-version-min=10.8"))
@@ -545,6 +558,9 @@ int main() { return 0; }''',
     if opt.debug_symbols:
         optimization_flags += flags_dict['debuggable']
 
+    if opt.profile:
+        optimization_flags += flags_dict['profile']
+
     if opt.stl_debug:
         cxx_flags.append("-D_GLIBCXX_DEBUG")
 
@@ -587,6 +603,10 @@ int main() { return 0; }''',
     if opt.nls:
         compiler_flags.append('-DENABLE_NLS')
 
+    # use sparingly, prefer runtime profile
+    if Options.options.program_name.lower() == "mixbus":
+        compiler_flags.append ('-DMIXBUS')
+
     compiler_flags.append ('-DPROGRAM_NAME="' + Options.options.program_name + '"')
     compiler_flags.append ('-DPROGRAM_VERSION="' + PROGRAM_VERSION + '"')
 
@@ -643,9 +663,11 @@ def options(opt):
     opt.add_option('--no-fpu-optimization', action='store_false', dest='fpu_optimization')
     opt.add_option('--exports-hidden', action='store_true', default=False, dest='exports_hidden')
     opt.add_option('--freedesktop', action='store_true', default=False, dest='freedesktop',
-                    help='Install MIME type, icons and .desktop file as per freedesktop.org standards')
+                    help='Build MIME type and .desktop files as per freedesktop.org standards (will be placed in build/gtk2_ardour)')
     opt.add_option('--freebie', action='store_true', default=False, dest='freebie',
                     help='Build a version suitable for distribution as a zero-cost binary')
+    opt.add_option('--profile', action='store_true', default=False, dest='profile',
+                    help='Compile for use with profiling tools requiring a frame pointer')
     opt.add_option('--gprofile', action='store_true', default=False, dest='gprofile',
                     help='Compile for use with gprofile')
     opt.add_option('--libjack', type='string', default="auto", dest='libjack_link',
@@ -713,6 +735,8 @@ def options(opt):
                     help='Do not ask questions that require confirmation during the build')
     opt.add_option('--cxx11', action='store_true', default=False, dest='cxx11',
                     help='Turn on c++11 compiler flags (-std=c++11)')
+    opt.add_option('--use-libc++', action='store_true', default=False, dest='use_libcpp',
+                    help='use libc++ instead of default or auto-detected stdlib')
     opt.add_option('--address-sanitizer', action='store_true', default=False, dest='asan',
                     help='Turn on AddressSanitizer (requires GCC >= 4.8 or clang >= 3.1)')
     opt.add_option('--ptformat', action='store_true', default=False, dest='ptformat',
@@ -741,6 +765,19 @@ def configure(conf):
         conf.env['CFLAGS'] = []
         conf.env['CXXFLAGS'] = []
 
+    # freedesktop translations needs itstool > 1.0.3 (-j option)
+    if Options.options.freedesktop:
+        output = subprocess.Popen("itstool --version", shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0].splitlines()
+        o = output[0].decode('utf-8')
+        itstool = o.split(' ')[0]
+        version = o.split(' ')[1].split('.')
+        # use  distutils.version.StrictVersion  or something python to check >= 1.0.4
+        # but first make sure that all build-hosts (incl. OSX-10.5/PPC) have that python lib.
+        # lazy approach: just use major version 2.X.X
+        if itstool != "itstool" or version[0] < "2":
+            print("--freedesktop requires itstool > 2.0.0 to translate files.")
+            sys.exit(-1)
+
     conf.env['VERSION'] = VERSION
     conf.env['MAJOR'] = MAJOR
     conf.env['MINOR'] = MINOR
@@ -904,7 +941,7 @@ def configure(conf):
 
     have_rf64_riff_support = conf.check_cc(fragment = '''
 #include <sndfile.h>
-int main () { int x = SFC_AUTO_DOWNGRADE_RF64; return 0; }
+int main () { int x = SFC_RF64_AUTO_DOWNGRADE; return 0; }
 ''',
                                            features  = 'c',
                                            mandatory = False,
@@ -917,7 +954,7 @@ int main () { int x = SFC_AUTO_DOWNGRADE_RF64; return 0; }
     if have_rf64_riff_support:
             conf.env.append_value('CXXFLAGS', "-DHAVE_RF64_RIFF")
             conf.env.append_value('CFLAGS', "-DHAVE_RF64_RIFF")
-    
+
     if Options.options.dist_target == 'mingw':
         Options.options.fpu_optimization = True
         conf.env.append_value('CFLAGS', '-DPLATFORM_WINDOWS')
@@ -944,6 +981,23 @@ int main () { int x = SFC_AUTO_DOWNGRADE_RF64; return 0; }
         conf.env.append_value('CXXFLAGS', '-DUSE_CAIRO_IMAGE_SURFACE')
         conf.define ('WINDOWS', 1)
 
+        have_ptw_semaphore = conf.check_cc(fragment = '''
+#include <pthread.h>
+#include <semaphore.h>
+int main () { return 0; }
+''',
+                                           features  = 'c',
+                                           mandatory = False,
+                                           execute   = False,
+                                           msg       = 'Checking for pthread posix semaphore',
+                                           okmsg     = 'Found',
+                                           errmsg    = 'Not found, falling back to Windows Semaphore.')
+
+        #if have_ptw_semaphore:
+        #    conf.define('USE_PTW32_SEMAPHORE', 1)
+        #    conf.env.append_value('CFLAGS', '-DUSE_PTW32_SEMAPHORE')
+        #    conf.env.append_value('CXXFLAGS', '-DUSE_PTW32_SEMAPHORE')
+
     if Options.options.dist_target == 'msvc':
         conf.env.append_value('CFLAGS', '-DPLATFORM_WINDOWS')
         conf.env.append_value('CFLAGS', '-DCOMPILER_MSVC')
@@ -983,6 +1037,8 @@ int main () { int x = SFC_AUTO_DOWNGRADE_RF64; return 0; }
         conf.env['PHONE_HOME'] = True
     if opts.fpu_optimization:
         conf.env['FPU_OPTIMIZATION'] = True
+    if opts.freedesktop:
+        conf.env['FREEDESKTOP'] = True
     if opts.nls:
         conf.define('ENABLE_NLS', 1)
         conf.env['ENABLE_NLS'] = True
@@ -1103,6 +1159,7 @@ const char* const ardour_config_info = "\\n\\
     write_config_text('Free/Demo copy',        conf.is_defined('FREEBIE'))
     write_config_text('Build target',          conf.env['build_target'])
     write_config_text('CoreAudio',             conf.is_defined('HAVE_COREAUDIO'))
+    write_config_text('CoreAudio 10.5 compat', conf.is_defined('COREAUDIO105'))
     write_config_text('CoreAudio/Midi Backend',conf.env['BUILD_CORECRAPPITA'])
     write_config_text('Debug RT allocations',  conf.is_defined('DEBUG_RT_ALLOC'))
     write_config_text('Debug Symbols',         conf.is_defined('debug_symbols') or conf.env['DEBUG'])
@@ -1122,7 +1179,8 @@ const char* const ardour_config_info = "\\n\\
     write_config_text('Phone home',            conf.is_defined('PHONE_HOME'))
     write_config_text('Program name',          opts.program_name)
     write_config_text('Samplerate',            conf.is_defined('HAVE_SAMPLERATE'))
-    write_config_text('PT format',            conf.is_defined('PTFORMAT'))
+    write_config_text('PT format',             conf.is_defined('PTFORMAT'))
+    write_config_text('PTW32 Semaphore',       conf.is_defined('USE_PTW32_SEMAPHORE'))
 #    write_config_text('Soundtouch',            conf.is_defined('HAVE_SOUNDTOUCH'))
     write_config_text('Translation',           opts.nls)
 #    write_config_text('Tranzport',             opts.tranzport)

-- 
ardour Debian packaging



More information about the pkg-multimedia-commits mailing list