From a12a065457a10d9be2582f3ad2fcee7178405981 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 16 Dec 2014 14:37:40 -0500 Subject: [PATCH] Fix copy paste of MIDI and track automation. --- gtk2_ardour/automation_streamview.cc | 9 +------ gtk2_ardour/editor_ops.cc | 29 ++++----------------- gtk2_ardour/midi_region_view.cc | 4 --- gtk2_ardour/midi_streamview.cc | 38 ++++++++++++++++++++++++++++ gtk2_ardour/midi_streamview.h | 2 ++ gtk2_ardour/midi_time_axis.cc | 11 ++++++++ gtk2_ardour/midi_time_axis.h | 2 ++ gtk2_ardour/region_view.h | 6 +++++ gtk2_ardour/selection.cc | 2 -- gtk2_ardour/selection.h | 2 +- 10 files changed, 66 insertions(+), 39 deletions(-) diff --git a/gtk2_ardour/automation_streamview.cc b/gtk2_ardour/automation_streamview.cc index 16dab909c7..9b68c55d23 100644 --- a/gtk2_ardour/automation_streamview.cc +++ b/gtk2_ardour/automation_streamview.cc @@ -319,13 +319,6 @@ AutomationStreamView::get_lines () const return lines; } -struct RegionPositionSorter { - bool operator() (RegionView* a, RegionView* b) { - return a->region()->position() < b->region()->position(); - } -}; - - bool AutomationStreamView::paste (framepos_t pos, unsigned paste_count, @@ -338,7 +331,7 @@ AutomationStreamView::paste (framepos_t pos, return false; } - region_views.sort (RegionPositionSorter ()); + region_views.sort (RegionView::PositionOrder()); list::const_iterator prev = region_views.begin (); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 77dad5bf29..c09bbcceb8 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -4478,46 +4478,27 @@ Editor::paste_internal (framepos_t position, float times) R1.A1, R1.A2, R2, R2.A1, ... */ } + begin_reversible_command (Operations::paste); + 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. */ - begin_reversible_command (Operations::paste); - PasteContext ctx(paste_count, times, ItemCounts(), true); ts.front()->paste (position, *cut_buffer, ctx); - commit_reversible_command (); - - } else if (internal_editing ()) { - - /* undo/redo is handled by individual tracks/regions */ - - RegionSelection rs; - get_regions_at (rs, position, ts); - - PasteContext ctx(paste_count, times, ItemCounts(), false); - for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { - MidiRegionView* mrv = dynamic_cast (*r); - if (mrv) { - mrv->paste (position, *cut_buffer, ctx); - } - } - } else { - /* we do redo (do you do voodoo?) */ - - begin_reversible_command (Operations::paste); + /* Paste into tracks */ PasteContext ctx(paste_count, times, ItemCounts(), false); for (TrackViewList::iterator i = ts.begin(); i != ts.end(); ++i) { (*i)->paste (position, *cut_buffer, ctx); } - - commit_reversible_command (); } + + commit_reversible_command (); } void diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 18ea905ce4..787a997e7e 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -3365,8 +3365,6 @@ MidiRegionView::selection_as_cut_buffer () const bool MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx) { - trackview.editor().begin_reversible_command (Operations::paste); - // Paste notes, if available MidiNoteSelection::const_iterator m = selection.midi_notes.get_nth(ctx.counts.n_notes()); if (m != selection.midi_notes.end()) { @@ -3381,8 +3379,6 @@ MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContex a->second->paste(pos, selection, ctx); } - trackview.editor().commit_reversible_command (); - return true; } diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index f47091b3a6..5207b7354d 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -654,3 +654,41 @@ MidiStreamView::resume_updates () _canvas_group->redraw (); } + +struct RegionPositionSorter { + bool operator() (RegionView* a, RegionView* b) { + return a->region()->position() < b->region()->position(); + } +}; + +bool +MidiStreamView::paste (ARDOUR::framepos_t pos, const Selection& selection, PasteContext& ctx) +{ + /* Paste into the first region which starts on or before pos. Only called when + using an internal editing tool. */ + + if (region_views.empty()) { + return false; + } + + region_views.sort (RegionView::PositionOrder()); + + list::const_iterator prev = region_views.begin (); + + for (list::const_iterator i = region_views.begin(); i != region_views.end(); ++i) { + if ((*i)->region()->position() > pos) { + break; + } + prev = i; + } + + boost::shared_ptr r = (*prev)->region (); + + /* If *prev doesn't cover pos, it's no good */ + if (r->position() > pos || ((r->position() + r->length()) < pos)) { + return false; + } + + MidiRegionView* mrv = dynamic_cast (*prev); + return mrv ? mrv->paste(pos, selection, ctx) : false; +} diff --git a/gtk2_ardour/midi_streamview.h b/gtk2_ardour/midi_streamview.h index 7733f87074..9be3b34d9c 100644 --- a/gtk2_ardour/midi_streamview.h +++ b/gtk2_ardour/midi_streamview.h @@ -98,6 +98,8 @@ class MidiStreamView : public StreamView RegionView* create_region_view (boost::shared_ptr, bool, bool); + bool paste (ARDOUR::framepos_t pos, const Selection& selection, PasteContext& ctx); + void apply_note_range(uint8_t lowest, uint8_t highest, bool to_region_views); void suspend_updates (); diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index b23d86194a..f15cf231f0 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -1583,3 +1583,14 @@ MidiTimeAxisView::capture_channel_mode_changed () break; } } + +bool +MidiTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx) +{ + if (!_editor.internal_editing()) { + // Non-internal paste, paste regions like any other route + return RouteTimeAxisView::paste(pos, selection, ctx); + } + + return midi_view()->paste(pos, selection, ctx); +} diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index ebc51b1427..1897174e11 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -81,6 +81,8 @@ class MidiTimeAxisView : public RouteTimeAxisView void show_existing_automation (bool apply_to_selection = false); void create_automation_child (const Evoral::Parameter& param, bool show); + bool paste (ARDOUR::framepos_t, const Selection&, PasteContext& ctx); + ARDOUR::NoteMode note_mode() const { return _note_mode; } ARDOUR::ColorMode color_mode() const { return _color_mode; } diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 389faf8921..d39e75b759 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -113,6 +113,12 @@ class RegionView : public TimeAxisViewItem void drop_silent_frames (); void hide_silent_frames (); + struct PositionOrder { + bool operator()(const RegionView* a, const RegionView* b) { + return a->region()->position() < b->region()->position(); + } + }; + ARDOUR::frameoffset_t snap_frame_to_frame (ARDOUR::frameoffset_t) const; protected: diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index 9f69666497..b00f59ce83 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -42,8 +42,6 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -PBD::Signal0 Selection::ClearMidiNoteSelection; - struct AudioRangeComparator { bool operator()(AudioRange a, AudioRange b) { return a.start < b.start; diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h index 1701d69399..fe2be2e6e4 100644 --- a/gtk2_ardour/selection.h +++ b/gtk2_ardour/selection.h @@ -221,7 +221,7 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList XMLNode& get_state () const; int set_state (XMLNode const &, int); - static PBD::Signal0 ClearMidiNoteSelection; + PBD::Signal0 ClearMidiNoteSelection; private: PublicEditor const * editor;