From 0ea7e80aa6ea9599b34d95624dc4e72b134e095e Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Fri, 12 Jul 2024 18:25:04 +0200 Subject: [PATCH] Implement paste to region gain/fx automation --- gtk2_ardour/audio_region_view.cc | 35 ++++++++++++++++++++++++++++++++ gtk2_ardour/audio_region_view.h | 2 ++ gtk2_ardour/editor_ops.cc | 11 ++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 9a9eaa4346..7c62f2990d 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -67,6 +67,7 @@ #include "mergeable_line.h" #include "region_gain_line.h" #include "control_point.h" +#include "paste_context.h" #include "ghostregion.h" #include "audio_time_axis.h" #include "rgb_macros.h" @@ -1258,6 +1259,40 @@ AudioRegionView::get_region_fx_line (PBD::ID& id, uint32_t& param_id) return _rdx_param != UINT32_MAX && _rfx_id != 0; } +bool +AudioRegionView::paste (Temporal::timepos_t const& pos, const Selection& selection, PasteContext& ctx) +{ + if (!_fx_line || selection.lines.size() != 1) { + return false; + } + std::shared_ptr alist (_fx_line->the_list()); + + AutomationSelection::const_iterator p = selection.lines.begin (); + + Temporal::timecnt_t len = (*p)->length(); + Temporal::timepos_t tpos (pos); + + unsigned paste_count = ctx.count; + + switch (alist->time_domain()) { + case Temporal::BeatTime: + tpos += trackview.editor().get_paste_offset (pos, paste_count > 0 ? 1 : 0, len); + break; + case Temporal::AudioTime: + tpos += trackview.editor().get_paste_offset (pos, paste_count, len); + break; + } + + XMLNode &before = alist->get_state(); + Temporal::timepos_t model_pos (_region->position().distance (tpos)); + alist->paste (**p, model_pos); + timepos_t rlen ((samplepos_t)_region->length().samples()); + alist->truncate_end (rlen); + trackview.session()->add_command (new MementoCommand(*alist.get(), &before, &alist->get_state())); + + return true; +} + void AudioRegionView::update_envelope_visibility () { diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h index 762dba9107..07d03eba8b 100644 --- a/gtk2_ardour/audio_region_view.h +++ b/gtk2_ardour/audio_region_view.h @@ -54,6 +54,7 @@ class GhostRegion; class AutomationTimeAxisView; class RegionFxLine; class RouteTimeAxisView; +class PasteContext; class AudioRegionView : public RegionView, public LineMerger { @@ -97,6 +98,7 @@ public: bool set_region_fx_line (std::weak_ptr); bool get_region_fx_line (PBD::ID&, uint32_t&); void update_envelope_visibility (); + bool paste (Temporal::timepos_t const&, const Selection&, PasteContext&); sigc::signal region_line_changed; diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index b720cf3022..1025c6c6e0 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -5405,7 +5405,7 @@ Editor::paste_internal (timepos_t const & pos, float times) * the below "do the reasonable thing" logic. */ ts = selection->tracks.filter_to_unique_playlists (); sort_track_selection (ts); - } else { + } else if (cut_buffer->lines.empty ()) { /* Figure out which track to base the paste at. */ TimeAxisView* base_track = NULL; if (_edit_point == Editing::EditAtMouse && entered_track) { @@ -5459,10 +5459,17 @@ Editor::paste_internal (timepos_t const & pos, float times) R1.A1, R1.A2, R2, R2.A1, ... */ } + bool commit = false; begin_reversible_command (Operations::paste); - if (ts.size() == 1 && cut_buffer->lines.size() == 1 && + if (ts.size() == 0 && cut_buffer->lines.size() == 1 && entered_regionview) { + AudioRegionView* arv = dynamic_cast(entered_regionview); + if (arv) { + PasteContext ctx(paste_count, times, ItemCounts(), true); + commit |= arv->paste (position, *cut_buffer, ctx); + } + } else if (ts.size() == 1 && cut_buffer->lines.size() == 1 && dynamic_cast(ts.front())) { /* Only one line copied, and one automation track selected. Do a "greedy" paste from one automation type to another. */