[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 ®ion_before = audio_region()->get_state();
audio_region()->set_envelope_active(true);
XMLNode ®ion_after = audio_region()->get_state();
- trackview.session()->add_command (new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_after));
+ region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_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 *)¶ms->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)¶ms->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 *)¶ms->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 *)¶ms->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)¶ms->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 *)¶ms->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 ¶m, 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 ¶m, 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(¶mValue);
+
+ 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, ¤tPreset, &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 ¶m, 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, ¬eState); // 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 *)¶ms->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)¶ms->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 *)¶ms->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 *)¶ms->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)¶ms->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 *)¶ms->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 ¶mInfo = 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 ¶meter = _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