[SCM] ardour/upstream: New upstream version 5.3~dfsg

umlaeute at users.alioth.debian.org umlaeute at users.alioth.debian.org
Tue Aug 30 12:16:54 UTC 2016


The following commit has been merged in the upstream branch:
commit de0035c5eab634e6d03f6ba0d4e68e1db51b0c42
Author: IOhannes m zmölnig <zmoelnig at umlautQ.umlaeute.mur.at>
Date:   Tue Aug 30 10:42:58 2016 +0200

    New upstream version 5.3~dfsg

diff --git a/Ardour-5.1.0.tar.bz2 b/Ardour-5.1.0.tar.bz2
deleted file mode 100644
index e69de29..0000000
diff --git a/gtk2_ardour/about.cc b/gtk2_ardour/about.cc
index 5caa7e5..eb98398 100644
--- a/gtk2_ardour/about.cc
+++ b/gtk2_ardour/about.cc
@@ -174,6 +174,7 @@ static const char* authors[] = {
 	N_("André Nusser"),
 	N_("Bent Bisballe Nyeng"),
 	N_("Jack O'Quin"),
+	N_("Len Ovens"),
 	N_("Pavel Potocek"),
 	N_("Nimal Ratnayake"),
 	N_("Julien Rivaud"),
diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc
index e817882..922ba84 100644
--- a/gtk2_ardour/ardour_button.cc
+++ b/gtk2_ardour/ardour_button.cc
@@ -649,7 +649,7 @@ ArdourButton::on_size_request (Gtk::Requisition* req)
 			req->width = req->height;
 		if (req->height < req->width)
 			req->height = req->width;
-	} else if (_text_width > 0 && !(_elements & (Menu | Indicator))) {
+	} else if (_sizing_text.empty() && _text_width > 0 && !(_elements & (Menu | Indicator))) {
 		// properly centered text for those elements that are centered
 		// (no sub-pixel offset)
 		if ((req->width - _text_width) & 1) { ++req->width; }
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index d10e673..dceb61e 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -770,8 +770,7 @@ ARDOUR_UI::resize_text_widgets ()
 void
 ARDOUR_UI::focus_on_clock ()
 {
-	if (editor && primary_clock) {
-		editor->present ();
+	if (primary_clock) {
 		primary_clock->focus ();
 	}
 }
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 7d754ed..75ba686 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1451,6 +1451,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 	void set_loop_from_selection (bool play);
 	void set_punch_from_selection ();
 	void set_punch_from_region ();
+	void set_auto_punch_range();
 
 	void set_session_start_from_playhead ();
 	void set_session_end_from_playhead ();
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 44c66e3..660a051 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -330,6 +330,7 @@ Editor::register_actions ()
 
 	reg_sens (editor_actions, "set-playhead", _("Playhead to Mouse"), sigc::mem_fun(*this, &Editor::set_playhead_cursor));
 	reg_sens (editor_actions, "set-edit-point", _("Active Marker to Mouse"), sigc::mem_fun(*this, &Editor::set_edit_point));
+	reg_sens (editor_actions, "set-auto-punch-range", _("Set Auto Punch In/Out from Playhead"), sigc::mem_fun(*this, &Editor::set_auto_punch_range));
 
 	reg_sens (editor_actions, "duplicate-range", _("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false));
 
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index f7bbf2a..35415c8 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -6359,6 +6359,59 @@ Editor::set_punch_from_selection ()
 }
 
 void
+Editor::set_auto_punch_range ()
+{
+	// auto punch in/out button from a single button
+	// If Punch In is unset, set punch range from playhead to end, enable punch in
+	// If Punch In is set, the next punch sets Punch Out, unless the playhead has been
+	//   rewound beyond the Punch In marker, in which case that marker will be moved back
+	//   to the current playhead position.
+	// If punch out is set, it clears the punch range and Punch In/Out buttons
+
+	if (_session == 0) {
+		return;
+	}
+
+	Location* tpl = transport_punch_location();
+	framepos_t now = playhead_cursor->current_frame();
+	framepos_t begin = now;
+	framepos_t end = _session->current_end_frame();
+
+	if (!_session->config.get_punch_in()) {
+		// First Press - set punch in and create range from here to eternity
+		set_punch_range (begin, end, _("Auto Punch In"));
+		_session->config.set_punch_in(true);
+	} else if (tpl && !_session->config.get_punch_out()) {
+		// Second press - update end range marker and set punch_out
+		if (now < tpl->start()) {
+			// playhead has been rewound - move start back  and pretend nothing happened
+			begin = now;
+			set_punch_range (begin, end, _("Auto Punch In/Out"));
+		} else {
+			// normal case for 2nd press - set the punch out
+			end = playhead_cursor->current_frame ();
+			set_punch_range (tpl->start(), now, _("Auto Punch In/Out"));
+			_session->config.set_punch_out(true);
+		}
+	} else 	{
+		if (_session->config.get_punch_out()) {
+			_session->config.set_punch_out(false);
+		}
+
+		if (_session->config.get_punch_in()) {
+			_session->config.set_punch_in(false);
+		}
+
+		if (tpl)
+		{
+			// third press - unset punch in/out and remove range
+			_session->locations()->remove(tpl);
+		}
+	}
+
+}
+
+void
 Editor::set_session_extents_from_selection ()
 {
 	if (_session == 0) {
diff --git a/gtk2_ardour/fft.cc b/gtk2_ardour/fft.cc
index a4e34bf..ec9af2f 100644
--- a/gtk2_ardour/fft.cc
+++ b/gtk2_ardour/fft.cc
@@ -140,6 +140,6 @@ FFT::~FFT()
 	fftwf_destroy_plan(_plan);
 	free(_power_at_bin);
 	free(_phase_at_bin);
-	free(_fftOutput);
-	free(_fftInput);
+	fftwf_free(_fftOutput);
+	fftwf_free(_fftInput);
 }
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
index 4e04929..8e35758 100644
--- a/gtk2_ardour/generic_pluginui.cc
+++ b/gtk2_ardour/generic_pluginui.cc
@@ -273,8 +273,6 @@ GenericPluginUI::build ()
 			}
 
 			control_uis.push_back(cui);
-		} else {
-			grid = false;
 		}
 	}
 
@@ -987,9 +985,7 @@ void
 GenericPluginUI::set_all_automation (AutoState as)
 {
 	for (vector<ControlUI*>::iterator i = input_controls_with_automation.begin(); i != input_controls_with_automation.end(); ++i) {
-		if ((*i)->controller || (*i)->button) {
-			set_automation_state (as, (*i));
-		}
+		set_automation_state (as, (*i));
 	}
 }
 
diff --git a/gtk2_ardour/luainstance.cc b/gtk2_ardour/luainstance.cc
index c813eee..0dd4731 100644
--- a/gtk2_ardour/luainstance.cc
+++ b/gtk2_ardour/luainstance.cc
@@ -37,6 +37,7 @@
 #include "luainstance.h"
 #include "luasignal.h"
 #include "marker.h"
+#include "processor_box.h"
 #include "time_axis_view.h"
 #include "selection.h"
 #include "script_selector.h"
@@ -349,6 +350,16 @@ const char *luasignalstr[] = {
 }; // namespace
 
 
+/** special cases for Ardour's Mixer UI */
+namespace LuaMixer {
+
+	ProcessorBox::ProcSelection
+	processor_selection (lua_State* L) {
+		return ProcessorBox::current_processor_selection ();
+	}
+
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 
 #define xstr(s) stringify(s)
@@ -545,6 +556,8 @@ LuaInstance::register_classes (lua_State* L)
 
 		.addFunction ("http_get", (std::string (*)(const std::string&))&ArdourCurl::http_get)
 
+		.addFunction ("processor_selection", &LuaMixer::processor_selection)
+
 		.beginStdList <ArdourMarker*> ("ArdourMarkerList")
 		.endClass ()
 
@@ -801,11 +814,12 @@ using namespace ARDOUR_UI_UTILS;
 using namespace PBD;
 using namespace std;
 
-#ifndef NDEBUG
 static void _lua_print (std::string s) {
+#ifndef NDEBUG
 	std::cout << "LuaInstance: " << s << "\n";
-}
 #endif
+	PBD::info << "LuaInstance: " << s << endmsg;
+}
 
 LuaInstance* LuaInstance::_instance = 0;
 
@@ -821,9 +835,7 @@ LuaInstance::instance ()
 
 LuaInstance::LuaInstance ()
 {
-#ifndef NDEBUG
 	lua.Print.connect (&_lua_print);
-#endif
 	init ();
 
 	LuaScriptParamList args;
@@ -1280,9 +1292,7 @@ LuaInstance::register_lua_slot (const std::string& name, const std::string& scri
 	ActionHook ah;
 	try {
 		LuaState l;
-#ifndef NDEBUG
 		l.Print.connect (&_lua_print);
-#endif
 		lua_State* L = l.getState();
 		register_hooks (L);
 		l.do_command ("function ardour () end");
@@ -1478,9 +1488,7 @@ LuaCallback::get_state (void)
 void
 LuaCallback::init (void)
 {
-#ifndef NDEBUG
 	lua.Print.connect (&_lua_print);
-#endif
 
 	lua.do_command (
 			"function ScriptManager ()"
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 57cde4a..c65b234 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -119,6 +119,7 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, ArdourCanva
 	, _channel_selector (0)
 	, _step_edit_item (0)
 	, controller_menu (0)
+	, poly_pressure_menu (0)
 	, _step_editor (0)
 {
 	_midnam_model_selector.disable_scrolling();
@@ -605,6 +606,13 @@ MidiTimeAxisView::build_automation_action_menu (bool for_selection)
 		build_controller_menu ();
 
 		automation_items.push_back (MenuElem (_("Controllers"), *controller_menu));
+
+		if (!poly_pressure_menu) {
+			poly_pressure_menu = new Gtk::Menu;
+		}
+
+		automation_items.push_back (MenuElem  (_("Polyphonic Pressure"), *poly_pressure_menu));
+
 		automation_items.back().set_sensitive (
 			!for_selection || _editor.get_selection().tracks.size() == 1);
 	} else {
@@ -1605,6 +1613,10 @@ MidiTimeAxisView::contents_height_changed ()
 void
 MidiTimeAxisView::playback_channel_mode_changed ()
 {
+	/* Invalidate the controller automation menu */
+	delete controller_menu;
+	controller_menu = 0;
+	/* Update the button text */
 	switch (midi_track()->get_playback_channel_mode()) {
 	case AllChannels:
 		_playback_channel_status.set_markup (string_compose ("<b>%1</b>: <i>%2</i>", _("Play"), _("all")));
diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h
index fa6102c..2b721a7 100644
--- a/gtk2_ardour/midi_time_axis.h
+++ b/gtk2_ardour/midi_time_axis.h
@@ -161,6 +161,7 @@ private:
 	void add_channel_command_menu_item (Gtk::Menu_Helpers::MenuList& items, const std::string& label, ARDOUR::AutomationType auto_type, uint8_t cmd);
 
 	Gtk::Menu* controller_menu;
+	Gtk::Menu* poly_pressure_menu;
 
 	void add_single_channel_controller_item (Gtk::Menu_Helpers::MenuList& ctl_items, int ctl, const std::string& name);
 	void add_multi_channel_controller_item (Gtk::Menu_Helpers::MenuList& ctl_items, int ctl, const std::string& name);
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index 5dd7483..5f01155 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -454,6 +454,16 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
 	static Gtkmm2ext::Bindings* bindings;
 	static void register_actions();
 
+	typedef std::vector<boost::shared_ptr<ARDOUR::Processor> > ProcSelection;
+
+	static ProcSelection current_processor_selection () {
+		ProcSelection ps;
+		if (_current_processor_box) {
+			_current_processor_box->get_selected_processors (ps);
+		}
+		return ps;
+	}
+
 #ifndef NDEBUG
 	static bool show_all_processors;
 #endif
@@ -535,8 +545,6 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
 
 	void ab_plugins ();
 
-	typedef std::vector<boost::shared_ptr<ARDOUR::Processor> > ProcSelection;
-
 	void cut_processors (const ProcSelection&);
 	void copy_processors (const ProcSelection&);
 	void delete_processors (const ProcSelection&);
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index 7596c6f..8e562f4 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -1860,14 +1860,6 @@ RCOptionEditor::RCOptionEditor ()
         , _rc_config (Config)
 	, _mixer_strip_visibility ("mixer-element-visibility")
 {
-	XMLNode* node = ARDOUR_UI::instance()->preferences_settings();
-	if (node) {
-		/* gcc4 complains about ambiguity with Gtk::Widget::set_state
-		   (Gtk::StateType) here !!!
-		*/
-		Tabbable::set_state (*node, Stateful::loading_state_version);
-	}
-
 	UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &RCOptionEditor::parameter_changed));
 
 	/* MISC */
@@ -1890,7 +1882,7 @@ RCOptionEditor::RCOptionEditor ()
                 procs->add (0, _("all available processors"));
 
                 for (uint32_t i = 1; i <= hwcpus; ++i) {
-                        procs->add (i, string_compose (_("%1 processors"), i));
+	                procs->add (i, string_compose (P_("%1 processor", "%1 processors", i), i));
                 }
 
 		procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
@@ -3368,6 +3360,14 @@ if (!ARDOUR::Profile->get_mixbus()) {
 	parameter_changed ("sync-source");
 	parameter_changed ("use-monitor-bus");
 	parameter_changed ("open-gui-after-adding-plugin");
+
+	XMLNode* node = ARDOUR_UI::instance()->preferences_settings();
+	if (node) {
+		/* gcc4 complains about ambiguity with Gtk::Widget::set_state
+		   (Gtk::StateType) here !!!
+		*/
+		Tabbable::set_state (*node, Stateful::loading_state_version);
+	}
 }
 
 void
@@ -3491,7 +3491,7 @@ RCOptionEditor::populate_sync_options ()
 Gtk::Window*
 RCOptionEditor::use_own_window (bool and_fill_it)
 {
-	bool new_window = !own_window();
+	bool new_window = !own_window ();
 
 	Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
 
diff --git a/gtk2_ardour/windows_vst_plugin_ui.cc b/gtk2_ardour/windows_vst_plugin_ui.cc
index 5281890..7f14819 100644
--- a/gtk2_ardour/windows_vst_plugin_ui.cc
+++ b/gtk2_ardour/windows_vst_plugin_ui.cc
@@ -58,6 +58,8 @@ WindowsVSTPluginUI::WindowsVSTPluginUI (boost::shared_ptr<PluginInsert> pi, boos
 
 WindowsVSTPluginUI::~WindowsVSTPluginUI ()
 {
+	fst_destroy_editor (_vst->state());
+
 	// plugin destructor destroys the custom GUI, via Windows fun-and-games,
 	// and then our PluginUIWindow does the rest
 }
diff --git a/libs/ardour/config_text.cc b/libs/ardour/config_text.cc
index 73392b4..cd053e9 100644
--- a/libs/ardour/config_text.cc
+++ b/libs/ardour/config_text.cc
@@ -3,7 +3,7 @@ namespace ARDOUR {
 const char* const ardour_config_info = "\n\
 Build documentation: False\n\
 Debuggable build: True\n\
-Export all symbols (backtrace): False\n\
+Export all symbols (backtrace): True\n\
 Install prefix: /usr/local\n\
 Strict compiler flags: []\n\
 Internal Shared Libraries: True\n\
@@ -46,11 +46,11 @@ Wiimote support: True\n\
 Windows key: Mod4><Super\n\
 PortAudio Backend: False\n\
 CoreAudio/Midi Backend: False\n\
-ALSA Backend: False\n\
+ALSA Backend: True\n\
 Dummy backend: False\n\
 JACK Backend: True\n\
-C compiler flags: ['-I/usr/local/music/src/ardour/5.1', '-DWAF_BUILD', '-g', '-fshow-column', '-DARCH_X86', '-mmmx', '-msse', '-mfpmath=sse', '-DUSE_XMMINTRIN', '-DBUILD_SSE_OPTIMIZATIONS', '-DLXVST_64BIT', '-Wall', '-Wpointer-arith', '-Wcast-qual', '-Wcast-align', '-Wno-unused-parameter', '-DBOOST_SYSTEM_NO_DEPRECATED', '-D_ISOC9X_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-DENABLE_NLS', '-DPROGRAM_NAME=\"Ardour\"', u'-DPROGRAM_VERSION=\"5\"', '-Wstrict-prototypes', '-Wmissing-prototypes']\n\
-C++ compiler flags: ['-I/usr/local/music/src/ardour/5.1', '-DWAF_BUILD', '-g', '-fshow-column', '-DARCH_X86', '-mmmx', '-msse', '-mfpmath=sse', '-DUSE_XMMINTRIN', '-DBUILD_SSE_OPTIMIZATIONS', '-DLXVST_64BIT', '-Wall', '-Wpointer-arith', '-Wcast-qual', '-Wcast-align', '-Wno-unused-parameter', '-DBOOST_SYSTEM_NO_DEPRECATED', '-D_ISOC9X_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-DENABLE_NLS', '-DPROGRAM_NAME=\"Ardour\"', u'-DPROGRAM_VERSION=\"5\"', '-Woverloaded-virtual', '-Wno-unused-local-typedefs', '-D__STDC_LIMIT_MACROS', '-D__STDC_FORMAT_MACROS', '-DCANVAS_COMPATIBILITY', '-DCANVAS_DEBUG']\n\
-Linker flags: ['']\n\
+C compiler flags: ['-I/usr/local/music/src/ardour/5.3', '-DWAF_BUILD', '-g', '-std=c99', '-pedantic', '-Wshadow', '-Wall', '-Wcast-align', '-Wextra', '-Wwrite-strings', '-Wunsafe-loop-optimizations', '-Wlogical-op', '-fshow-column', '-DARCH_X86', '-mmmx', '-msse', '-mfpmath=sse', '-DUSE_XMMINTRIN', '-DBUILD_SSE_OPTIMIZATIONS', '-DLXVST_64BIT', '-Wall', '-Wpointer-arith', '-Wcast-qual', '-Wcast-align', '-Wno-unused-parameter', '-DBOOST_SYSTEM_NO_DEPRECATED', '-D_ISOC9X_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-DENABLE_NLS', '-DPROGRAM_NAME=\"Ardour\"', u'-DPROGRAM_VERSION=\"5\"', '-Wstrict-prototypes', '-Wmissing-prototypes']\n\
+C++ compiler flags: ['-I/usr/local/music/src/ardour/5.3', '-DWAF_BUILD', '-g', '-ansi', '-Wnon-virtual-dtor', '-Woverloaded-virtual', '-fstrict-overflow', '-Wall', '-Wcast-align', '-Wextra', '-Wwrite-strings', '-Wunsafe-loop-optimizations', '-Wlogical-op', '-fshow-column', '-DARCH_X86', '-mmmx', '-msse', '-mfpmath=sse', '-DUSE_XMMINTRIN', '-DBUILD_SSE_OPTIMIZATIONS', '-DLXVST_64BIT', '-Wall', '-Wpointer-arith', '-Wcast-qual', '-Wcast-align', '-Wno-unused-parameter', '-DBOOST_SYSTEM_NO_DEPRECATED', '-D_ISOC9X_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-DENABLE_NLS', '-DPROGRAM_NAME=\"Ardour\"', u'-DPROGRAM_VERSION=\"5\"', '-Woverloaded-virtual', '-Wno-unused-local-typedefs', '-D__STDC_LIMIT_MACROS', '-D__STDC_FORMAT_MACROS', '-DCANVAS_COMPATIBILITY', '-DCANVAS_DEBUG']\n\
+Linker flags: ['', '-rdynamic']\n\
 ";
 }
diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc
index 33283c5..d316c85 100644
--- a/libs/ardour/luabindings.cc
+++ b/libs/ardour/luabindings.cc
@@ -180,10 +180,13 @@ CLASSKEYS(PBD::ID);
 CLASSKEYS(ARDOUR::Location);
 CLASSKEYS(ARDOUR::PluginInfo);
 CLASSKEYS(ARDOUR::MonitorProcessor);
+CLASSKEYS(ARDOUR::Plugin::PresetRecord);
+CLASSKEYS(std::vector<ARDOUR::Plugin::PresetRecord>);
 CLASSKEYS(PBD::PropertyChange);
 CLASSKEYS(std::vector<std::string>);
 CLASSKEYS(std::list<boost::shared_ptr<ARDOUR::Route> >);
 CLASSKEYS(std::list<boost::shared_ptr<ARDOUR::Port> >);
+CLASSKEYS(std::vector<boost::shared_ptr<ARDOUR::Processor> >);
 CLASSKEYS(boost::shared_ptr<ARDOUR::PluginInfo>);
 CLASSKEYS(boost::shared_ptr<ARDOUR::Region>);
 CLASSKEYS(boost::weak_ptr<ARDOUR::Route>);
@@ -455,6 +458,16 @@ LuaBindings::common (lua_State* L)
 
 		.beginWSPtrClass <PluginInfo> ("PluginInfo")
 		.addVoidConstructor ()
+		.addData ("name", &PluginInfo::name, false)
+		.addData ("category", &PluginInfo::category, false)
+		.addData ("creator", &PluginInfo::creator, false)
+		.addData ("path", &PluginInfo::path, false)
+		.addData ("n_inputs", &PluginInfo::n_inputs, false)
+		.addData ("n_outputs", &PluginInfo::n_outputs, false)
+		.addData ("type", &PluginInfo::type, false)
+		.addData ("unique_id", &PluginInfo::unique_id, false)
+		.addFunction ("is_instrument", &PluginInfo::is_instrument)
+		.addFunction ("get_presets", &PluginInfo::get_presets)
 		.endClass ()
 
 		.beginNamespace ("Route")
@@ -810,6 +823,8 @@ LuaBindings::common (lua_State* L)
 		.addData ("valid", &Plugin::PresetRecord::valid, false)
 		.endClass ()
 
+		.beginStdVector <Plugin::PresetRecord> ("PresetVector").endClass ()
+
 		.deriveWSPtrClass <Automatable, Evoral::ControlSet> ("Automatable")
 		.addFunction ("automation_control", (boost::shared_ptr<AutomationControl>(Automatable::*)(const Evoral::Parameter&, bool))&Automatable::automation_control)
 		.endClass ()
@@ -821,6 +836,8 @@ LuaBindings::common (lua_State* L)
 		.addStaticFunction ("midi_note_name", &ParameterDescriptor::midi_note_name)
 		.endClass ()
 
+		.beginStdVector <boost::shared_ptr<ARDOUR::Processor> > ("ProcessorVector").endClass ()
+
 		.deriveWSPtrClass <Processor, SessionObject> ("Processor")
 		.addCast<Automatable> ("to_automatable")
 		.addCast<PluginInsert> ("to_insert")
@@ -864,6 +881,7 @@ LuaBindings::common (lua_State* L)
 		.addFunction ("load_preset", &Plugin::load_preset)
 		.addFunction ("parameter_is_input", &Plugin::parameter_is_input)
 		.addFunction ("get_docs", &Plugin::get_docs)
+		.addFunction ("get_info", &Plugin::get_info)
 		.addFunction ("get_parameter_docs", &Plugin::get_parameter_docs)
 		.addRefFunction ("get_parameter_descriptor", &Plugin::get_parameter_descriptor)
 		.endClass ()
diff --git a/libs/ardour/luaproc.cc b/libs/ardour/luaproc.cc
index c67667c..362b785 100644
--- a/libs/ardour/luaproc.cc
+++ b/libs/ardour/luaproc.cc
@@ -46,7 +46,7 @@ LuaProc::LuaProc (AudioEngine& engine,
                   Session& session,
                   const std::string &script)
 	: Plugin (engine, session)
-	, _mempool ("LuaProc", 2097152)
+	, _mempool ("LuaProc", 3145728)
 #ifdef USE_TLSF
 	, lua (lua_newstate (&PBD::TLSF::lalloc, &_mempool))
 #elif defined USE_MALLOC
@@ -76,7 +76,7 @@ LuaProc::LuaProc (AudioEngine& engine,
 
 LuaProc::LuaProc (const LuaProc &other)
 	: Plugin (other)
-	, _mempool ("LuaProc", 2097152)
+	, _mempool ("LuaProc", 3145728)
 #ifdef USE_TLSF
 	, lua (lua_newstate (&PBD::TLSF::lalloc, &_mempool))
 #elif defined USE_MALLOC
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index e0498b7..e45270e 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -1095,8 +1095,8 @@ LV2Plugin::get_layout (uint32_t which, UILayoutHint& h) const
 		case 15: h.x0 = 13; h.x1 = 14; h.y0 = 0; h.y1 = 1; break; // Gain H
 		case 22: h.x0 = 13; h.x1 = 14; h.y0 = 5; h.y1 = 6; break; // enable H
 
-
-		case 16: h.x0 = 14; h.x1 = 15; h.y0 = 4; h.y1 = 6; break; // Master Gain
+		case 16: h.x0 = 14; h.x1 = 15; h.y0 = 1; h.y1 = 3; break; // Master Gain
+		case 23: h.x0 = 14; h.x1 = 15; h.y0 = 5; h.y1 = 6; break; // Master Enable
 		default:
 			return false;
 	}
diff --git a/libs/ardour/revision.cc b/libs/ardour/revision.cc
index 2becc9e..80a0f36 100644
--- a/libs/ardour/revision.cc
+++ b/libs/ardour/revision.cc
@@ -1,2 +1,2 @@
 #include "ardour/revision.h"
-namespace ARDOUR { const char* revision = "5.1"; }
+namespace ARDOUR { const char* revision = "5.3"; }
diff --git a/libs/backends/coreaudio/coreaudio_backend.cc b/libs/backends/coreaudio/coreaudio_backend.cc
index d4e1d91..504a737 100644
--- a/libs/backends/coreaudio/coreaudio_backend.cc
+++ b/libs/backends/coreaudio/coreaudio_backend.cc
@@ -203,8 +203,8 @@ CoreAudioBackend::available_sample_rates2 (const std::string& input_device, cons
 	std::vector<float> sr_in;
 	std::vector<float> sr_out;
 
-	const uint32_t inp = name_to_id (input_device);
-	const uint32_t out = name_to_id (output_device);
+	const uint32_t inp = name_to_id (input_device, Input);
+	const uint32_t out = name_to_id (output_device, Output);
 
 	if (inp == UINT32_MAX && out == UINT32_MAX) {
 		return sr;
@@ -237,8 +237,8 @@ CoreAudioBackend::available_buffer_sizes2 (const std::string& input_device, cons
 	std::vector<uint32_t> bs;
 	std::vector<uint32_t> bs_in;
 	std::vector<uint32_t> bs_out;
-	const uint32_t inp = name_to_id (input_device);
-	const uint32_t out = name_to_id (output_device);
+	const uint32_t inp = name_to_id (input_device, Input);
+	const uint32_t out = name_to_id (output_device, Output);
 	if (inp == UINT32_MAX && out == UINT32_MAX) {
 		return bs;
 	} else if (inp == UINT32_MAX) {
@@ -292,7 +292,7 @@ int
 CoreAudioBackend::set_input_device_name (const std::string& d)
 {
 	_input_audio_device = d;
-	const float sr = _pcmio->current_sample_rate(name_to_id(_input_audio_device));
+	const float sr = _pcmio->current_sample_rate(name_to_id(_input_audio_device, Input));
 	if (sr > 0) { set_sample_rate(sr); }
 	return 0;
 }
@@ -302,7 +302,7 @@ CoreAudioBackend::set_output_device_name (const std::string& d)
 {
 	_output_audio_device = d;
 	// TODO check SR.
-	const float sr = _pcmio->current_sample_rate(name_to_id(_output_audio_device));
+	const float sr = _pcmio->current_sample_rate(name_to_id(_output_audio_device, Output));
 	if (sr > 0) { set_sample_rate(sr); }
 	return 0;
 }
@@ -459,10 +459,10 @@ void
 CoreAudioBackend::launch_control_app ()
 {
 	if (name_to_id (_input_audio_device) != UINT32_MAX) {
-		_pcmio->launch_control_app(name_to_id(_input_audio_device));
+		_pcmio->launch_control_app(name_to_id(_input_audio_device, Input));
 	}
 	if (name_to_id (_output_audio_device) != UINT32_MAX) {
-		_pcmio->launch_control_app(name_to_id(_output_audio_device));
+		_pcmio->launch_control_app(name_to_id(_output_audio_device, Output));
 	}
 }
 
@@ -507,8 +507,8 @@ CoreAudioBackend::_start (bool for_latency_measurement)
 		_portmap.clear();
 	}
 
-	uint32_t device1 = name_to_id(_input_audio_device);
-	uint32_t device2 = name_to_id(_output_audio_device);
+	uint32_t device1 = name_to_id(_input_audio_device, Input);
+	uint32_t device2 = name_to_id(_output_audio_device, Output);
 
 	assert(_active_ca == false);
 	assert(_active_fw == false);
@@ -778,10 +778,24 @@ CoreAudioBackend::samples_since_cycle_start ()
 }
 
 uint32_t
-CoreAudioBackend::name_to_id(std::string device_name) const {
+CoreAudioBackend::name_to_id(std::string device_name, DeviceFilter filter) const {
 	uint32_t device_id = UINT32_MAX;
 	std::map<size_t, std::string> devices;
-	_pcmio->device_list(devices);
+	switch (filter) {
+		case Input:
+			_pcmio->input_device_list (devices);
+			break;
+		case Output:
+			_pcmio->output_device_list (devices);
+			break;
+		case Duplex:
+			_pcmio->duplex_device_list (devices);
+			break;
+		case All:
+		default:
+			_pcmio->device_list (devices);
+			break;
+	}
 
 	for (std::map<size_t, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
 		if (i->second == device_name) {
@@ -1074,8 +1088,8 @@ CoreAudioBackend::register_system_audio_ports()
 	const uint32_t a_ins = _n_inputs;
 	const uint32_t a_out = _n_outputs;
 
-	const uint32_t coreaudio_reported_input_latency = _pcmio->get_latency(name_to_id(_input_audio_device), true);
-	const uint32_t coreaudio_reported_output_latency = _pcmio->get_latency(name_to_id(_output_audio_device), false);
+	const uint32_t coreaudio_reported_input_latency = _pcmio->get_latency(name_to_id(_input_audio_device, Input), true);
+	const uint32_t coreaudio_reported_output_latency = _pcmio->get_latency(name_to_id(_output_audio_device, Output), false);
 
 #ifndef NDEBUG
 	printf("COREAUDIO LATENCY: i:%d, o:%d\n",
diff --git a/libs/backends/coreaudio/coreaudio_backend.h b/libs/backends/coreaudio/coreaudio_backend.h
index d37ef6c..5211839 100644
--- a/libs/backends/coreaudio/coreaudio_backend.h
+++ b/libs/backends/coreaudio/coreaudio_backend.h
@@ -434,7 +434,8 @@ class CoreAudioBackend : public AudioBackend {
 	uint32_t _systemic_audio_output_latency;
 
 	/* coreaudio specific  */
-	uint32_t name_to_id(std::string) const;
+	enum DeviceFilter { All, Input, Output, Duplex };
+	uint32_t name_to_id(std::string, DeviceFilter filter = All) const;
 
 	/* processing */
 	float  _dsp_load;
diff --git a/libs/fluidsynth/config.h b/libs/fluidsynth/config.h
index d423dfc..9b0edd9 100644
--- a/libs/fluidsynth/config.h
+++ b/libs/fluidsynth/config.h
@@ -210,7 +210,15 @@
 /* #undef WITH_READLINE */
 
 /* Define if the compiler supports VLA */ 
+#ifndef _MSC_VER
+/* MSVC doesn't support variable length arrays (i.e. arrays 
+   whose size isn't known to the compiler at build time). */
 #define SUPPORTS_VLA 1 
+#endif
+
+#ifdef _MSC_VER
+#define HAVE_IO_H 1
+#endif
 
 /* Define to 1 if your processor stores words with the most significant byte
    first (like Motorola and SPARC, unlike Intel and VAX). */
diff --git a/libs/fluidsynth/src/fluidsynth_priv.h b/libs/fluidsynth/src/fluidsynth_priv.h
index 74b9f4b..b01618d 100644
--- a/libs/fluidsynth/src/fluidsynth_priv.h
+++ b/libs/fluidsynth/src/fluidsynth_priv.h
@@ -105,8 +105,6 @@
 #endif
 
 #if HAVE_WINDOWS_H
-#include <winsock2.h>
-#include <ws2tcpip.h>
 #include <windows.h>
 #endif
 
@@ -123,6 +121,12 @@
 #define STDOUT_FILENO 1
 #define STDERR_FILENO 2
 
+#elif defined _MSC_VER
+
+#define STDIN_FILENO  _fileno(stdin)
+#define STDOUT_FILENO _fileno(stdout)
+#define STDERR_FILENO _fileno(stderr)
+
 #endif
 
 /* Darwin special defines (taken from config_macosx.h) */
diff --git a/libs/fluidsynth/wscript b/libs/fluidsynth/wscript
index a36c8da..849c31f 100644
--- a/libs/fluidsynth/wscript
+++ b/libs/fluidsynth/wscript
@@ -35,7 +35,7 @@ def build(bld):
     bld (export_includes = ['fluidsynth'],
          name = 'libfluidsynth_includes'
          )
-    bld.stlib (source = [
+    obj = bld.stlib (source = [
         'src/fluid_midi.c',
         'src/fluid_adsr_env.c',
         'src/fluid_chorus.c',
@@ -69,5 +69,13 @@ def build(bld):
                defines = [ 'HAVE_CONFIG_H', 'DEFAULT_SOUNDFONT=""' ]
                )
 
+    # wine-gcc hacks:
+    # defining __MINGW32__ for wine-gcc is a workaround for fluidsynth's include
+    # strategy (which is made for mingw or windows) without it
+    # winsock2.h will complain about undeclared "u_short"
+    # we also need to explicitly define  _WIN32
+    if bld.is_defined('WINDOWS_VST_SUPPORT') and not bld.env['build_target'] == 'mingw':
+        obj.defines += [ '_WIN32', '__MINGW32__' ]
+
 def shutdown():
     autowaf.shutdown()
diff --git a/libs/fst/vstwin.c b/libs/fst/vstwin.c
index 3a1f624..ba31876 100644
--- a/libs/fst/vstwin.c
+++ b/libs/fst/vstwin.c
@@ -374,6 +374,9 @@ fst_exit (void)
 int
 fst_run_editor (VSTState* fst, void* window_parent)
 {
+	/* For safety, remove any pre-existing editor window */ 
+	fst_destroy_editor (fst);
+	
 	if (fst->windows_window == NULL) {
 		HMODULE hInst;
 		HWND window;
diff --git a/libs/lua/LuaBridge/detail/CFunctions.h b/libs/lua/LuaBridge/detail/CFunctions.h
index 9f17129..824bdd7 100644
--- a/libs/lua/LuaBridge/detail/CFunctions.h
+++ b/libs/lua/LuaBridge/detail/CFunctions.h
@@ -401,7 +401,6 @@ struct CFunc
     }
   };
 
-
   template <class T>
   struct PtrNullCheck
   {
@@ -430,6 +429,98 @@ struct CFunc
     }
   };
 
+  template <class T>
+  struct PtrEqualCheck
+  {
+    static int f (lua_State* L)
+    {
+      boost::shared_ptr<T> t0 = luabridge::Stack<boost::shared_ptr<T> >::get (L, 1);
+      boost::shared_ptr<T> t1 = luabridge::Stack<boost::shared_ptr<T> >::get (L, 2);
+      Stack <bool>::push (L, t0 == t1);
+      return 1;
+    }
+  };
+
+  template <class T>
+  struct WPtrEqualCheck
+  {
+    static int f (lua_State* L)
+    {
+      bool rv = false;
+      boost::weak_ptr<T> tw0 = luabridge::Stack<boost::weak_ptr<T> >::get (L, 1);
+      boost::weak_ptr<T> tw1 = luabridge::Stack<boost::weak_ptr<T> >::get (L, 2);
+      boost::shared_ptr<T> const t0 = tw0.lock();
+      boost::shared_ptr<T> const t1 = tw1.lock();
+      if (t0 && t1) {
+        T* const tt0 = t0.get();
+        T* const tt1 = t1.get();
+        rv = (tt0 == tt1);
+      }
+      Stack <bool>::push (L, rv);
+      return 1;
+    }
+  };
+
+  template <class C, typename T>
+  static int getPtrProperty (lua_State* L)
+  {
+    boost::shared_ptr<C> cp = luabridge::Stack<boost::shared_ptr<C> >::get (L, 1);
+    C const* const c = cp.get();
+    if (!c) {
+      return luaL_error (L, "shared_ptr is nil");
+    }
+    T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+    Stack <T>::push (L, c->**mp);
+    return 1;
+  }
+
+  template <class C, typename T>
+  static int getWPtrProperty (lua_State* L)
+  {
+    boost::weak_ptr<C> cw = luabridge::Stack<boost::weak_ptr<C> >::get (L, 1);
+    boost::shared_ptr<C> const cp = cw.lock();
+    if (!cp) {
+      return luaL_error (L, "cannot lock weak_ptr");
+    }
+    C const* const c = cp.get();
+    if (!c) {
+      return luaL_error (L, "weak_ptr is nil");
+    }
+    T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+    Stack <T>::push (L, c->**mp);
+    return 1;
+  }
+
+  template <class C, typename T>
+  static int setPtrProperty (lua_State* L)
+  {
+    boost::shared_ptr<C> cp = luabridge::Stack<boost::shared_ptr<C> >::get (L, 1);
+    C* const c = cp.get();
+    if (!c) {
+      return luaL_error (L, "shared_ptr is nil");
+    }
+    T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+    c->**mp = Stack <T>::get (L, 2);
+    return 0;
+  }
+
+  template <class C, typename T>
+  static int setWPtrProperty (lua_State* L)
+  {
+    boost::weak_ptr<C> cw = luabridge::Stack<boost::weak_ptr<C> >::get (L, 1);
+    boost::shared_ptr<C> cp = cw.lock();
+    if (!cp) {
+      return luaL_error (L, "cannot lock weak_ptr");
+    }
+    C* const c = cp.get();
+    if (!c) {
+      return luaL_error (L, "weak_ptr is nil");
+    }
+    T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
+    c->**mp = Stack <T>::get (L, 2);
+    return 0;
+  }
+
   template <class MemFnPtr, class T,
            class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
   struct CallMemberWPtr
diff --git a/libs/lua/LuaBridge/detail/Namespace.h b/libs/lua/LuaBridge/detail/Namespace.h
index 07963f4..bb05751 100644
--- a/libs/lua/LuaBridge/detail/Namespace.h
+++ b/libs/lua/LuaBridge/detail/Namespace.h
@@ -1298,6 +1298,81 @@ private:
       return *this;
     }
 
+    WSPtrClass <T>& addEqualCheck ()
+    {
+      PRINTDOC("Member Function", _name << "sameinstance", std::string("bool"), std::string("void (*)(" + type_name <T>() + ")"))
+      set_weak_class ();
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, &CFunc::WPtrEqualCheck <T>::f, 0);
+      rawsetfield (L, -3, "sameinstance"); // class table
+
+      set_shared_class ();
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, &CFunc::PtrEqualCheck <T>::f, 0);
+      rawsetfield (L, -3, "sameinstance"); // class table
+
+      return *this;
+    }
+
+    template <class U>
+    WSPtrClass <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
+    {
+      DATADOC ("Data Member", name, mp)
+      typedef const U T::*mp_t;
+
+      set_weak_class ();
+      assert (lua_istable (L, -1));
+      // Add to __propget in class and const tables.
+      {
+        rawgetfield (L, -2, "__propget");
+        rawgetfield (L, -4, "__propget");
+        new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
+        lua_pushcclosure (L, &CFunc::getWPtrProperty <T,U>, 1);
+        lua_pushvalue (L, -1);
+        rawsetfield (L, -4, name);
+        rawsetfield (L, -2, name);
+        lua_pop (L, 2);
+      }
+
+      if (isWritable)
+      {
+        // Add to __propset in class table.
+        rawgetfield (L, -2, "__propset");
+        assert (lua_istable (L, -1));
+        new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
+        lua_pushcclosure (L, &CFunc::setWPtrProperty <T,U>, 1);
+        rawsetfield (L, -2, name);
+        lua_pop (L, 1);
+      }
+
+      set_shared_class ();
+      assert (lua_istable (L, -1));
+      // Add to __propget in class and const tables.
+      {
+        rawgetfield (L, -2, "__propget");
+        rawgetfield (L, -4, "__propget");
+        new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
+        lua_pushcclosure (L, &CFunc::getPtrProperty <T,U>, 1);
+        lua_pushvalue (L, -1);
+        rawsetfield (L, -4, name);
+        rawsetfield (L, -2, name);
+        lua_pop (L, 2);
+      }
+
+      if (isWritable)
+      {
+        // Add to __propset in class table.
+        rawgetfield (L, -2, "__propset");
+        assert (lua_istable (L, -1));
+        new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
+        lua_pushcclosure (L, &CFunc::setPtrProperty <T,U>, 1);
+        rawsetfield (L, -2, name);
+        lua_pop (L, 1);
+      }
+
+      return *this;
+    }
+
 
     Namespace endClass ()
     {
@@ -1652,7 +1727,8 @@ public:
   WSPtrClass <T> beginWSPtrClass (char const* name)
   {
     return WSPtrClass <T> (name, this)
-      .addNullCheck();
+      .addNullCheck()
+      .addEqualCheck();
   }
 
   //----------------------------------------------------------------------------
@@ -1810,7 +1886,8 @@ public:
     return WSPtrClass <T> (name, this,
         ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
         ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
-      .addNullCheck();
+      .addNullCheck()
+      .addEqualCheck();
   }
 
 };
diff --git a/libs/lua/luastate.cc b/libs/lua/luastate.cc
index 3b8a7ae..8b704fb 100644
--- a/libs/lua/luastate.cc
+++ b/libs/lua/luastate.cc
@@ -83,7 +83,8 @@ LuaState::collect_garbage_step () {
 
 void
 LuaState::tweak_rt_gc () {
-	//lua_gc (L, LUA_GCSETPAUSE, 20);
+	/* GC runs same speed as  memory allocation */
+	lua_gc (L, LUA_GCSETPAUSE, 100);
 	lua_gc (L, LUA_GCSETSTEPMUL, 100);
 }
 
diff --git a/libs/plugins/a-comp.lv2/a-comp#stereo.ttl.in b/libs/plugins/a-comp.lv2/a-comp#stereo.ttl.in
index 59f2b83..7a45e5a 100644
--- a/libs/plugins/a-comp.lv2/a-comp#stereo.ttl.in
+++ b/libs/plugins/a-comp.lv2/a-comp#stereo.ttl.in
@@ -106,40 +106,51 @@
         lv2:index 8 ;
         lv2:name "Sidechain" ;
         lv2:symbol "sidech" ;
-        lv2:default 0.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 0 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
+    ] ,
+    [
+        a lv2:InputPort, lv2:ControlPort ;
+        lv2:index 9 ;
+        lv2:name "Enable" ;
+        lv2:symbol "enable" ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
+        lv2:designation <http://ardour.org/lv2/processing#enable>;
     ] ;
 
     lv2:port [
         a lv2:InputPort, lv2:AudioPort ;
-        lv2:index 9 ;
+        lv2:index 10 ;
         lv2:symbol "in_1" ;
         lv2:name "Audio Input 1" ;
     ] ,
     [
         a lv2:InputPort, lv2:AudioPort ;
-        lv2:index 10 ;
+        lv2:index 11 ;
         lv2:symbol "in_2" ;
         lv2:name "Audio Input 2" ;
     ] ,
     [
         a lv2:InputPort, lv2:AudioPort ;
-        lv2:index 11 ;
+        lv2:index 12 ;
         lv2:symbol "sidechain_in" ;
         lv2:name "Sidechain Input" ;
         lv2:portProperty lv2:isSideChain ;
-    ],
+    ] ,
     [
         a lv2:OutputPort, lv2:AudioPort ;
-        lv2:index 12 ;
+        lv2:index 13 ;
         lv2:symbol "out_1" ;
         lv2:name "Audio Output 1" ;
     ],
     [
         a lv2:OutputPort, lv2:AudioPort ;
-        lv2:index 13 ;
+        lv2:index 14 ;
         lv2:symbol "out_2" ;
         lv2:name "Audio Output 2" ;
     ] ;
diff --git a/libs/plugins/a-comp.lv2/a-comp.c b/libs/plugins/a-comp.lv2/a-comp.c
index 3b123d2..b27ab1d 100644
--- a/libs/plugins/a-comp.lv2/a-comp.c
+++ b/libs/plugins/a-comp.lv2/a-comp.c
@@ -27,6 +27,10 @@
 #define ACOMP_URI		"urn:ardour:a-comp"
 #define ACOMP_STEREO_URI	"urn:ardour:a-comp#stereo"
 
+#ifndef M_PI
+#  define M_PI 3.14159265358979323846
+#endif
+
 typedef enum {
 	ACOMP_ATTACK = 0,
 	ACOMP_RELEASE,
@@ -38,30 +42,14 @@ typedef enum {
 	ACOMP_GAINR,
 	ACOMP_OUTLEVEL,
 	ACOMP_SIDECHAIN,
+	ACOMP_ENABLE,
 
-	ACOMP_INPUT,
-	ACOMP_SC,
-	ACOMP_OUTPUT,
-} PortIndexMono;
-
-typedef enum {
-	ACOMP_STEREO_ATTACK = 0,
-	ACOMP_STEREO_RELEASE,
-	ACOMP_STEREO_KNEE,
-	ACOMP_STEREO_RATIO,
-	ACOMP_STEREO_THRESHOLD,
-	ACOMP_STEREO_MAKEUP,
-
-	ACOMP_STEREO_GAINR,
-	ACOMP_STEREO_OUTLEVEL,
-	ACOMP_STEREO_SIDECHAIN,
-
-	ACOMP_STEREO_INPUT0,
-	ACOMP_STEREO_INPUT1,
-	ACOMP_STEREO_SC,
-	ACOMP_STEREO_OUTPUT0,
-	ACOMP_STEREO_OUTPUT1,
-} PortIndexStereo;
+	ACOMP_A0,
+	ACOMP_A1,
+	ACOMP_A2,
+	ACOMP_A3,
+	ACOMP_A4,
+} PortIndex;
 
 typedef struct {
 	float* attack;
@@ -74,6 +62,7 @@ typedef struct {
 	float* gainr;
 	float* outlevel;
 	float* sidechain;
+	float* enable;
 
 	float* input0;
 	float* input1;
@@ -86,6 +75,9 @@ typedef struct {
 	float old_y1;
 	float old_yg;
 
+	float makeup_gain;
+	float tau;
+
 #ifdef LV2_EXTENDED
 	LV2_Inline_Display_Image_Surface surf;
 	bool                     need_expose;
@@ -124,6 +116,7 @@ instantiate(const LV2_Descriptor* descriptor,
 
 	acomp->srate = rate;
 	acomp->old_yl=acomp->old_y1=acomp->old_yg=0.f;
+	acomp->tau = (1.0 - exp (-2.f * M_PI * 25.f / acomp->srate));
 #ifdef LV2_EXTENDED
 	acomp->need_expose = true;
 #endif
@@ -133,101 +126,96 @@ instantiate(const LV2_Descriptor* descriptor,
 
 
 static void
-connect_port_mono(LV2_Handle instance,
+connect_port(LV2_Handle instance,
              uint32_t port,
              void* data)
 {
 	AComp* acomp = (AComp*)instance;
 
-	switch ((PortIndexMono)port) {
-	case ACOMP_ATTACK:
-		acomp->attack = (float*)data;
-		break;
-	case ACOMP_RELEASE:
-		acomp->release = (float*)data;
-		break;
-	case ACOMP_KNEE:
-		acomp->knee = (float*)data;
-		break;
-	case ACOMP_RATIO:
-		acomp->ratio = (float*)data;
-		break;
-	case ACOMP_THRESHOLD:
-		acomp->thresdb = (float*)data;
-		break;
-	case ACOMP_MAKEUP:
-		acomp->makeup = (float*)data;
-		break;
-	case ACOMP_GAINR:
-		acomp->gainr = (float*)data;
-		break;
-	case ACOMP_OUTLEVEL:
-		acomp->outlevel = (float*)data;
-		break;
-	case ACOMP_SIDECHAIN:
-		acomp->sidechain = (float*)data;
-		break;
-	case ACOMP_INPUT:
-		acomp->input0 = (float*)data;
-		break;
-	case ACOMP_SC:
-		acomp->sc = (float*)data;
-		break;
-	case ACOMP_OUTPUT:
-		acomp->output0 = (float*)data;
-		break;
+	switch ((PortIndex)port) {
+		case ACOMP_ATTACK:
+			acomp->attack = (float*)data;
+			break;
+		case ACOMP_RELEASE:
+			acomp->release = (float*)data;
+			break;
+		case ACOMP_KNEE:
+			acomp->knee = (float*)data;
+			break;
+		case ACOMP_RATIO:
+			acomp->ratio = (float*)data;
+			break;
+		case ACOMP_THRESHOLD:
+			acomp->thresdb = (float*)data;
+			break;
+		case ACOMP_MAKEUP:
+			acomp->makeup = (float*)data;
+			break;
+		case ACOMP_GAINR:
+			acomp->gainr = (float*)data;
+			break;
+		case ACOMP_OUTLEVEL:
+			acomp->outlevel = (float*)data;
+			break;
+		case ACOMP_SIDECHAIN:
+			acomp->sidechain = (float*)data;
+			break;
+		case ACOMP_ENABLE:
+			acomp->enable = (float*)data;
+			break;
+		default:
+			break;
 	}
 }
 
 static void
-connect_port_stereo(LV2_Handle instance,
+connect_mono(LV2_Handle instance,
              uint32_t port,
              void* data)
 {
 	AComp* acomp = (AComp*)instance;
-
-	switch ((PortIndexStereo)port) {
-	case ACOMP_STEREO_ATTACK:
-		acomp->attack = (float*)data;
-		break;
-	case ACOMP_STEREO_RELEASE:
-		acomp->release = (float*)data;
-		break;
-	case ACOMP_STEREO_KNEE:
-		acomp->knee = (float*)data;
-		break;
-	case ACOMP_STEREO_RATIO:
-		acomp->ratio = (float*)data;
-		break;
-	case ACOMP_STEREO_THRESHOLD:
-		acomp->thresdb = (float*)data;
-		break;
-	case ACOMP_STEREO_MAKEUP:
-		acomp->makeup = (float*)data;
-		break;
-	case ACOMP_STEREO_GAINR:
-		acomp->gainr = (float*)data;
-		break;
-	case ACOMP_STEREO_OUTLEVEL:
-		acomp->outlevel = (float*)data;
-		break;
-	case ACOMP_STEREO_SIDECHAIN:
-		acomp->sidechain = (float*)data;
-		break;
-	case ACOMP_STEREO_INPUT0:
-		acomp->input0 = (float*)data;
-		break;
-	case ACOMP_STEREO_INPUT1:
-		acomp->input1 = (float*)data;
-		break;
-	case ACOMP_STEREO_SC:
-		acomp->sc = (float*)data;
-		break;
-	case ACOMP_STEREO_OUTPUT0:
-		acomp->output0 = (float*)data;
+	connect_port (instance, port, data);
+
+	switch ((PortIndex)port) {
+		case ACOMP_A0:
+			acomp->input0 = (float*)data;
+			break;
+		case ACOMP_A1:
+			acomp->sc = (float*)data;
+			break;
+		case ACOMP_A2:
+			acomp->output0 = (float*)data;
+			break;
+	default:
 		break;
-	case ACOMP_STEREO_OUTPUT1:
-		acomp->output1 = (float*)data;
+	}
+}
+
+static void
+connect_stereo(LV2_Handle instance,
+               uint32_t port,
+               void* data)
+{
+	AComp* acomp = (AComp*)instance;
+	connect_port (instance, port, data);
+
+	switch ((PortIndex)port) {
+		case ACOMP_A0:
+			acomp->input0 = (float*)data;
+			break;
+		case ACOMP_A1:
+			acomp->input1 = (float*)data;
+			break;
+		case ACOMP_A2:
+			acomp->sc = (float*)data;
+			break;
+		case ACOMP_A3:
+			acomp->output0 = (float*)data;
+			break;
+		case ACOMP_A4:
+			acomp->output1 = (float*)data;
+			break;
+	default:
 		break;
 	}
 }
@@ -280,13 +268,24 @@ run_mono(LV2_Handle instance, uint32_t n_samples)
 	float lgaininp = 0.f;
 	float Lgain = 1.f;
 	float Lxg, Lxl, Lyg, Lyl, Ly1;
-	int usesidechain = (*(acomp->sidechain) < 0.5) ? 0 : 1;
+	int usesidechain = (*(acomp->sidechain) <= 0.f) ? 0 : 1;
 	uint32_t i;
 	float ingain;
 	float in0;
 	float sc0;
-	float ratio = *(acomp->ratio);
-	float thresdb = *(acomp->thresdb);
+
+	float ratio = *acomp->ratio;
+	float thresdb = *acomp->thresdb;
+	float makeup_target = from_dB(*acomp->makeup);
+	float makeup_gain = acomp->makeup_gain;
+
+	const const float tau = acomp->tau;
+
+	if (*acomp->enable <= 0) {
+		ratio = 1.f;
+		thresdb = 0.f;
+		makeup_target = 1.f;
+	}
 
 #ifdef LV2_EXTENDED
 	if (acomp->v_knee != *acomp->knee) {
@@ -294,13 +293,13 @@ run_mono(LV2_Handle instance, uint32_t n_samples)
 		acomp->need_expose = true;
 	}
 
-	if (acomp->v_ratio != *acomp->ratio) {
-		acomp->v_ratio = *acomp->ratio;
+	if (acomp->v_ratio != ratio) {
+		acomp->v_ratio = ratio;
 		acomp->need_expose = true;
 	}
 
-	if (acomp->v_thresdb != *acomp->thresdb) {
-		acomp->v_thresdb = *acomp->thresdb;
+	if (acomp->v_thresdb != thresdb) {
+		acomp->v_thresdb = thresdb;
 		acomp->need_expose = true;
 	}
 #endif
@@ -341,7 +340,9 @@ run_mono(LV2_Handle instance, uint32_t n_samples)
 		*(acomp->gainr) = Lyl;
 
 		lgaininp = in0 * Lgain;
-		output[i] = lgaininp * from_dB(*(acomp->makeup));
+
+		makeup_gain += tau * (makeup_target - makeup_gain) + 1e-12;
+		output[i] = lgaininp * makeup_gain;
 
 		max = (fabsf(output[i]) > max) ? fabsf(output[i]) : sanitize_denormal(max);
 
@@ -353,6 +354,7 @@ run_mono(LV2_Handle instance, uint32_t n_samples)
 	}
 
 	*(acomp->outlevel) = (max < 0.0056f) ? -45.f : to_dB(max);
+	acomp->makeup_gain = makeup_gain;
 
 #ifdef LV2_EXTENDED
 	acomp->v_lvl += .1 * (in_peak - acomp->v_lvl);  // crude LPF TODO use n_samples/rate TC
@@ -362,7 +364,7 @@ run_mono(LV2_Handle instance, uint32_t n_samples)
 		// >= 1dB difference
 		acomp->need_expose = true;
 		acomp->v_lvl_in = v_lvl_in;
-		acomp->v_lvl_out = v_lvl_out - *acomp->makeup;
+		acomp->v_lvl_out = v_lvl_out - to_dB(makeup_gain);
 	}
 	if (acomp->need_expose && acomp->queue_draw) {
 		acomp->need_expose = false;
@@ -393,15 +395,26 @@ run_stereo(LV2_Handle instance, uint32_t n_samples)
 	float rgaininp = 0.f;
 	float Lgain = 1.f;
 	float Lxg, Lxl, Lyg, Lyl, Ly1;
-	int usesidechain = (*(acomp->sidechain) < 0.5) ? 0 : 1;
+	int usesidechain = (*(acomp->sidechain) <= 0.f) ? 0 : 1;
 	uint32_t i;
 	float ingain;
 	float in0;
 	float in1;
 	float sc0;
 	float maxabslr;
-	float ratio = *(acomp->ratio);
-	float thresdb = *(acomp->thresdb);
+
+	float ratio = *acomp->ratio;
+	float thresdb = *acomp->thresdb;
+	float makeup_target = from_dB(*acomp->makeup);
+	float makeup_gain = acomp->makeup_gain;
+
+	const const float tau = acomp->tau;
+
+	if (*acomp->enable <= 0) {
+		ratio = 1.f;
+		thresdb = 0.f;
+		makeup_target = 1.f;
+	}
 
 #ifdef LV2_EXTENDED
 	if (acomp->v_knee != *acomp->knee) {
@@ -409,13 +422,13 @@ run_stereo(LV2_Handle instance, uint32_t n_samples)
 		acomp->need_expose = true;
 	}
 
-	if (acomp->v_ratio != *acomp->ratio) {
-		acomp->v_ratio = *acomp->ratio;
+	if (acomp->v_ratio != ratio) {
+		acomp->v_ratio = ratio;
 		acomp->need_expose = true;
 	}
 
-	if (acomp->v_thresdb != *acomp->thresdb) {
-		acomp->v_thresdb = *acomp->thresdb;
+	if (acomp->v_thresdb != thresdb) {
+		acomp->v_thresdb = thresdb;
 		acomp->need_expose = true;
 	}
 #endif
@@ -459,8 +472,11 @@ run_stereo(LV2_Handle instance, uint32_t n_samples)
 
 		lgaininp = in0 * Lgain;
 		rgaininp = in1 * Lgain;
-		output0[i] = lgaininp * from_dB(*(acomp->makeup));
-		output1[i] = rgaininp * from_dB(*(acomp->makeup));
+
+		makeup_gain += tau * (makeup_target - makeup_gain) + 1e-12;
+
+		output0[i] = lgaininp * makeup_gain;
+		output1[i] = rgaininp * makeup_gain;
 
 		max = (fmaxf(fabs(output0[i]), fabs(output1[i])) > max) ? fmaxf(fabs(output0[i]), fabs(output1[i])) : sanitize_denormal(max);
 
@@ -472,6 +488,7 @@ run_stereo(LV2_Handle instance, uint32_t n_samples)
 	}
 
 	*(acomp->outlevel) = (max < 0.0056f) ? -45.f : to_dB(max);
+	acomp->makeup_gain = makeup_gain;
 
 #ifdef LV2_EXTENDED
 	acomp->v_lvl += .1 * (in_peak - acomp->v_lvl);  // crude LPF TODO use n_samples/rate TC
@@ -481,7 +498,7 @@ run_stereo(LV2_Handle instance, uint32_t n_samples)
 		// >= 1dB difference
 		acomp->need_expose = true;
 		acomp->v_lvl_in = v_lvl_in;
-		acomp->v_lvl_out = v_lvl_out - *acomp->makeup;
+		acomp->v_lvl_out = v_lvl_out - to_dB(makeup_gain);
 	}
 	if (acomp->need_expose && acomp->queue_draw) {
 		acomp->need_expose = false;
@@ -664,7 +681,7 @@ extension_data(const char* uri)
 static const LV2_Descriptor descriptor_mono = {
 	ACOMP_URI,
 	instantiate,
-	connect_port_mono,
+	connect_mono,
 	activate,
 	run_mono,
 	deactivate,
@@ -675,7 +692,7 @@ static const LV2_Descriptor descriptor_mono = {
 static const LV2_Descriptor descriptor_stereo = {
 	ACOMP_STEREO_URI,
 	instantiate,
-	connect_port_stereo,
+	connect_stereo,
 	activate,
 	run_stereo,
 	deactivate,
diff --git a/libs/plugins/a-comp.lv2/a-comp.ttl.in b/libs/plugins/a-comp.lv2/a-comp.ttl.in
index 7a962fa..438da89 100644
--- a/libs/plugins/a-comp.lv2/a-comp.ttl.in
+++ b/libs/plugins/a-comp.lv2/a-comp.ttl.in
@@ -109,25 +109,36 @@
         lv2:default 0.000000 ;
         lv2:minimum 0.000000 ;
         lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
-    ] ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
+    ] ,
+    [
+        a lv2:InputPort, lv2:ControlPort ;
+        lv2:index 9 ;
+        lv2:name "Enable" ;
+        lv2:symbol "enable" ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
+        lv2:designation <http://ardour.org/lv2/processing#enable>;
+    ];
 
     lv2:port [
         a lv2:InputPort, lv2:AudioPort ;
-        lv2:index 9 ;
+        lv2:index 10 ;
         lv2:symbol "lv2_audio_in_1" ;
         lv2:name "Audio Input 1" ;
     ] ,
     [
         a lv2:InputPort, lv2:AudioPort ;
-        lv2:index 10 ;
+        lv2:index 11 ;
         lv2:symbol "lv2_sidechain_in" ;
         lv2:name "Sidechain Input" ;
         lv2:portProperty lv2:isSideChain ;
     ],
     [
         a lv2:OutputPort, lv2:AudioPort ;
-        lv2:index 11 ;
+        lv2:index 12 ;
         lv2:symbol "lv2_audio_out_1" ;
         lv2:name "Audio Output 1" ;
     ] ;
diff --git a/libs/plugins/a-delay.lv2/a-delay.c b/libs/plugins/a-delay.lv2/a-delay.c
index 8ad4265..b6f7663 100644
--- a/libs/plugins/a-delay.lv2/a-delay.c
+++ b/libs/plugins/a-delay.lv2/a-delay.c
@@ -45,8 +45,8 @@ typedef enum {
 	ADELAY_FEEDBACK,
 	ADELAY_LPF,
 	ADELAY_GAIN,
-	
 	ADELAY_DELAYTIME,
+	ADELAY_ENABLE,
 } PortIndex;
 
 
@@ -79,6 +79,7 @@ typedef struct {
 	float* gain;
 	
 	float* delaytime;
+	float* enable;
 
 	float srate;
 	float bpm;
@@ -154,8 +155,7 @@ instantiate(const LV2_Descriptor* descriptor,
 
 	adelay->srate = rate;
 	adelay->bpmvalid = 0;
-	// 25Hz time constant @ 64fpp
-	adelay->tau = (1.0 - exp(-2.0 * M_PI * 64. * 25. / adelay->srate));
+	adelay->tau = (1.0 - exp (-2.f * M_PI * 25.f / adelay->srate));
 
 	return (LV2_Handle)adelay;
 }
@@ -204,6 +204,9 @@ connect_port(LV2_Handle instance,
 	case ADELAY_DELAYTIME:
 		adelay->delaytime = (float*)data;
 		break;
+	case ADELAY_ENABLE:
+		adelay->enable = (float*)data;
+		break;
 	}
 }
 
@@ -352,8 +355,18 @@ run(LV2_Handle instance, uint32_t n_samples)
 	const float* const input = adelay->input;
 	float* const output = adelay->output;
 
-	float srate = adelay->srate;
-	float tau = adelay->tau;
+	const float srate = adelay->srate;
+	const float tau = adelay->tau;
+
+	float wetdry_target = *adelay->wetdry / 100.f;
+	float gain_target = from_dB(*adelay->gain);
+	float wetdry = adelay->wetdryold;
+	float gain = adelay->gainold;
+
+	if (*adelay->enable <= 0) {
+		wetdry_target = 0.f;
+		gain_target = 1.0;
+	}
 
 	uint32_t i;
 	float in;
@@ -362,6 +375,8 @@ run(LV2_Handle instance, uint32_t n_samples)
 	float inv;
 	float xfade;
 	int recalc;
+
+	// TODO LPF
 	if (*(adelay->inv) < 0.5) {
 		inv = -1.f;
 	} else {
@@ -385,10 +400,8 @@ run(LV2_Handle instance, uint32_t n_samples)
 		recalc = 1;
 	}
 	if (!is_eq(adelay->lpfold, *adelay->lpf, 0.1)) {
-		adelay->lpfold += tau * (*adelay->lpf - adelay->lpfold);
-		recalc = 1;
-	}
-	if (*(adelay->gain) != adelay->gainold) {
+		float  tc = (1.0 - exp (-2.f * M_PI * n_samples * 25.f / adelay->srate));
+		adelay->lpfold += tc * (*adelay->lpf - adelay->lpfold);
 		recalc = 1;
 	}
 	
@@ -419,20 +432,29 @@ run(LV2_Handle instance, uint32_t n_samples)
 			if (p<0) p += MAX_DELAY;
 			adelay->fbstate += adelay->z[p] * xfade;
 		}
-		output[i] = from_dB(*(adelay->gain)) * ((100.-*(adelay->wetdry)) / 100. * in + *(adelay->wetdry) / 100. * -inv * runfilter(adelay, adelay->fbstate));
+
+		wetdry += tau * (wetdry_target - wetdry) + 1e-12;
+		gain += tau * (gain_target - gain) + 1e-12;
+
+		output[i] = (1.f - wetdry) * in;
+		output[i] += wetdry * -inv * runfilter(adelay, adelay->fbstate);
+		output[i] *= gain;
+
 		if (++(adelay->posz) >= MAX_DELAY) {
 			adelay->posz = 0;
 		}
 	}
+
 	adelay->feedbackold = *(adelay->feedback);
 	adelay->divisorold = *(adelay->divisor);
-	adelay->gainold = *(adelay->gain);
 	adelay->invertold = *(adelay->inv);
 	adelay->timeold = *(adelay->time);
 	adelay->syncold = *(adelay->sync);
-	adelay->wetdryold = *(adelay->wetdry);
+	adelay->wetdryold = wetdry;
+	adelay->gainold = gain;
 	adelay->delaytimeold = *(adelay->delaytime);
 	adelay->delaysamplesold = delaysamples;
+
 	if (recalc) {
 		tmp = adelay->active;
 		adelay->active = adelay->next;
diff --git a/libs/plugins/a-delay.lv2/a-delay.ttl.in b/libs/plugins/a-delay.lv2/a-delay.ttl.in
index ee90c50..5086f53 100644
--- a/libs/plugins/a-delay.lv2/a-delay.ttl.in
+++ b/libs/plugins/a-delay.lv2/a-delay.ttl.in
@@ -50,20 +50,20 @@
         lv2:index 3 ;
         lv2:name "Invert" ;
         lv2:symbol "inv" ;
-        lv2:default 0.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 0 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
     ] ,
     [
         a lv2:InputPort, lv2:ControlPort ;
         lv2:index 4 ;
         lv2:name "Sync BPM" ;
         lv2:symbol "sync" ;
-        lv2:default 0.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 0 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
     ] ,
     [
         a lv2:InputPort, lv2:ControlPort ;
@@ -148,6 +148,17 @@
         lv2:minimum 1.000000 ;
         lv2:maximum 8000.000000 ;
         unit:unit unit:ms ;
+    ] ,
+    [
+        a lv2:InputPort, lv2:ControlPort ;
+        lv2:index 12 ;
+        lv2:name "Enable" ;
+        lv2:symbol "enable" ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
+        lv2:designation <http://ardour.org/lv2/processing#enable>;
     ] ;
 
     rdfs:comment """
diff --git a/libs/plugins/a-eq.lv2/a-eq.c b/libs/plugins/a-eq.lv2/a-eq.c
index bb9840d..d286552 100644
--- a/libs/plugins/a-eq.lv2/a-eq.c
+++ b/libs/plugins/a-eq.lv2/a-eq.c
@@ -23,6 +23,13 @@
 #include <stdbool.h>
 #include <stdio.h>
 
+#ifdef COMPILER_MSVC
+#include <float.h>
+#define isfinite_local(val) (bool)_finite((double)val)
+#else
+#define isfinite_local isfinite
+#endif
+
 #include "lv2/lv2plug.in/ns/lv2core/lv2.h"
 
 #ifdef LV2_EXTENDED
@@ -60,6 +67,7 @@ typedef enum {
 	AEQ_FILTOG3,
 	AEQ_FILTOG4,
 	AEQ_FILTOGH,
+	AEQ_ENABLE,
 	AEQ_INPUT,
 	AEQ_OUTPUT,
 } PortIndex;
@@ -91,12 +99,20 @@ static void linear_svf_reset(struct linear_svf *self)
 	self->s[0] = self->s[1] = 0.0;
 }
 
+static void linear_svf_protect(struct linear_svf *self)
+{
+	if (!isfinite_local (self->s[0]) || !isfinite_local (self->s[1])) {
+		linear_svf_reset (self);
+	}
+}
+
 typedef struct {
 	float* f0[BANDS];
 	float* g[BANDS];
 	float* bw[BANDS];
 	float* filtog[BANDS];
 	float* master;
+	float* enable;
 
 	float srate;
 	float tau;
@@ -128,7 +144,7 @@ instantiate(const LV2_Descriptor* descriptor,
 {
 	Aeq* aeq = (Aeq*)calloc(1, sizeof(Aeq));
 	aeq->srate = rate;
-	aeq->tau = (1.0 - exp(-2.0 * M_PI * 64 * 25. / aeq->srate)); // 25Hz time constant @ 64fpp
+	aeq->tau = 1.0 - expf (-2.f * M_PI * 64.f * 25.f / aeq->srate); // 25Hz time constant @ 64fpp
 
 #ifdef LV2_EXTENDED
 	for (int i=0; features[i]; ++i) {
@@ -157,6 +173,9 @@ connect_port(LV2_Handle instance,
 	Aeq* aeq = (Aeq*)instance;
 
 	switch ((PortIndex)port) {
+	case AEQ_ENABLE:
+		aeq->enable = (float*)data;
+		break;
 	case AEQ_FREQL:
 		aeq->f0[0] = (float*)data;
 		break;
@@ -355,16 +374,17 @@ run(LV2_Handle instance, uint32_t n_samples)
 	const float tau = aeq->tau;
 	uint32_t offset = 0;
 
+	const float target_gain = *aeq->enable <= 0 ? 0 : *aeq->master; // dB
+
 	while (n_samples > 0) {
 		uint32_t block = n_samples;
 		bool any_changed = false;
 
-		// TODO global en/disable
-		if (!is_eq(aeq->v_master, *aeq->master, 0.1)) {
-			aeq->v_master += tau * (*aeq->master - aeq->v_master);
+		if (!is_eq(aeq->v_master, target_gain, 0.1)) {
+			aeq->v_master += tau * (target_gain - aeq->v_master);
 			any_changed = true;
 		} else {
-			aeq->v_master = *aeq->master;
+			aeq->v_master = target_gain;
 		}
 
 		for (int i = 0; i < BANDS; ++i) {
@@ -377,7 +397,7 @@ run(LV2_Handle instance, uint32_t n_samples)
 				aeq->v_f0[i] = *aeq->f0[i];
 			}
 
-			if (*aeq->filtog[i] <= 0) {
+			if (*aeq->filtog[i] <= 0 || *aeq->enable <= 0) {
 				if (!is_eq(aeq->v_g[i], 0.f, 0.05)) {
 					aeq->v_g[i] += tau * (0.0 - aeq->v_g[i]);
 					changed = true;
@@ -420,12 +440,16 @@ run(LV2_Handle instance, uint32_t n_samples)
 			for (uint32_t j = 0; j < BANDS; j++) {
 				out = run_linear_svf(&aeq->v_filter[j], out);
 			}
-			output[i + offset] = out * from_dB(*(aeq->master));
+			output[i + offset] = out * from_dB(aeq->v_master);
 		}
 		n_samples -= block;
 		offset += block;
 	}
 
+	for (uint32_t j = 0; j < BANDS; j++) {
+		linear_svf_protect(&aeq->v_filter[j]);
+	}
+
 #ifdef LV2_EXTENDED
 	if (aeq->need_expose && aeq->queue_draw) {
 		aeq->need_expose = false;
diff --git a/libs/plugins/a-eq.lv2/a-eq.ttl.in b/libs/plugins/a-eq.lv2/a-eq.ttl.in
index eafd2fa..21c6b70 100644
--- a/libs/plugins/a-eq.lv2/a-eq.ttl.in
+++ b/libs/plugins/a-eq.lv2/a-eq.ttl.in
@@ -210,72 +210,83 @@ unit:hz0
         lv2:index 17 ;
         lv2:name "Filter L" ;
         lv2:symbol "filtogl" ;
-        lv2:default 1.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
     ],
     [
         a lv2:InputPort, lv2:ControlPort ;
         lv2:index 18 ;
         lv2:name "Filter 1" ;
         lv2:symbol "filtog1" ;
-        lv2:default 1.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
     ],
     [
         a lv2:InputPort, lv2:ControlPort ;
         lv2:index 19 ;
         lv2:name "Filter 2" ;
         lv2:symbol "filtog2" ;
-        lv2:default 1.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
     ],
     [
         a lv2:InputPort, lv2:ControlPort ;
         lv2:index 20 ;
         lv2:name "Filter 3" ;
         lv2:symbol "filtog3" ;
-        lv2:default 1.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
     ],
     [
         a lv2:InputPort, lv2:ControlPort ;
         lv2:index 21 ;
         lv2:name "Filter 4" ;
         lv2:symbol "filtog4" ;
-        lv2:default 1.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
     ],
     [
         a lv2:InputPort, lv2:ControlPort ;
         lv2:index 22 ;
         lv2:name "Filter H" ;
         lv2:symbol "filtogh" ;
-        lv2:default 1.000000 ;
-        lv2:minimum 0.000000 ;
-        lv2:maximum 1.000000 ;
-        lv2:portProperty lv2:toggled ;
-    ] ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
+    ],
+    [
+        a lv2:InputPort, lv2:ControlPort ;
+        lv2:index 23 ;
+        lv2:name "Enable" ;
+        lv2:symbol "enable" ;
+        lv2:default 1 ;
+        lv2:minimum 0 ;
+        lv2:maximum 1 ;
+        lv2:portProperty lv2:integer, lv2:toggled ;
+        lv2:designation <http://ardour.org/lv2/processing#enable>;
+    ];
 
     lv2:port [
         a lv2:InputPort, lv2:AudioPort ;
-        lv2:index 23 ;
+        lv2:index 24 ;
         lv2:symbol "in_1" ;
         lv2:name "Audio Input 1" ;
     ] ;
 
     lv2:port [
         a lv2:OutputPort, lv2:AudioPort ;
-        lv2:index 24 ;
+        lv2:index 25 ;
         lv2:symbol "out_1" ;
         lv2:name "Audio Output 1" ;
     ] ;
diff --git a/libs/plugins/a-reverb.lv2/a-reverb.c b/libs/plugins/a-reverb.lv2/a-reverb.c
index e2dd969..40811bd 100644
--- a/libs/plugins/a-reverb.lv2/a-reverb.c
+++ b/libs/plugins/a-reverb.lv2/a-reverb.c
@@ -32,6 +32,13 @@
 #define RV_NZ 7
 #define DENORMAL_PROTECT (1e-14)
 
+#ifdef COMPILER_MSVC
+#include <float.h>
+#define isfinite_local(val) (bool)_finite((double)val)
+#else
+#define isfinite_local isfinite
+#endif
+
 typedef struct {
 	float* delays[2][RV_NZ]; /**< delay line buffer */
 
@@ -164,10 +171,15 @@ reverb (b_reverb* r,
 	for (size_t i = 0; i < n_samples; ++i) {
 		int j;
 		float y;
-		const float xo0 = *xp0++;
-		const float xo1 = *xp1++;
+		float xo0 = *xp0++;
+		float xo1 = *xp1++;
+		if (!isfinite_local(xo0) || fabsf (xo0) > 10.f) { xo0 = 0; }
+		if (!isfinite_local(xo1) || fabsf (xo1) > 10.f) { xo1 = 0; }
+		xo0 += DENORMAL_PROTECT;
+		xo1 += DENORMAL_PROTECT;
 		const float x0 = y_1_0 + (inputGain * xo0);
 		const float x1 = y_1_1 + (inputGain * xo1);
+
 		float xa = 0.0;
 		float xb = 0.0;
 		/* First we do four feedback comb filters (ie parallel delay lines,
@@ -220,6 +232,11 @@ reverb (b_reverb* r,
 		*yp1++ = ((wet * y) + (dry * xo1));
 	}
 
+	if (!isfinite_local(y_1_0)) { y_1_0 = 0; }
+	if (!isfinite_local(yy1_1)) { yy1_0 = 0; }
+	if (!isfinite_local(y_1_1)) { y_1_1 = 0; }
+	if (!isfinite_local(yy1_1)) { yy1_1 = 0; }
+
 	r->y_1_0 = y_1_0 + DENORMAL_PROTECT;
 	r->yy1_0 = yy1_0 + DENORMAL_PROTECT;
 	r->y_1_1 = y_1_1 + DENORMAL_PROTECT;
@@ -239,6 +256,7 @@ typedef enum {
 	AR_OUTPUT1    = 3,
 	AR_MIX        = 4,
 	AR_ROOMSZ     = 5,
+	AR_ENABLE     = 6,
 } PortIndex;
 
 typedef struct {
@@ -249,10 +267,12 @@ typedef struct {
 
 	float* mix;
 	float* roomsz;
+	float* enable;
 
 	float v_mix;
 	float v_roomsz;
 	float srate;
+	float tau;
 
 	b_reverb r;
 } AReverb;
@@ -275,6 +295,7 @@ instantiate (const LV2_Descriptor*     descriptor,
 	self->v_roomsz = 0.75;
 	self->v_mix = 0.1;
 	self->srate = rate;
+	self->tau = 1.f - expf (-2.f * M_PI * 64.f * 15.f / self->srate); // 15Hz, 64fpp
 
 	return (LV2_Handle)self;
 }
@@ -305,6 +326,9 @@ connect_port (LV2_Handle instance,
 		case AR_ROOMSZ:
 			self->roomsz = (float*)data;
 			break;
+		case AR_ENABLE:
+			self->enable = (float*)data;
+			break;
 	}
 }
 
@@ -318,23 +342,52 @@ run (LV2_Handle instance, uint32_t n_samples)
 	float* const      output0 = self->output0;
 	float* const      output1 = self->output1;
 
-	// 15Hz time constant
-	const float tau = (1.0 - exp(-2.0 * M_PI * n_samples * 15. / self->srate));
+	const float tau = self->tau;
+	const float mix = *self->enable <= 0 ? 0 : *self->mix;
+
+	uint32_t remain = n_samples;
+	uint32_t offset = 0;
+	uint32_t iterpolate = 0;
 
-	if (*self->mix != self->v_mix) {
-		self->v_mix += tau * ( *self->mix - self->v_mix);
-		self->r.wet = self->v_mix;
-		self->r.dry = 1.0 - self->v_mix;
+	if (fabsf (mix - self->v_mix) < .01) { // 40dB
+		self->v_mix = mix;
+	} else {
+		iterpolate |= 1;
 	}
-	if (*self->roomsz != self->v_roomsz) {
-		self->v_roomsz += tau * ( *self->roomsz - self->v_roomsz);
-		self->r.gain[0] = 0.773 * self->v_roomsz;
-		self->r.gain[1] = 0.802 * self->v_roomsz;
-		self->r.gain[2] = 0.753 * self->v_roomsz;
-		self->r.gain[3] = 0.733 * self->v_roomsz;
+
+	if (fabsf (*self->roomsz  - self->v_roomsz) < .01) {
+		self->v_roomsz = *self->roomsz;
+	} else {
+		iterpolate |= 2;
 	}
 
-	reverb (&self->r, input0, input1, output0, output1, n_samples);
+	while (remain > 0) {
+		uint32_t p_samples = remain;
+		if (iterpolate && p_samples > 64) {
+			p_samples = 64;
+		}
+
+		if (iterpolate & 1) {
+			self->v_mix += tau * (mix - self->v_mix);
+			self->r.wet = self->v_mix;
+			self->r.dry = 1.0 - self->v_mix;
+		}
+		if (iterpolate & 2) {
+			self->v_roomsz += tau * ( *self->roomsz - self->v_roomsz);
+			self->r.gain[0] = 0.773 * self->v_roomsz;
+			self->r.gain[1] = 0.802 * self->v_roomsz;
+			self->r.gain[2] = 0.753 * self->v_roomsz;
+			self->r.gain[3] = 0.733 * self->v_roomsz;
+		}
+
+		reverb (&self->r,
+				&input0[offset], &input1[offset],
+				&output0[offset], &output1[offset],
+				p_samples);
+
+		offset += p_samples;
+		remain -= p_samples;
+	}
 }
 
 static void
diff --git a/libs/plugins/a-reverb.lv2/a-reverb.ttl.in b/libs/plugins/a-reverb.lv2/a-reverb.ttl.in
index 2f51d49..1932358 100644
--- a/libs/plugins/a-reverb.lv2/a-reverb.ttl.in
+++ b/libs/plugins/a-reverb.lv2/a-reverb.ttl.in
@@ -72,4 +72,15 @@
 		lv2:default 0.5 ;
 		lv2:minimum 0.5 ;
 		lv2:maximum 1.0 ;
-	] .
+	],
+	[
+		a lv2:InputPort, lv2:ControlPort ;
+		lv2:index 6 ;
+		lv2:name "Enable" ;
+		lv2:symbol "enable" ;
+		lv2:default 1 ;
+		lv2:minimum 0 ;
+		lv2:maximum 1 ;
+		lv2:portProperty lv2:integer, lv2:toggled ;
+		lv2:designation <http://ardour.org/lv2/processing#enable>;
+	].
diff --git a/libs/qm-dsp/dsp/tonal/ChangeDetectionFunction.cpp b/libs/qm-dsp/dsp/tonal/ChangeDetectionFunction.cpp
index a572da6..9b1a321 100644
--- a/libs/qm-dsp/dsp/tonal/ChangeDetectionFunction.cpp
+++ b/libs/qm-dsp/dsp/tonal/ChangeDetectionFunction.cpp
@@ -16,7 +16,7 @@
 #include "ChangeDetectionFunction.h"
 
 #ifndef PI
-#define PI (3.14159265358979232846)
+#define PI (3.14159265358979323846)
 #endif
 
 
diff --git a/libs/qm-dsp/dsp/tonal/TonalEstimator.cpp b/libs/qm-dsp/dsp/tonal/TonalEstimator.cpp
index 72b6f85..03e22cc 100644
--- a/libs/qm-dsp/dsp/tonal/TonalEstimator.cpp
+++ b/libs/qm-dsp/dsp/tonal/TonalEstimator.cpp
@@ -19,7 +19,7 @@
 #include <iostream>
 
 #ifndef PI
-#define PI (3.14159265358979232846)
+#define PI (3.14159265358979323846)
 #endif
 
 TonalEstimator::TonalEstimator()
diff --git a/libs/qm-dsp/maths/MathAliases.h b/libs/qm-dsp/maths/MathAliases.h
index 8660129..f597edc 100644
--- a/libs/qm-dsp/maths/MathAliases.h
+++ b/libs/qm-dsp/maths/MathAliases.h
@@ -24,7 +24,7 @@ typedef complex<double> ComplexData;
 
 
 #ifndef PI
-#define PI (3.14159265358979232846)
+#define PI (3.14159265358979323846)
 #endif
 
 #define TWO_PI 		(2. * PI)
diff --git a/scripts/_notch_bank.lua b/scripts/_notch_bank.lua
new file mode 100644
index 0000000..6195418
--- /dev/null
+++ b/scripts/_notch_bank.lua
@@ -0,0 +1,121 @@
+ardour {
+	["type"]    = "dsp",
+	name        = "Notch Bank",
+	category    = "Example",
+	license     = "MIT",
+	author      = "Ardour Lua Task Force",
+	description = [[An Example Filter Plugin]]
+}
+
+-------------------------------------------------------------------
+-- this is a quick/dirty example filter: no de-click, no de-zipper,
+-- no latency reporting,...
+-------------------------------------------------------------------
+
+-- configuration
+local max_stages = 100
+
+-- plugin i/o ports
+function dsp_ioconfig ()
+	return
+	{
+		-- allow any number of I/O as long as port-count matches
+		{ audio_in = -1, audio_out = -1},
+	}
+end
+
+-- plugin control ports
+function dsp_params ()
+	return
+	{
+		{ ["type"] = "input", name = "Base Freq", min = 10, max = 1000, default = 100, unit="Hz", logarithmic = true },
+		{ ["type"] = "input", name = "Quality", min = 1.0, max = 100.0, default = 8.0, logarithmic = true },
+		{ ["type"] = "input", name = "Stages", min = 1.0, max = max_stages, default = 8.0, integer = true },
+	}
+end
+
+
+-- plugin instance state
+local filters = {} -- the biquad filter instances
+local chn = 0 -- configured channel count
+local sample_rate = 0 -- configured sample-rate
+
+-- cached control ports (keep track of changed)
+local freq = 0
+local qual = 0
+
+
+-- dsp_init is called once when instantiating the plugin
+function dsp_init (rate)
+	-- remember the sample-rate
+	sample_rate = rate
+end
+
+-- dsp_configure is called every time when the channel-count
+-- changes, and at least once at the beginning.
+function dsp_configure (ins, outs)
+	assert (ins:n_audio () == outs:n_audio ())
+
+	-- remember audio-channels
+	chn = ins:n_audio ()
+
+	-- set up filter instances for all channels
+	for c = 1, chn do
+		filters[c] = {}
+		for i = 1, max_stages do
+			filters[c][i] = ARDOUR.DSP.Biquad (sample_rate)
+		end
+	end
+end
+
+
+-- the actual process function, called every cycle
+-- ins, outs are audio-data arrays
+--   http://manual.ardour.org/lua-scripting/class_reference/#C:FloatArray
+-- n_samples are the number of samples to process
+function dsp_run (ins, outs, n_samples)
+	-- make sure input and output count matches...
+	assert (#ins == #outs)
+	-- ...and matches the configured number of channels
+	assert (#ins == chn)
+
+	local ctrl = CtrlPorts:array() -- get control parameters as array
+	-- ctrl[1] ..  corresponds to the parameters given in in dsp_params()
+
+	-- test if the plugin-parameters have changed
+	if freq ~= ctrl[1] or qual ~= ctrl[2] then
+		-- remember current settings
+		freq = ctrl[1]
+		qual = ctrl[2]
+		-- re-compute the filter coefficients for all filters
+		for c = 1, chn do -- for each channel
+			for i = 1, max_stages do -- and for each filter stage
+				-- the parameters are    type,  frequency,  quality(bandwidth),  gain
+				-- see http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:DSP:Biquad
+				-- for a list of available types, see
+				-- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR.DSP.Biquad.Type
+				filters[c][i]:compute (ARDOUR.DSP.BiquadType.Notch, freq * i, qual * i, 0)
+			end
+		end
+	end
+
+	-- limit the number of process stages
+	local limit = math.floor (sample_rate / ( 2 * freq )) -- at most up to SR / 2
+	local stages = math.floor (ctrl['3']) -- current user-set parameter
+	if stages < 1 then stages = 1 end -- at least one stage...
+	if stages > max_stages then stages = max_stages end
+	if stages > limit then stages = limit end
+
+	-- process all channels
+	for c = 1, chn do
+		-- when not processing in-place, copy the data from input to output first
+		if not ins[c]:sameinstance (outs[c]) then
+			ARDOUR.DSP.copy_vector (outs[c], ins[c], n_samples)
+		end
+
+		-- run all stages, in-place on the output buffer
+		for i = 1, stages do
+			filters[c][i]:run (outs[c], n_samples)
+		end
+	end
+end
diff --git a/tools/ardour_fluidsynth.diff b/tools/ardour_fluidsynth.diff
index 4aa4083..52db833 100644
--- a/tools/ardour_fluidsynth.diff
+++ b/tools/ardour_fluidsynth.diff
@@ -269,7 +269,7 @@ index cc440aa..8977ed6 100644
    tuning->pitch[key] = pitch;
  }
 diff --git b/libs/fluidsynth/src/fluidsynth_priv.h a/libs/fluidsynth/src/fluidsynth_priv.h
-index faf2772..74b9f4b 100644
+index faf2772..b01618d 100644
 --- b/libs/fluidsynth/src/fluidsynth_priv.h
 +++ a/libs/fluidsynth/src/fluidsynth_priv.h
 @@ -28,14 +28,6 @@
@@ -287,3 +287,25 @@ index faf2772..74b9f4b 100644
  #if HAVE_STRING_H
  #include <string.h>
  #endif
+@@ -113,8 +105,6 @@
+ #endif
+ 
+ #if HAVE_WINDOWS_H
+-#include <winsock2.h>
+-#include <ws2tcpip.h>
+ #include <windows.h>
+ #endif
+ 
+@@ -131,6 +121,12 @@
+ #define STDOUT_FILENO 1
+ #define STDERR_FILENO 2
+ 
++#elif defined _MSC_VER
++
++#define STDIN_FILENO  _fileno(stdin)
++#define STDOUT_FILENO _fileno(stdout)
++#define STDERR_FILENO _fileno(stderr)
++
+ #endif
+ 
+ /* Darwin special defines (taken from config_macosx.h) */
diff --git a/tools/waflib-tar.patch b/tools/waflib-tar.patch
new file mode 100644
index 0000000..9858590
--- /dev/null
+++ b/tools/waflib-tar.patch
@@ -0,0 +1,11 @@
+--- .waf-1.6.11-06ee4b7efbeab1252ed3b11499834d2a/waflib/Scripting.py~	2016-07-14 16:34:10.741387174 -0400
++++ .waf-1.6.11-06ee4b7efbeab1252ed3b11499834d2a/waflib/Scripting.py	2016-08-11 11:45:11.833131519 -0400
+@@ -252,7 +252,7 @@
+ 		return node.abspath()
+ 	def add_tar_file(self,x,tar):
+ 		p=self.get_tar_path(x)
+-		tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+x.path_from(self.base_path))
++		tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+(x.path_from(self.base_path)).decode ('utf8'))
+ 		tinfo.uid=0
+ 		tinfo.gid=0
+ 		tinfo.uname='root'

-- 
ardour Debian packaging



More information about the pkg-multimedia-commits mailing list