diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index ca619e2f31..ed1b8305e6 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -51,6 +51,7 @@ #include "ardour/lv2_plugin.h" #include "ardour/plugin.h" #include "ardour/plugin_insert.h" +#include "ardour/region_fx_plugin.h" #include "ardour/session.h" #include "lv2_plugin_ui.h" @@ -85,7 +86,7 @@ extern VST3PluginUI* create_mac_vst3_gui (std::shared_ptr pib) , cpuload_expander (_("CPU Profile")) , latency_gui (0) , latency_dialog (0) + , tailtime_gui (0) + , tailtime_dialog (0) , eqgui (0) , stats_gui (0) , preset_gui (0) @@ -555,6 +558,7 @@ PlugUIBase::PlugUIBase (std::shared_ptr pib) set_tooltip (_pin_management_button, _("Show Plugin Pin Management Dialog")); set_tooltip (_bypass_button, _("Disable signal processing by the plugin")); set_tooltip (_latency_button, _("Edit Plugin Delay/Latency Compensation")); + set_tooltip (_tailtime_button, _("Edit Plugin tail time")); _no_load_preset = 0; update_preset_list (); @@ -565,6 +569,11 @@ PlugUIBase::PlugUIBase (std::shared_ptr pib) _latency_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::latency_button_clicked)); set_latency_label (); + _tailtime_button.set_icon (ArdourIcon::TailTimeClock); + _tailtime_button.add_elements (ArdourButton::Text); + _tailtime_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::tailtime_button_clicked)); + set_tailtime_label (); + _add_button.set_name ("generic button"); _add_button.set_icon (ArdourIcon::PsetAdd); _add_button.signal_clicked.connect (sigc::mem_fun (*this, &PlugUIBase::add_plugin_setting)); @@ -636,6 +645,11 @@ PlugUIBase::PlugUIBase (std::shared_ptr pib) _pi->LatencyChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::set_latency_label, this), gui_context ()); automation_state_changed (); } + + shared_ptr tt = std::dynamic_pointer_cast (_pib); + if (tt) { + tt->TailTimeChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::set_tailtime_label, this), gui_context ()); + } } PlugUIBase::~PlugUIBase () @@ -645,6 +659,8 @@ PlugUIBase::~PlugUIBase () delete preset_gui; delete latency_gui; delete latency_dialog; + delete tailtime_gui; + delete tailtime_dialog; delete preset_dialog; delete _focus_out_image; @@ -696,6 +712,9 @@ PlugUIBase::add_common_widgets (Gtk::HBox* b, bool with_focus) b->pack_end (_pin_management_button, false, false); b->pack_start (_latency_button, false, false, 4); } + else if (std::dynamic_pointer_cast (_pib)) { + b->pack_start (_tailtime_button, false, false, 4); + } } void @@ -709,13 +728,26 @@ PlugUIBase::set_latency_label () _latency_button.set_text (samples_as_time_string (l, sr, true)); } +void + +PlugUIBase::set_tailtime_label () +{ + auto rfx = std::dynamic_pointer_cast (_pib); /* may be NULL */ + if (!rfx) { + return; + } + samplecnt_t const l = rfx->effective_tailtime (); + float const sr = rfx->session ().sample_rate (); + + _tailtime_button.set_text (samples_as_time_string (l, sr, true)); +} void PlugUIBase::latency_button_clicked () { assert (_pi); if (!latency_gui) { - latency_gui = new LatencyGUI (*(_pi.get ()), _pi->session ().sample_rate (), _pi->session ().get_block_size ()); + latency_gui = new TimeCtlGUI (*(_pi.get ()), _pi->session ().sample_rate (), _pi->session ().get_block_size ()); latency_dialog = new ArdourWindow (_("Edit Latency")); /* use both keep-above and transient for to try cover as many different WM's as possible. @@ -732,6 +764,29 @@ PlugUIBase::latency_button_clicked () latency_dialog->show_all (); } +void +PlugUIBase::tailtime_button_clicked () +{ + auto rfx = std::dynamic_pointer_cast (_pib); /* may be NULL */ + assert (rfx); + if (!tailtime_gui) { + tailtime_gui = new TimeCtlGUI (*dynamic_cast(rfx.get()), rfx->session ().sample_rate (), rfx->session ().get_block_size ()); + tailtime_dialog = new ArdourWindow (_("Edit Tail Time")); + /* use both keep-above and transient for to try cover as many + different WM's as possible. + */ + tailtime_dialog->set_keep_above (true); + Window* win = dynamic_cast (_bypass_button.get_toplevel ()); + if (win) { + tailtime_dialog->set_transient_for (*win); + } + tailtime_dialog->add (*tailtime_gui); + } + + tailtime_gui->refresh (); + tailtime_dialog->show_all (); +} + void PlugUIBase::processor_active_changed (std::weak_ptr weak_p) { diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h index 2963a6f7a9..d4a38259da 100644 --- a/gtk2_ardour/plugin_ui.h +++ b/gtk2_ardour/plugin_ui.h @@ -81,7 +81,7 @@ namespace ArdourWidgets { class FastMeter; } -class LatencyGUI; +class TimeCtlGUI; class ArdourWindow; class PluginEqGui; class PluginLoadStatsGui; @@ -110,6 +110,7 @@ public: void update_preset (); void latency_button_clicked (); + void tailtime_button_clicked (); virtual bool on_window_show(const std::string& /*title*/) { return true; } virtual void on_window_hide() {} @@ -157,6 +158,8 @@ protected: Gtk::Expander cpuload_expander; /** a button which, when clicked, opens the latency GUI */ ArdourWidgets::ArdourButton _latency_button; + /** a button which, when clicked, opens the tailtime GUI */ + ArdourWidgets::ArdourButton _tailtime_button; /** a button which sets all controls' automation setting to Manual */ ArdourWidgets::ArdourButton automation_manual_all_button; /** a button which sets all controls' automation setting to Play */ @@ -169,9 +172,13 @@ protected: ArdourWidgets::ArdourButton automation_latch_all_button; void set_latency_label (); - LatencyGUI* latency_gui; + TimeCtlGUI* latency_gui; ArdourWindow* latency_dialog; + void set_tailtime_label (); + TimeCtlGUI* tailtime_gui; + ArdourWindow* tailtime_dialog; + PluginEqGui* eqgui; PluginLoadStatsGui* stats_gui; PluginPresetsUI* preset_gui; diff --git a/gtk2_ardour/port_insert_ui.cc b/gtk2_ardour/port_insert_ui.cc index 0b22f83d2a..7c88924da7 100644 --- a/gtk2_ardour/port_insert_ui.cc +++ b/gtk2_ardour/port_insert_ui.cc @@ -35,7 +35,7 @@ #include "context_menu_helper.h" #include "gui_thread.h" -#include "latency_gui.h" +#include "timectl_gui.h" #include "port_insert_ui.h" #include "timers.h" #include "utils.h" @@ -282,7 +282,7 @@ PortInsertUI::edit_latency_button_clicked () { assert (_pi); if (!_latency_gui) { - _latency_gui = new LatencyGUI (*(_pi.get ()), _pi->session ().sample_rate (), _pi->session ().get_block_size ()); + _latency_gui = new TimeCtlGUI (*(_pi.get ()), _pi->session ().sample_rate (), _pi->session ().get_block_size ()); _latency_dialog = new ArdourWindow (_("Edit Latency")); /* use both keep-above and transient for to try cover as many different WM's as possible. diff --git a/gtk2_ardour/port_insert_ui.h b/gtk2_ardour/port_insert_ui.h index 6538b7015b..94f4188419 100644 --- a/gtk2_ardour/port_insert_ui.h +++ b/gtk2_ardour/port_insert_ui.h @@ -31,7 +31,7 @@ namespace ARDOUR class PortInsert; } -class LatencyGUI; +class TimeCtlGUI; class MTDM; class PortInsertUI : public Gtk::VBox @@ -78,7 +78,7 @@ private: Gtk::HBox _latency_hbox; Gtk::Window* _parent; - LatencyGUI* _latency_gui; + TimeCtlGUI* _latency_gui; ArdourWindow* _latency_dialog; sigc::connection _latency_timeout; diff --git a/gtk2_ardour/latency_gui.cc b/gtk2_ardour/timectl_gui.cc similarity index 59% rename from gtk2_ardour/latency_gui.cc rename to gtk2_ardour/timectl_gui.cc index e3c8d12dc2..f5f3ae6af1 100644 --- a/gtk2_ardour/latency_gui.cc +++ b/gtk2_ardour/timectl_gui.cc @@ -29,10 +29,12 @@ #include "pbd/unwind.h" #include "ardour/latent.h" +#include "ardour/rc_configuration.h" +#include "ardour/tailtime.h" #include "gtkmm2ext/utils.h" -#include "latency_gui.h" +#include "timectl_gui.h" #include "utils.h" #include "pbd/i18n.h" @@ -50,46 +52,66 @@ static const gchar *_unit_strings[] = { 0 }; -std::vector LatencyGUI::unit_strings; +std::vector TimeCtlGUI::unit_strings; std::string -LatencyBarController::get_label (double&) +TimeCtlBarController::get_label (double&) { return ARDOUR_UI_UTILS::samples_as_time_string ( - _latency_gui->adjustment.get_value(), _latency_gui->sample_rate, true); + _timectl_gui->adjustment.get_value(), _timectl_gui->sample_rate, true); } void -LatencyGUIControllable::set_value (double v, PBD::Controllable::GroupControlDisposition group_override) +TimeCtlGUIControllable::set_value (double v, PBD::Controllable::GroupControlDisposition group_override) { - _latency_gui->adjustment.set_value (v); + _timectl_gui->adjustment.set_value (v); } double -LatencyGUIControllable::get_value () const +TimeCtlGUIControllable::get_value () const { - return _latency_gui->adjustment.get_value (); + return _timectl_gui->adjustment.get_value (); } double -LatencyGUIControllable::lower() const +TimeCtlGUIControllable::lower() const { - return _latency_gui->adjustment.get_lower (); + return _timectl_gui->adjustment.get_lower (); } double -LatencyGUIControllable::upper() const +TimeCtlGUIControllable::upper() const { - return _latency_gui->adjustment.get_upper (); + return _timectl_gui->adjustment.get_upper (); } -LatencyGUI::LatencyGUI (Latent& l, samplepos_t sr, samplepos_t psz) - : _latent (l) +TimeCtlGUI::TimeCtlGUI (Latent& l, samplepos_t sr, samplepos_t psz) + : _latent (&l) + , _tailtime (0) , sample_rate (sr) , period_size (psz) , _ignore_change (false) , adjustment (0, 0.0, sample_rate, 1.0, sample_rate / 1000.0f) /* max 1 second, step by samples, page by msecs */ , bc (adjustment, this) , reset_button (_("Reset")) +{ + init (); +} + +TimeCtlGUI::TimeCtlGUI (TailTime& t, samplepos_t sr, samplepos_t psz) + : _latent (0) + , _tailtime (&t) + , sample_rate (sr) + , period_size (psz) + , _ignore_change (false) + , adjustment (0, 0.0, 20 * sample_rate, sample_rate / 1000.f, 1.0, sample_rate / 2.0f) /* max 20 second, step by msec, page by 0.5 sec */ + , bc (adjustment, this) + , reset_button (_("Reset")) +{ + init (); +} + +void +TimeCtlGUI::init () { Widget* w; @@ -116,17 +138,21 @@ LatencyGUI::LatencyGUI (Latent& l, samplepos_t sr, samplepos_t psz) hbox2.pack_start (plus_button); hbox2.pack_start (units_combo, true, true); - minus_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &LatencyGUI::change_latency_from_button), -1)); - plus_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &LatencyGUI::change_latency_from_button), 1)); - reset_button.signal_clicked().connect (sigc::mem_fun (*this, &LatencyGUI::reset)); + minus_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &TimeCtlGUI::change_from_button), -1)); + plus_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &TimeCtlGUI::change_from_button), 1)); + reset_button.signal_clicked().connect (sigc::mem_fun (*this, &TimeCtlGUI::reset)); /* Limit value to adjustment range (max = sample_rate). * Otherwise if the signal_latency() is larger than the adjustment's max, - * LatencyGUI::finish() would set the adjustment's max value as custom-latency. + * TimeCtlGUI::finish() would set the adjustment's max value as custom-latency. */ - adjustment.set_value (std::min (sample_rate, _latent.signal_latency ())); + if (_latent) { + adjustment.set_value (std::min (sample_rate, _latent->signal_latency ())); + } else if (_tailtime) { + adjustment.set_value (std::min (sample_rate, _tailtime->signal_tailtime ())); + } - adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &LatencyGUI::finish)); + adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &TimeCtlGUI::finish)); bc.set_size_request (-1, 25); bc.set_name (X_("ProcessorControlSlider")); @@ -137,32 +163,46 @@ LatencyGUI::LatencyGUI (Latent& l, samplepos_t sr, samplepos_t psz) } void -LatencyGUI::finish () +TimeCtlGUI::finish () { if (_ignore_change) { return; } samplepos_t new_value = (samplepos_t) adjustment.get_value(); - _latent.set_user_latency (new_value); + if (_latent) { + _latent->set_user_latency (new_value); + } else if (_tailtime) { + _tailtime->set_user_tailtime (new_value); + } } void -LatencyGUI::reset () +TimeCtlGUI::reset () { - _latent.unset_user_latency (); - PBD::Unwinder uw (_ignore_change, true); - adjustment.set_value (std::min (sample_rate, _latent.signal_latency ())); + if (_latent) { + _latent->unset_user_latency (); + PBD::Unwinder uw (_ignore_change, true); + adjustment.set_value (std::min (sample_rate, _latent->signal_latency ())); + } else if (_tailtime) { + _tailtime->unset_user_tailtime (); + PBD::Unwinder uw (_ignore_change, true); + adjustment.set_value (std::min (Config->get_max_tail_samples (), _tailtime->signal_tailtime ())); + } } void -LatencyGUI::refresh () +TimeCtlGUI::refresh () { PBD::Unwinder uw (_ignore_change, true); - adjustment.set_value (std::min (sample_rate, _latent.effective_latency ())); + if (_latent) { + adjustment.set_value (std::min (sample_rate, _latent->effective_latency ())); + } else if (_tailtime) { + adjustment.set_value (std::min (Config->get_max_tail_samples (),_tailtime->effective_tailtime ())); + } } void -LatencyGUI::change_latency_from_button (int dir) +TimeCtlGUI::change_from_button (int dir) { std::string unitstr = units_combo.get_active_text(); double shift = 0.0; diff --git a/gtk2_ardour/latency_gui.h b/gtk2_ardour/timectl_gui.h similarity index 69% rename from gtk2_ardour/latency_gui.h rename to gtk2_ardour/timectl_gui.h index 838e01d848..b20d253ac0 100644 --- a/gtk2_ardour/latency_gui.h +++ b/gtk2_ardour/timectl_gui.h @@ -2,7 +2,7 @@ * Copyright (C) 2007-2017 Paul Davis * Copyright (C) 2009 Carl Hetherington * Copyright (C) 2009 David Robillard - * Copyright (C) 2017-2019 Robin Gareus + * Copyright (C) 2017-2024 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 @@ -19,8 +19,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __gtk2_ardour_latency_gui_h__ -#define __gtk2_ardour_latency_gui_h__ +#ifndef __gtk2_ardour_timectl_gui_h__ +#define __gtk2_ardour_timectl_gui_h__ #include #include @@ -38,16 +38,17 @@ namespace ARDOUR { class Latent; + class TailTime; } -class LatencyGUI; +class TimeCtlGUI; -class LatencyGUIControllable : public PBD::Controllable +class TimeCtlGUIControllable : public PBD::Controllable { public: - LatencyGUIControllable (LatencyGUI* g) + TimeCtlGUIControllable (TimeCtlGUI* g) : PBD::Controllable ("ignoreMe") - , _latency_gui (g) + , _timectl_gui (g) {} void set_value (double v, PBD::Controllable::GroupControlDisposition group_override); @@ -62,44 +63,48 @@ public: } private: - LatencyGUI* _latency_gui; + TimeCtlGUI* _timectl_gui; }; -class LatencyBarController : public ArdourWidgets::BarController +class TimeCtlBarController : public ArdourWidgets::BarController { public: - LatencyBarController (Gtk::Adjustment& adj, LatencyGUI* g) - : BarController (adj, std::shared_ptr (new LatencyGUIControllable (g))) - , _latency_gui (g) + TimeCtlBarController (Gtk::Adjustment& adj, TimeCtlGUI* g) + : BarController (adj, std::shared_ptr (new TimeCtlGUIControllable (g))) + , _timectl_gui (g) { set_digits (0); } private: - LatencyGUI* _latency_gui; + TimeCtlGUI* _timectl_gui; std::string get_label (double&); }; -class LatencyGUI : public Gtk::VBox +class TimeCtlGUI : public Gtk::VBox { public: - LatencyGUI (ARDOUR::Latent&, samplepos_t sample_rate, samplepos_t period_size); - ~LatencyGUI() { } + TimeCtlGUI (ARDOUR::Latent&, samplepos_t sample_rate, samplepos_t period_size); + TimeCtlGUI (ARDOUR::TailTime&, samplepos_t sample_rate, samplepos_t period_size); + ~TimeCtlGUI() { } void refresh (); private: + void init (); void reset (); void finish (); - ARDOUR::Latent& _latent; + ARDOUR::Latent* _latent; + ARDOUR::TailTime* _tailtime; + samplepos_t sample_rate; samplepos_t period_size; bool _ignore_change; Gtk::Adjustment adjustment; - LatencyBarController bc; + TimeCtlBarController bc; Gtk::HBox hbox1; Gtk::HBox hbox2; Gtk::HButtonBox hbbox; @@ -108,12 +113,12 @@ private: Gtk::Button reset_button; Gtk::ComboBoxText units_combo; - void change_latency_from_button (int dir); + void change_from_button (int dir); - friend class LatencyBarController; - friend class LatencyGUIControllable; + friend class TimeCtlBarController; + friend class TimeCtlGUIControllable; static std::vector unit_strings; }; -#endif /* __gtk2_ardour_latency_gui_h__ */ +#endif /* __gtk2_ardour_timectl_gui_h__ */ diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index d1e0f94274..e16141a3f1 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -139,7 +139,6 @@ gtk2_ardour_sources = [ 'hit.cc', 'keyboard.cc', 'keyeditor.cc', - 'latency_gui.cc', 'led.cc', 'level_meter.cc', 'library_download_dialog.cc', @@ -301,6 +300,7 @@ gtk2_ardour_sources = [ 'time_fx_dialog.cc', 'time_info_box.cc', 'time_selection.cc', + 'timectl_gui.cc', 'timers.cc', 'track_record_axis.cc', 'track_selection.cc',