From b2d4280e0fde46b7c51a646702258817230de7dd Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 17 Apr 2024 03:53:30 +0200 Subject: [PATCH] Add support for Region Fx Automation --- gtk2_ardour/audio_region_editor.cc | 147 ++++++++++++++++- gtk2_ardour/audio_region_editor.h | 16 +- gtk2_ardour/audio_region_view.cc | 242 +++++++++++++++++++--------- gtk2_ardour/audio_region_view.h | 25 ++- gtk2_ardour/audio_streamview.cc | 4 +- gtk2_ardour/automation_line.cc | 2 +- gtk2_ardour/automation_line.h | 3 +- gtk2_ardour/editor_canvas_events.cc | 6 +- gtk2_ardour/editor_drag.cc | 8 +- gtk2_ardour/editor_mouse.cc | 2 +- gtk2_ardour/editor_ops.cc | 2 +- gtk2_ardour/luainstance.cc | 7 + gtk2_ardour/region_editor.cc | 8 +- gtk2_ardour/region_editor.h | 3 +- gtk2_ardour/region_fx_line.cc | 92 +++++++++++ gtk2_ardour/region_fx_line.h | 50 ++++++ gtk2_ardour/region_gain_line.cc | 81 ++++------ gtk2_ardour/region_gain_line.h | 14 +- gtk2_ardour/region_view.cc | 2 +- gtk2_ardour/selection.cc | 35 +--- gtk2_ardour/streamview.cc | 4 +- gtk2_ardour/wscript | 1 + 22 files changed, 552 insertions(+), 202 deletions(-) create mode 100644 gtk2_ardour/region_fx_line.cc create mode 100644 gtk2_ardour/region_fx_line.h diff --git a/gtk2_ardour/audio_region_editor.cc b/gtk2_ardour/audio_region_editor.cc index d91390c356..613a395149 100644 --- a/gtk2_ardour/audio_region_editor.cc +++ b/gtk2_ardour/audio_region_editor.cc @@ -33,10 +33,12 @@ #include "ardour/audioregion.h" #include "ardour/session_event.h" #include "ardour/dB.h" +#include "ardour/region_fx_plugin.h" #include "audio_region_editor.h" #include "audio_region_view.h" #include "gui_thread.h" +#include "public_editor.h" #include "pbd/i18n.h" @@ -52,11 +54,13 @@ _peak_amplitude_thread (void* arg) return 0; } -AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr r) - : RegionEditor (s, r) - , _audio_region (r) +AudioRegionEditor::AudioRegionEditor (Session* s, AudioRegionView* arv) + : RegionEditor (s, arv) + , _arv (arv) + , _audio_region (arv->audio_region ()) , gain_adjustment(accurate_coefficient_to_dB(fabsf (_audio_region->scale_amplitude())), -40.0, +40.0, 0.1, 1.0, 0) , _polarity_toggle (_("Invert")) + , _show_on_touch (_("Show on Touch")) , _peak_channel (false) { @@ -87,14 +91,27 @@ AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr r _polarity_label.set_name ("AudioRegionEditorLabel"); _polarity_label.set_text (_("Polarity:")); + _polarity_label.set_alignment (1, 0.5); _table.attach (_polarity_label, 0, 1, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL); _table.attach (_polarity_toggle, 1, 2, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL); ++_table_row; + _region_line_label.set_name ("AudioRegionEditorLabel"); + _region_line_label.set_text (_("Region Line:")); + _region_line_label.set_alignment (1, 0.5); + _table.attach (_region_line_label, 0, 1, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL); + _table.attach (_region_line, 1, 2, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL); + _table.attach (_show_on_touch, 2, 3, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL); + ++_table_row; + gain_changed (); + refill_region_line (); gain_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &AudioRegionEditor::gain_adjustment_changed)); _polarity_toggle.signal_toggled().connect (sigc::mem_fun (*this, &AudioRegionEditor::gain_adjustment_changed)); + _show_on_touch.signal_toggled().connect (sigc::mem_fun (*this, &AudioRegionEditor::show_on_touch_changed)); + + arv->region_line_changed.connect ((sigc::mem_fun (*this, &AudioRegionEditor::refill_region_line))); _peak_amplitude.property_editable() = false; _peak_amplitude.set_text (_("Calculating...")); @@ -105,6 +122,7 @@ AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr r snprintf (name, 64, "peak amplitude-%p", this); pthread_create_and_store (name, &_peak_amplitude_thread_handle, _peak_amplitude_thread, this); signal_peak_thread (); + } AudioRegionEditor::~AudioRegionEditor () @@ -128,6 +146,14 @@ AudioRegionEditor::region_changed (const PBD::PropertyChange& what_changed) signal_peak_thread (); } } + +void +AudioRegionEditor::region_fx_changed () +{ + RegionEditor::region_fx_changed (); + refill_region_line (); +} + void AudioRegionEditor::gain_changed () { @@ -189,3 +215,118 @@ AudioRegionEditor::peak_amplitude_found (double p) _peak_amplitude.set_text (s.str ()); } +void +AudioRegionEditor::show_touched_automation (std::weak_ptr wac) +{ + if (!_arv->set_region_fx_line (wac)) { + return; + } + + switch (PublicEditor::instance ().current_mouse_mode ()) { + case Editing::MouseObject: + case Editing::MouseTimeFX: + case Editing::MouseGrid: + case Editing::MouseCut: + PublicEditor::instance ().set_mouse_mode (Editing::MouseDraw, false); + break; + default: + break; + } +} + +void +AudioRegionEditor::show_on_touch_changed () +{ + if (!_show_on_touch.get_active ()) { + _ctrl_touched_connection.disconnect (); + return; + } + Controllable::ControlTouched.connect (_ctrl_touched_connection, invalidator (*this), boost::bind (&AudioRegionEditor::show_touched_automation, this, _1), gui_context ()); +} + +void +AudioRegionEditor::refill_region_line () +{ + using namespace Gtk::Menu_Helpers; + + _region_line.clear_items (); + + MenuList& rm_items (_region_line.items ()); + + int nth = 0; + PBD::ID rfx_id (0); + uint32_t param_id = 0; + string active_text = _("Gain Envelope"); + + _arv->get_region_fx_line (rfx_id, param_id); + _arv->set_ignore_line_change (true); + + Gtk::RadioMenuItem::Group grp; + AudioRegionView* arv = _arv; + + rm_items.push_back (RadioMenuElem (grp, _("Gain Envelope"))); + Gtk::CheckMenuItem* cmi = static_cast (&rm_items.back ()); + cmi->set_active (rfx_id == 0 || param_id == UINT32_MAX); + cmi->signal_activate ().connect ([cmi, arv] () { if (cmi->get_active ()) {arv->set_region_gain_line (); }}); + + _audio_region->foreach_plugin ([&rm_items, arv, &nth, &grp, &active_text, rfx_id, param_id](std::weak_ptr wfx) + { + std::shared_ptr fx (wfx.lock ()); + if (!fx) { + return; + } + std::shared_ptr plugin = fx->plugin (); + + Gtk::Menu* acm = manage (new Gtk::Menu); + MenuList& acm_items (acm->items ()); + + for (size_t i = 0; i < plugin->parameter_count (); ++i) { + if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) { + continue; + } + const Evoral::Parameter param (PluginAutomation, 0, i); + std::string label = plugin->describe_parameter (param); + if (label == X_("latency") || label == X_("hidden")) { + continue; + } + std::shared_ptr c (std::dynamic_pointer_cast (fx->control (param))); + if (c && c->flags () & (Controllable::HiddenControl | Controllable::NotAutomatable)) { + continue; + } + bool active = fx->id () == rfx_id && param_id == i; + + acm_items.push_back (RadioMenuElem (grp, label)); + Gtk::CheckMenuItem* cmi = static_cast (&acm_items.back ()); + cmi->set_active (active); + cmi->signal_activate ().connect ([cmi, arv, nth, i] () { if (cmi->get_active ()) {arv->set_region_fx_line (nth, i); }}); + if (active) { + active_text = fx->name () + ": " + label; + } + } + + if (!acm_items.empty ()) { + rm_items.push_back (MenuElem (fx->name (), *acm)); + } else { + delete acm; + } + ++nth; + }); + + + if (rm_items.size () > 1) { + _show_on_touch.set_sensitive (true); + } else { + _show_on_touch.set_active (false); + _show_on_touch.set_sensitive (false); + } + + _region_line.set_text (active_text); + _arv->set_ignore_line_change (false); +} + +void +AudioRegionEditor::on_unmap () +{ + _show_on_touch.set_active (false); + ArdourDialog::on_unmap (); +} diff --git a/gtk2_ardour/audio_region_editor.h b/gtk2_ardour/audio_region_editor.h index 6d73f69721..a941840682 100644 --- a/gtk2_ardour/audio_region_editor.h +++ b/gtk2_ardour/audio_region_editor.h @@ -37,6 +37,7 @@ #include #include +#include "widgets/ardour_dropdown.h" #include "pbd/signals.h" #include "pbd/crossthread.h" @@ -55,18 +56,25 @@ class AudioRegionView; class AudioRegionEditor : public RegionEditor { public: - AudioRegionEditor (ARDOUR::Session*, std::shared_ptr); + AudioRegionEditor (ARDOUR::Session*, AudioRegionView*); ~AudioRegionEditor (); void peak_amplitude_thread (); + void on_unmap (); private: void region_changed (PBD::PropertyChange const &); + void region_fx_changed (); void gain_changed (); void gain_adjustment_changed (); + void refill_region_line (); + void show_on_touch_changed (); + void show_touched_automation (std::weak_ptr); + + AudioRegionView* _arv; std::shared_ptr _audio_region; Gtk::Label gain_label; @@ -79,6 +87,12 @@ private: Gtk::Label _peak_amplitude_label; Gtk::Entry _peak_amplitude; + Gtk::Label _region_line_label; + ArdourWidgets::ArdourDropdown _region_line; + + Gtk::CheckButton _show_on_touch; + PBD::ScopedConnection _ctrl_touched_connection; + void signal_peak_thread (); pthread_t _peak_amplitude_thread_handle; void peak_amplitude_found (double); diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 069165c639..0445434fd8 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -36,6 +36,7 @@ #include "ardour/audioregion.h" #include "ardour/audiosource.h" #include "ardour/profile.h" +#include "ardour/region_fx_plugin.h" #include "ardour/session.h" #include "pbd/memento_command.h" @@ -112,8 +113,7 @@ static Cairo::RefPtr create_pending_peak_pattern() { return p; } -AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, std::shared_ptr r, double spu, - uint32_t basic_color) +AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, std::shared_ptr r, double spu, uint32_t basic_color) : RegionView (parent, tv, r, spu, basic_color) , fade_in_handle(0) , fade_out_handle(0) @@ -129,6 +129,9 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxis , _amplitude_above_axis(1.0) , trim_fade_in_drag_active(false) , trim_fade_out_drag_active(false) + , _rfx_id (0) + , _rdx_param (UINT32_MAX) + , _ignore_line_change (false) { } @@ -149,6 +152,9 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxis , _amplitude_above_axis(1.0) , trim_fade_in_drag_active(false) , trim_fade_out_drag_active(false) + , _rfx_id (0) + , _rdx_param (UINT32_MAX) + , _ignore_line_change (false) { } @@ -168,6 +174,9 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other, std::shared_ptr< , _amplitude_above_axis (other._amplitude_above_axis) , trim_fade_in_drag_active(false) , trim_fade_out_drag_active(false) + , _rfx_id (0) + , _rdx_param (UINT32_MAX) + , _ignore_line_change (false) { init (true); } @@ -232,12 +241,7 @@ AudioRegionView::init (bool wfd) set_fade_visibility (false); } - const string line_name = _region->name() + ":gain"; - - gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope())); - - update_envelope_visibility (); - gain_line->reset (); + set_region_gain_line (); /* streamview will call set_height() */ //set_height (trackview.current_height()); // XXX not correct for Layered mode, but set_height() will fix later. @@ -278,7 +282,7 @@ AudioRegionView::init (bool wfd) setup_waveform_visibility (); get_canvas_frame()->set_data ("linemerger", (LineMerger*) this); - gain_line->canvas_group().raise_to_top (); + _fx_line->canvas_group().raise_to_top (); /* XXX sync mark drag? */ } @@ -606,15 +610,15 @@ AudioRegionView::set_height (gdouble height) } } - if (gain_line) { + if (_fx_line) { if ((height / nchans) < NAME_HIGHLIGHT_THRESH) { - gain_line->hide (); + _fx_line->hide (); } else { update_envelope_visibility (); } - gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2); + _fx_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2); } reset_fade_shapes (); @@ -1081,8 +1085,8 @@ AudioRegionView::set_samples_per_pixel (gdouble fpp) } } - if (gain_line) { - gain_line->reset (); + if (_fx_line) { + _fx_line->reset (); } reset_fade_shapes (); @@ -1101,12 +1105,9 @@ AudioRegionView::set_colors () { RegionView::set_colors(); - if (gain_line) { - gain_line->set_line_color (audio_region()->envelope_active() ? - UIConfiguration::instance().color ("gain line") : - UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive")); - } + assert (_fx_line); + set_fx_line_colors (); set_waveform_colors (); if (start_xfade_curve) { @@ -1148,8 +1149,8 @@ AudioRegionView::setup_waveform_visibility () void AudioRegionView::temporarily_hide_envelope () { - if (gain_line) { - gain_line->hide (); + if (_fx_line) { + _fx_line->hide (); } } @@ -1160,20 +1161,118 @@ AudioRegionView::unhide_envelope () } void -AudioRegionView::update_envelope_visibility () +AudioRegionView::set_region_gain_line () { - if (!gain_line) { + if (_ignore_line_change) { return; } + const string line_name = _region->name() + ":gain"; + _fx_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope())); + _fx_line->set_height ((uint32_t) rint (height() - NAME_HIGHLIGHT_SIZE) - 2); + _fx_line->reset (); + _region_fx_connection.disconnect (); + bool changed = _rfx_id != PBD::ID (0) || _rdx_param != UINT32_MAX; + _rfx_id = PBD::ID (0); + _rdx_param = UINT32_MAX; + + envelope_active_changed (); + if (changed) { + region_line_changed (); /* EMIT SIGNAL */ + } +} + +void +AudioRegionView::set_region_fx_line (std::shared_ptr ac, std::shared_ptr rfx, uint32_t param_id) +{ + const string line_name = _region->name () + ":" + rfx->describe_parameter (Evoral::Parameter (PluginAutomation, 0, param_id)); + _fx_line.reset (new RegionFxLine (line_name, *this, *group, ac)); + _fx_line->set_height ((uint32_t) rint (height() - NAME_HIGHLIGHT_SIZE) - 2); + _fx_line->reset (); + + rfx->DropReferences.connect (_region_fx_connection, invalidator (*this), boost::bind (&AudioRegionView::set_region_gain_line, this), gui_context ()); + + bool changed = _rfx_id != rfx->id () || _rdx_param != param_id; + _rfx_id = rfx->id (); + _rdx_param = param_id; + + envelope_active_changed (); + if (changed) { + region_line_changed (); /* EMIT SIGNAL */ + } +} + +bool +AudioRegionView::set_region_fx_line (uint32_t plugin_id, uint32_t param_id) +{ + if (_ignore_line_change) { + return false; + } + std::shared_ptr rfx = _region->nth_plugin (plugin_id); + if (rfx) { + std::shared_ptr c = rfx->control (Evoral::Parameter (PluginAutomation, 0, param_id)); + std::shared_ptr ac = std::dynamic_pointer_cast (c); + if (ac) { + set_region_fx_line (ac, rfx, param_id); + return true; + } + } + return false; +} + +bool +AudioRegionView::set_region_fx_line (std::weak_ptr wac) +{ + if (_ignore_line_change) { + return false; + } + std::shared_ptr ac = std::dynamic_pointer_cast (wac.lock ()); + if (!ac) { + return false; + } + bool found = false; + _region->foreach_plugin ([this, ac, &found](std::weak_ptr wfx) + { + std::shared_ptr rfx (wfx.lock ()); + if (!rfx || found) { + return; + } + std::shared_ptr plugin = rfx->plugin (); + for (size_t i = 0; i < plugin->parameter_count (); ++i) { + if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) { + continue; + } + const Evoral::Parameter param (PluginAutomation, 0, i); + if (ac == std::dynamic_pointer_cast (rfx->control (param))) { + set_region_fx_line (ac, rfx, i); + found = true; + break; + } + } + }); + return found; +} + +bool +AudioRegionView::get_region_fx_line (PBD::ID& id, uint32_t& param_id) +{ + id = _rfx_id; + param_id = _rdx_param; + return _rdx_param != UINT32_MAX && _rfx_id != 0; +} + +void +AudioRegionView::update_envelope_visibility () +{ + assert (_fx_line); if (trackview.editor().current_mouse_mode() == Editing::MouseDraw || trackview.editor().current_mouse_mode() == Editing::MouseContent ) { - gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::ControlPoints|AutomationLine::Line)); - gain_line->canvas_group().raise_to_top (); + _fx_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::ControlPoints|AutomationLine::Line)); + _fx_line->canvas_group().raise_to_top (); } else if (UIConfiguration::instance().get_show_region_gain() || trackview.editor().current_mouse_mode() == Editing::MouseRange ) { - gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::Line)); - gain_line->canvas_group().raise_to_top (); + _fx_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::Line)); + _fx_line->canvas_group().raise_to_top (); } else { - gain_line->set_visibility (AutomationLine::VisibleAspects(0)); + _fx_line->set_visibility (AutomationLine::VisibleAspects(0)); } } @@ -1374,7 +1473,7 @@ AudioRegionView::peaks_ready_handler (uint32_t which) void AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, bool with_guard_points) { - if (!gain_line) { + if (!_fx_line) { return; } @@ -1386,18 +1485,17 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b samplecnt_t const sample_within_region = (samplecnt_t) floor (mx * samples_per_pixel); - if (!gain_line->control_points_adjacent (sample_within_region, before_p, after_p)) { - /* no adjacent points */ - return; + double y = my; + + if (_fx_line->control_points_adjacent (sample_within_region, before_p, after_p)) { + /* y is in item frame */ + double const bx = _fx_line->nth (before_p)->get_x(); + double const ax = _fx_line->nth (after_p)->get_x(); + double const click_ratio = (ax - mx) / (ax - bx); + + y = ((_fx_line->nth (before_p)->get_y() * click_ratio) + (_fx_line->nth (after_p)->get_y() * (1 - click_ratio))); } - /* 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); - - double y = ((gain_line->nth (before_p)->get_y() * click_ratio) + (gain_line->nth (after_p)->get_y() * (1 - click_ratio))); - /* don't create points that can't be seen */ update_envelope_visibility (); @@ -1412,55 +1510,37 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b /* compute vertical fractional position */ - y = 1.0 - (y / (gain_line->height())); + y = 1.0 - (y / (_fx_line->height())); /* map using gain line */ - gain_line->view_to_model_coord_y (y); + _fx_line->view_to_model_coord_y (y); /* XXX STATEFUL: can't convert to stateful diff until we can represent automation data with it. */ - XMLNode &before = audio_region()->envelope()->get_state(); - MementoCommand* 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(); - region_memento = new MementoCommand(*(audio_region().get()), ®ion_before, ®ion_after); - } - - if (audio_region()->envelope()->editor_add (timepos_t (fx), y, with_guard_points)) { - XMLNode &after = audio_region()->envelope()->get_state(); + XMLNode &before = _fx_line->the_list()->get_state(); + if (_fx_line->the_list()->editor_add (timepos_t (fx), y, with_guard_points)) { + XMLNode &after = _fx_line->the_list()->get_state(); std::list results; trackview.editor().begin_reversible_command (_("add gain control point")); - if (region_memento) { - trackview.session()->add_command (region_memento); - } + _fx_line->enable_autoation (); - trackview.session()->add_command (new MementoCommand(*audio_region()->envelope().get(), &before, &after)); + trackview.session()->add_command (new MementoCommand(*_fx_line->the_list(), &before, &after)); - gain_line->get_selectables (region ()->position () + timecnt_t (fx), region ()->position () + timecnt_t (fx), 0.0, 1.0, results); + _fx_line->get_selectables (region ()->position () + timecnt_t (fx), region ()->position () + timecnt_t (fx), 0.0, 1.0, results); trackview.editor ().get_selection ().set (results); trackview.editor ().commit_reversible_command (); trackview.session ()->set_dirty (); } else { - delete region_memento; + delete &before; } } -void -AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent* /*ev*/) -{ - ControlPoint *cp = reinterpret_cast (item->get_data ("control_point")); - audio_region()->envelope()->erase (cp->model()); -} - GhostRegion* AudioRegionView::add_ghost (TimeAxisView& tv) { @@ -1557,10 +1637,6 @@ AudioRegionView::exited () trackview.editor().set_current_trimmable (std::shared_ptr()); trackview.editor().set_current_movable (std::shared_ptr()); -// if (gain_line) { -// gain_line->remove_visibility (AutomationLine::ControlPoints); -// } - if (fade_in_handle) { fade_in_handle->hide(); } if (fade_out_handle) { fade_out_handle->hide(); } if (fade_in_trim_handle) { fade_in_trim_handle->hide(); } @@ -1572,12 +1648,8 @@ AudioRegionView::exited () void AudioRegionView::envelope_active_changed () { - if (gain_line) { - gain_line->set_line_color (audio_region()->envelope_active() ? - UIConfiguration::instance().color ("gain line") : - UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive")); - update_envelope_visibility (); - } + set_fx_line_colors (); + update_envelope_visibility (); } void @@ -1595,6 +1667,20 @@ AudioRegionView::color_handler () } +void +AudioRegionView::set_fx_line_colors () +{ + assert (_fx_line); + + if (_rdx_param != UINT32_MAX && _rfx_id != 0) { + _fx_line->set_line_color (UIConfiguration::instance().color ("processor automation line")); + } else { + _fx_line->set_line_color (audio_region()->envelope_active() + ? UIConfiguration::instance().color ("gain line") + : UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive")); + } +} + void AudioRegionView::set_waveform_colors () { @@ -1696,7 +1782,7 @@ void AudioRegionView::show_region_editor () { if (editor == 0) { - editor = new AudioRegionEditor (trackview.session(), audio_region()); + editor = new AudioRegionEditor (trackview.session(), this); } editor->present (); @@ -1858,7 +1944,7 @@ AudioRegionView::parameter_changed (string const & p) MergeableLine* AudioRegionView::make_merger () { - return new MergeableLine (gain_line, std::shared_ptr(), + return new MergeableLine (_fx_line, std::shared_ptr(), [this](timepos_t const& t) { return timepos_t (_region->position().distance (t)); }, nullptr, nullptr); } diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h index 07b7265d64..762dba9107 100644 --- a/gtk2_ardour/audio_region_view.h +++ b/gtk2_ardour/audio_region_view.h @@ -50,9 +50,9 @@ namespace ARDOUR { }; class AudioTimeAxisView; -class AudioRegionGainLine; class GhostRegion; class AutomationTimeAxisView; +class RegionFxLine; class RouteTimeAxisView; class AudioRegionView : public RegionView, public LineMerger @@ -91,12 +91,18 @@ public: void temporarily_hide_envelope (); ///< Dangerous! void unhide_envelope (); ///< Dangerous! + void set_region_gain_line (); + void set_ignore_line_change (bool v) { _ignore_line_change = v; }; + bool set_region_fx_line (uint32_t, uint32_t); + bool set_region_fx_line (std::weak_ptr); + bool get_region_fx_line (PBD::ID&, uint32_t&); void update_envelope_visibility (); - void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points); - void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event); + sigc::signal region_line_changed; - std::shared_ptr get_gain_line() const { return gain_line; } + void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points); + + std::shared_ptr fx_line() const { return _fx_line; } void region_changed (const PBD::PropertyChange&); void envelope_active_changed (); @@ -184,7 +190,7 @@ protected: ArdourCanvas::Rectangle* end_xfade_rect; bool _end_xfade_visible; - std::shared_ptr gain_line; + std::shared_ptr _fx_line; double _amplitude_above_axis; @@ -206,6 +212,7 @@ protected: void set_colors (); void set_waveform_colors (); + void set_fx_line_colors (); void reset_width_dependent_items (double pixel_width); void color_handler (); @@ -234,6 +241,14 @@ private: bool trim_fade_in_drag_active; bool trim_fade_out_drag_active; + + void set_region_fx_line (std::shared_ptr, std::shared_ptr, uint32_t); + + PBD::ID _rfx_id; + uint32_t _rdx_param; + bool _ignore_line_change; + + PBD::ScopedConnection _region_fx_connection; }; #endif /* __gtk_ardour_audio_region_view_h__ */ diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index 8868bfcc31..139277e7bd 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -470,8 +470,8 @@ AudioStreamView::set_selected_points (PointSelection& points) { for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { AudioRegionView* const arv = dynamic_cast(*i); - if (arv && arv->get_gain_line ()) { - arv->get_gain_line ()->set_selected_points (points); + if (arv && arv->fx_line ()) { + arv->fx_line ()->set_selected_points (points); } } } diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index cd19b6c74d..0efee332ac 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -87,7 +87,7 @@ using namespace Temporal; AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanvas::Item& parent, - std::shared_ptr al, + std::shared_ptr al, const ParameterDescriptor& desc) : trackview (tv) , _name (name) diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index efa557851b..6ded1d2319 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -68,7 +68,7 @@ public: AutomationLine (const std::string& name, TimeAxisView& tv, ArdourCanvas::Item& parent, - std::shared_ptr al, + std::shared_ptr al, const ARDOUR::ParameterDescriptor& desc); @@ -248,6 +248,7 @@ private: const ARDOUR::ParameterDescriptor _desc; friend class AudioRegionGainLine; + friend class RegionFxLine; }; #endif /* __ardour_automation_line_h__ */ diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index b65af5ac09..15e18e6dff 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -707,11 +707,11 @@ bool Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al) { ItemType type; - AudioRegionGainLine* gl; - if ((gl = dynamic_cast (al)) != 0) { + RegionFxLine* rfl; + if ((rfl = dynamic_cast (al)) != 0) { type = GainLineItem; if (event->type == GDK_BUTTON_PRESS) { - clicked_regionview = &gl->region_view (); + clicked_regionview = &rfl->region_view (); } } else { type = AutomationLineItem; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index ab590dc20c..74aeefe970 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -5039,7 +5039,7 @@ LineDrag::finished (GdkEvent* event, bool movement_occurred) AudioRegionView* arv; if ((arv = dynamic_cast (_editor->clicked_regionview)) != 0) { - arv->add_gain_point_event (&arv->get_gain_line ()->grab_item (), event, false); + arv->add_gain_point_event (&arv->fx_line ()->grab_item (), event, false); } } } @@ -6367,7 +6367,7 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, list cons for (list::const_iterator i = v.begin (); i != v.end (); ++i) { if (AudioRegionView* audio_view = dynamic_cast (*i)) { - lines.push_back (audio_view->get_gain_line ()); + lines.push_back (audio_view->fx_line ()); } else if (AutomationRegionView* automation_view = dynamic_cast (*i)) { lines.push_back (automation_view->line ()); _integral = true; @@ -6394,8 +6394,8 @@ AutomationRangeDrag::setup (list> const& lines) /* need a special detection for automation lanes (not region gain line) */ // TODO: if we implement automation regions, this check can probably be removed - AudioRegionGainLine* argl = dynamic_cast ((*i).get ()); - if (!argl) { + RegionFxLine* fxl = dynamic_cast ((*i).get ()); + if (!fxl) { /* in automation lanes, the EFFECTIVE range should be considered 0->max_position (even if there is no line) */ r.first = Temporal::timepos_t ((*i)->the_list ()->time_domain ()); r.second = Temporal::timepos_t::max ((*i)->the_list ()->time_domain ()); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 9f79558201..1affc81086 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2340,7 +2340,7 @@ Editor::can_remove_control_point (ArdourCanvas::Item* item) } AutomationLine& line = control_point->line (); - if (dynamic_cast (&line)) { + if (dynamic_cast (&line)) { /* we shouldn't remove the first or last gain point in region gain lines */ if (line.is_last_point(*control_point) || line.is_first_point(*control_point)) { return false; diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 831d40903b..4b2e60a78f 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -4833,7 +4833,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, timepos_t const & earliest_time) bool erase = true; - if (dynamic_cast (&line)) { + if (dynamic_cast (&line)) { /* removing of first and last gain point in region gain lines is prohibited*/ if (line.is_last_point (*(*sel_point)) || line.is_first_point (*(*sel_point))) { erase = false; diff --git a/gtk2_ardour/luainstance.cc b/gtk2_ardour/luainstance.cc index 6d853ebeb8..2d6c72ff21 100644 --- a/gtk2_ardour/luainstance.cc +++ b/gtk2_ardour/luainstance.cc @@ -42,6 +42,7 @@ #include "ardour_http.h" #include "ardour_ui.h" +#include "audio_region_view.h" #include "public_editor.h" #include "region_selection.h" #include "luadialog.h" @@ -826,10 +827,16 @@ LuaInstance::register_classes (lua_State* L, bool sandbox) .endClass () .deriveClass ("RegionView") + .addCast ("to_audioregionview") .addFunction ("show_region_editor", &RegionView::show_region_editor) .addFunction ("hide_region_editor", &RegionView::hide_region_editor) .endClass () + .deriveClass ("RegionView") + .addFunction ("set_region_gain_line", &AudioRegionView::set_region_gain_line) + .addFunction ("set_region_fx_line", (bool (AudioRegionView::*)(uint32_t, uint32_t))&AudioRegionView::set_region_fx_line) + .endClass () + .deriveClass ("RouteUI") .endClass () diff --git a/gtk2_ardour/region_editor.cc b/gtk2_ardour/region_editor.cc index 9869e5e547..bb7a2b5973 100644 --- a/gtk2_ardour/region_editor.cc +++ b/gtk2_ardour/region_editor.cc @@ -62,11 +62,11 @@ using namespace PBD; using namespace std; using namespace Gtkmm2ext; -RegionEditor::RegionEditor (Session* s, std::shared_ptr r) +RegionEditor::RegionEditor (Session* s, RegionView* rv) : ArdourDialog (_("Region")) , _table (9, 3) , _table_row (0) - , _region (r) + , _region (rv->region ()) , name_label (_("Name:")) , audition_button (_("Audition")) , _clock_group (new ClockGroup) @@ -77,12 +77,12 @@ RegionEditor::RegionEditor (Session* s, std::shared_ptr r) , sync_offset_absolute_clock (X_("regionsyncoffsetabsolute"), true, "", true, false) /* XXX cannot file start yet */ , start_clock (X_("regionstart"), true, "", false, false) - , _region_fx_box (r) + , _region_fx_box (_region) , _sources (1) { set_session (s); - switch (r->time_domain()) { + switch (_region->time_domain()) { case Temporal::AudioTime: /* XXX check length of region and choose samples or minsec */ _clock_group->set_clock_mode (AudioClock::MinSec); diff --git a/gtk2_ardour/region_editor.h b/gtk2_ardour/region_editor.h index 2e422bfc39..ecc5f9f6b1 100644 --- a/gtk2_ardour/region_editor.h +++ b/gtk2_ardour/region_editor.h @@ -55,12 +55,13 @@ namespace ARDOUR { class RegionFxPlugin; } +class RegionView; class ClockGroup; class RegionEditor : public ArdourDialog { public: - RegionEditor (ARDOUR::Session*, std::shared_ptr); + RegionEditor (ARDOUR::Session*, RegionView*); virtual ~RegionEditor (); protected: diff --git a/gtk2_ardour/region_fx_line.cc b/gtk2_ardour/region_fx_line.cc new file mode 100644 index 0000000000..44945d930a --- /dev/null +++ b/gtk2_ardour/region_fx_line.cc @@ -0,0 +1,92 @@ +/* + * Copyright (C) 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 + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "ardour/automation_control.h" + +#include "audio_region_view.h" +#include "gui_thread.h" +#include "region_fx_line.h" + +#include "pbd/i18n.h" + +using namespace ARDOUR; + +RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas::Container& parent, std::shared_ptr l, ParameterDescriptor const& d) + : AutomationLine (name, r.get_time_axis_view(), parent, l, d) + , _rv (r) +{ + init (); +} + +RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas::Container& parent, std::shared_ptr ac) + : AutomationLine (name, r.get_time_axis_view(), parent, ac->alist (), ac->desc ()) + , _rv (r) + , _ac (ac) +{ + init (); +} + +void +RegionFxLine::init () +{ + _rv.region()->PropertyChanged.connect (_region_changed_connection, invalidator (*this), boost::bind (&RegionFxLine::region_changed, this, _1), gui_context()); + group->raise_to_top (); + group->set_y_position (2); +} + +Temporal::timepos_t +RegionFxLine::get_origin() const +{ + return _rv.region()->position(); +} + +void +RegionFxLine::enable_autoation () +{ + std::shared_ptr ac = _ac.lock (); + if (ac) { + ac->set_automation_state (Play); + } +} + +void +RegionFxLine::end_drag (bool with_push, uint32_t final_index) +{ + enable_autoation (); + AutomationLine::end_drag (with_push, final_index); +} + +void +RegionFxLine::end_draw_merge () +{ + enable_autoation (); + AutomationLine::end_draw_merge (); +} + +void +RegionFxLine::region_changed (PBD::PropertyChange const& what_changed) +{ + PBD::PropertyChange interesting_stuff; + + interesting_stuff.add (ARDOUR::Properties::start); + interesting_stuff.add (ARDOUR::Properties::length); + + if (what_changed.contains (interesting_stuff)) { + reset (); + } +} diff --git a/gtk2_ardour/region_fx_line.h b/gtk2_ardour/region_fx_line.h new file mode 100644 index 0000000000..64ae1e9afd --- /dev/null +++ b/gtk2_ardour/region_fx_line.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 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 + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __ardour_gtk_region_fx_line_h__ +#define __ardour_gtk_region_fx_line_h__ + +#include "automation_line.h" + +class RegionView; + +class RegionFxLine : public AutomationLine +{ +public: + RegionFxLine (std::string const&, RegionView&, ArdourCanvas::Container&, std::shared_ptr, ARDOUR::ParameterDescriptor const&); + RegionFxLine (std::string const&, RegionView&, ArdourCanvas::Container&, std::shared_ptr); + + Temporal::timepos_t get_origin() const; + + RegionView& region_view () { return _rv; } + + void end_drag (bool with_push, uint32_t final_index); + void end_draw_merge (); + + virtual void enable_autoation (); + +private: + void init (); + void region_changed (PBD::PropertyChange const&); + + RegionView& _rv; + std::weak_ptr _ac; + PBD::ScopedConnection _region_changed_connection; +}; + +#endif diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index 14830e95f9..bfabb2604c 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -35,67 +35,52 @@ #include "time_axis_view.h" #include "editor.h" -#include "gui_thread.h" #include "pbd/i18n.h" using namespace std; using namespace ARDOUR; -using namespace PBD; AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, ArdourCanvas::Container& parent, std::shared_ptr l) - : AutomationLine (name, r.get_time_axis_view(), parent, l, l->parameter()) - , rv (r) + : RegionFxLine (name, r, parent, l, l->parameter ()) + , arv (r) { - // If this isn't true something is horribly wrong, and we'll get catastrophic gain values - assert(l->parameter().type() == EnvelopeAutomation); - r.region()->PropertyChanged.connect (_region_changed_connection, invalidator (*this), boost::bind (&AudioRegionGainLine::region_changed, this, _1), gui_context()); - - group->raise_to_top (); - group->set_y_position (2); terminal_points_can_slide = false; } -timepos_t -AudioRegionGainLine::get_origin() const -{ - return rv.region()->position(); -} - - void AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fraction) { - AutomationLine::start_drag_single (cp, x, fraction); + RegionFxLine::start_drag_single (cp, x, fraction); // XXX Stateful need to capture automation curve data - if (!rv.audio_region()->envelope_active()) { - trackview.session()->add_command(new MementoCommand(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); - rv.audio_region()->set_envelope_active(false); + if (!arv.audio_region()->envelope_active()) { + trackview.session()->add_command(new MementoCommand(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0)); + arv.audio_region()->set_envelope_active(false); } } void AudioRegionGainLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) { - AutomationLine::start_drag_line (i1, i2, fraction); + RegionFxLine::start_drag_line (i1, i2, fraction); - if (!rv.audio_region()->envelope_active()) { - trackview.session()->add_command(new MementoCommand(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); - rv.audio_region()->set_envelope_active(false); + if (!arv.audio_region()->envelope_active()) { + trackview.session()->add_command(new MementoCommand(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0)); + arv.audio_region()->set_envelope_active(false); } } void AudioRegionGainLine::start_drag_multiple (list cp, float fraction, XMLNode* state) { - AutomationLine::start_drag_multiple (cp, fraction, state); + RegionFxLine::start_drag_multiple (cp, fraction, state); - if (!rv.audio_region()->envelope_active()) { - trackview.session()->add_command(new MementoCommand(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); - rv.audio_region()->set_envelope_active(false); + if (!arv.audio_region()->envelope_active()) { + trackview.session()->add_command(new MementoCommand(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0)); + arv.audio_region()->set_envelope_active(false); } } @@ -106,10 +91,10 @@ AudioRegionGainLine::remove_point (ControlPoint& cp) trackview.editor().begin_reversible_command (_("remove control point")); XMLNode &before = alist->get_state(); - if (!rv.audio_region()->envelope_active()) { - rv.audio_region()->clear_changes (); - rv.audio_region()->set_envelope_active(true); - trackview.session()->add_command(new StatefulDiffCommand (rv.audio_region())); + if (!arv.audio_region()->envelope_active()) { + arv.audio_region()->clear_changes (); + arv.audio_region()->set_envelope_active(true); + trackview.session()->add_command(new PBD::StatefulDiffCommand (arv.audio_region())); } trackview.editor ().get_selection ().clear_points (); @@ -123,35 +108,27 @@ AudioRegionGainLine::remove_point (ControlPoint& cp) void AudioRegionGainLine::end_drag (bool with_push, uint32_t final_index) { - if (!rv.audio_region()->envelope_active()) { - rv.audio_region()->set_envelope_active(true); - trackview.session()->add_command(new MementoCommand(*(rv.audio_region().get()), 0, &rv.audio_region()->get_state())); + if (!arv.audio_region()->envelope_active()) { + arv.audio_region()->set_envelope_active(true); + trackview.session()->add_command(new MementoCommand(*(arv.audio_region().get()), 0, &arv.audio_region()->get_state())); } - AutomationLine::end_drag (with_push, final_index); + RegionFxLine::end_drag (with_push, final_index); } void AudioRegionGainLine::end_draw_merge () { - if (!rv.audio_region()->envelope_active()) { - XMLNode& before = rv.audio_region()->get_state(); - rv.audio_region()->set_envelope_active(true); - trackview.session()->add_command(new MementoCommand(*(rv.audio_region().get()), &before, &rv.audio_region()->get_state())); - } - - AutomationLine::end_draw_merge (); + enable_autoation (); + RegionFxLine::end_draw_merge (); } void -AudioRegionGainLine::region_changed (const PropertyChange& what_changed) +AudioRegionGainLine::enable_autoation () { - PropertyChange interesting_stuff; - - interesting_stuff.add (ARDOUR::Properties::start); - interesting_stuff.add (ARDOUR::Properties::length); - - if (what_changed.contains (interesting_stuff)) { - reset (); + if (!arv.audio_region()->envelope_active()) { + XMLNode& before = arv.audio_region()->get_state(); + arv.audio_region()->set_envelope_active(true); + trackview.session()->add_command(new MementoCommand(*(arv.audio_region().get()), &before, &arv.audio_region()->get_state())); } } diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h index 9a2daccb91..6f6d724040 100644 --- a/gtk2_ardour/region_gain_line.h +++ b/gtk2_ardour/region_gain_line.h @@ -27,8 +27,7 @@ #include "ardour/ardour.h" - -#include "automation_line.h" +#include "region_fx_line.h" namespace ARDOUR { class Session; @@ -37,26 +36,21 @@ namespace ARDOUR { class TimeAxisView; class AudioRegionView; -class AudioRegionGainLine : public AutomationLine +class AudioRegionGainLine : public RegionFxLine { public: AudioRegionGainLine (const std::string & name, AudioRegionView&, ArdourCanvas::Container& parent, std::shared_ptr); - Temporal::timepos_t get_origin() const; - void start_drag_single (ControlPoint*, double, float); void start_drag_line (uint32_t, uint32_t, float); void start_drag_multiple (std::list, float, XMLNode*); void end_drag (bool with_push, uint32_t final_index); void end_draw_merge (); - + void enable_autoation (); void remove_point (ControlPoint&); - AudioRegionView& region_view () { return rv; } private: - PBD::ScopedConnection _region_changed_connection; - void region_changed (const PBD::PropertyChange& what_changed); - AudioRegionView& rv; + AudioRegionView& arv; }; #endif /* __ardour_gtk_region_gain_line_h__ */ diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index 41687de03f..7ce3fea02c 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -750,7 +750,7 @@ void RegionView::show_region_editor () { if (!editor) { - editor = new RegionEditor (trackview.session(), region()); + editor = new RegionEditor (trackview.session(), this); } editor->present (); diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index 831f4143ac..0cefb76e47 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -1176,11 +1176,11 @@ Selection::get_state () const continue; } - AudioRegionGainLine* argl = dynamic_cast (&(*i)->line()); - if (argl) { + RegionFxLine* fxl = dynamic_cast (&(*i)->line()); + if (fxl) { XMLNode* r = node->add_child (X_("ControlPoint")); r->set_property (X_("type"), "region"); - r->set_property (X_("region-id"), argl->region_view ().region ()->id ()); + r->set_property (X_("region-id"), fxl->region_view ().region ()->id ()); r->set_property (X_("view-index"), (*i)->view_index()); } @@ -1324,35 +1324,6 @@ Selection::set_state (XMLNode const & node, int) if (!cps.empty()) { add (cps); } - } else if (prop_type->value () == "region") { - - PBD::ID region_id; - uint32_t view_index; - if (!(*i)->get_property (X_("region-id"), region_id) || - !(*i)->get_property (X_("view-index"), view_index)) { - continue; - } - - RegionSelection rs; - editor->get_regionviews_by_id (region_id, rs); - - if (!rs.empty ()) { - vector cps; - for (RegionSelection::iterator rsi = rs.begin(); rsi != rs.end(); ++rsi) { - AudioRegionView* arv = dynamic_cast (*rsi); - if (arv) { - std::shared_ptr gl = arv->get_gain_line (); - ControlPoint* cp = gl->nth(view_index); - if (cp) { - cps.push_back (cp); - cp->show(); - } - } - } - if (!cps.empty()) { - add (cps); - } - } } } else if ((*i)->name() == X_("TimelineRange")) { diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index eda605d3e5..01bf9523eb 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -622,7 +622,7 @@ StreamView::get_selectables (timepos_t const & start, timepos_t const & end, dou || (!within && (*i)->region()->coverage (start, end) != Temporal::OverlapNone)) { if (_trackview.editor().internal_editing()) { AudioRegionView* arv = dynamic_cast (*i); - if (arv && arv->get_gain_line ()) { + if (arv && arv->fx_line ()) { /* Note: AutomationLine::get_selectables() uses trackview.current_height (), * disregarding Stacked layer display height */ @@ -630,7 +630,7 @@ StreamView::get_selectables (timepos_t const & start, timepos_t const & end, dou double const y = (*i)->get_canvas_group ()->position().y; double t = 1.0 - std::min (1.0, std::max (0., (top - _trackview.y_position () - y) / c)); double b = 1.0 - std::min (1.0, std::max (0., (bottom - _trackview.y_position () - y) / c)); - arv->get_gain_line()->get_selectables (start, end, b, t, results); + arv->fx_line()->get_selectables (start, end, b, t, results); } } else { results.push_back (*i); diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index fafcc4f185..60525f769e 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -241,6 +241,7 @@ gtk2_ardour_sources = [ 'recorder_group_tabs.cc', 'recorder_ui.cc', 'region_editor.cc', + 'region_fx_line.cc', 'region_gain_line.cc', 'region_layering_order_editor.cc', 'region_list_base.cc',