diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index 101d4f2450..d119c4f0fa 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -121,6 +121,9 @@ public: bool is_xrun() const { return _flags & IsXrun; } bool matches (Flags f) const { return _flags & f; } + /* any range with start < end -- not a marker */ + bool is_range() const { return _flags & (IsSessionRange | IsRangeMarker | IsAutoLoop | IsAutoPunch | IsCDMarker); } + Flags flags () const { return _flags; } std::shared_ptr scene_change() const { return _scene_change; } @@ -258,7 +261,7 @@ public: bool clear_cue_markers (samplepos_t start, samplepos_t end); - void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy); + void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op); void ripple (timepos_t const & at, timecnt_t const & distance, bool include_locked, bool notify); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 9883e6b8d3..d3d21372e5 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -167,7 +167,7 @@ public: /* end of vfunc-based API */ void shift (timepos_t const &, timecnt_t const &); - void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy); + void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op); /* controls use set_solo() to modify this route's solo state */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 0233514383..8002b9f7cc 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1169,7 +1169,7 @@ public: void clear_range_selection (); void clear_object_selection (); - void cut_copy_section (Temporal::timepos_t const& start, Temporal::timepos_t const& end, Temporal::timepos_t const& to, bool const copy = false); + void cut_copy_section (Temporal::timepos_t const& start, Temporal::timepos_t const& end, Temporal::timepos_t const& to, SectionOperation const op); /* buffers for gain and pan */ diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index a7dd3a01d3..7e3a5683f9 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -249,6 +249,13 @@ enum RecordMode { RecSoundOnSound }; +enum SectionOperation { + CopyPasteSection, + CutPasteSection, + InsertSection, + DeleteSection, +}; + enum NoteMode { Sustained, Percussive diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 5692270ca1..2fece2adc3 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -1681,7 +1681,7 @@ Locations::ripple (timepos_t const & at, timecnt_t const & distance, bool includ } void -Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy) +Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op) { LocationList ll; LocationList pastebuf; @@ -1699,20 +1699,38 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep continue; } - if (!i->is_mark ()) { + if (i->is_range ()) { if (i->start () >= start && i->end () <= end) { /* range is inside the selction, process it */ } else if (i->start () < start && i->end () < start) { /* range is entirely outside the selection, possible ripple it */ } else if (i->start () >= end && i->end () >= end) { /* range is entirely outside the selection, possible ripple it */ + } else if (i->start () < start && i->end () >= end) { + /* selection is inside the range, possible shorten or extend it */ + if (op != DeleteSection && op != InsertSection) { + continue; + } } else { // TODO - How do we handle ranges that intersect start/end ? continue; } } - if (!copy) { + if (op == DeleteSection) { + timecnt_t distance = end.distance(start); + if (i->start () >= start && i->start () < end) { + _session.locations()->remove (i); + } else if (i->start () >= end) { + if (i->is_range ()) { + i->set (i->start () + distance, i->end () + distance); + } else { + i->set_start (i->start () + distance); + } + } else if (i->end () >= start) { + i->set (i->start (), i->end () + distance); + } + } else if (op == CutPasteSection) { timecnt_t distance = timecnt_t (i->start ().time_domain ()); if (i->start () < start) { @@ -1738,7 +1756,7 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep } - if (i->is_mark ()) { + if (!i->is_range ()) { i->set_start (i->start () + distance); continue; } @@ -1756,7 +1774,7 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep i->set (i->start () + distance, i->end () + dist_end); - } else { + } else if (op == CopyPasteSection) { if (i->start() >= start && i->start() < end) { Location* copy = new Location (*i); pastebuf.push_back (copy); @@ -1764,27 +1782,30 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep } } - if (copy) { + if (op == CopyPasteSection || op == InsertSection) { /* ripple */ timecnt_t distance = start.distance(end); for (auto const& i : ll) { if (i->start() >= to) { - if (i->is_mark ()) { - i->set_start (i->start () + distance); - } else { + if (i->is_range ()) { i->set (i->start () + distance, i->end () + distance); + } else { + i->set_start (i->start () + distance); } - } else if (!i->is_mark () && i->end() >= to) { + } else if (i->is_range () && i->end() >= to) { i->set_end (i->end () + distance); } } + } + if (op == CopyPasteSection) { /* paste */ + timecnt_t distance = start.distance(end); distance = start.distance (to); for (auto const& i : pastebuf) { - if (i->is_mark ()) { - i->set_start (i->start () + distance); - } else { + if (i->is_range ()) { i->set (i->start () + distance, i->end () + distance); + } else { + i->set_start (i->start () + distance); } locations.push_back (i); added (i); /* EMIT SIGNAL */ diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index df1fe28162..f46c1bd175 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -2343,6 +2343,13 @@ LuaBindings::common (lua_State* L) .addConst ("SrcBest", ARDOUR::SrcQuality(SrcBest)) .endNamespace () + .beginNamespace ("SectionOperation") + .addConst ("CopyPaste", ARDOUR::SectionOperation(CopyPasteSection)) + .addConst ("CutPaste", ARDOUR::SectionOperation(CutPasteSection)) + .addConst ("Insert", ARDOUR::SectionOperation(InsertSection)) + .addConst ("Delete", ARDOUR::SectionOperation(DeleteSection)) + .endNamespace () + .beginNamespace ("MeterType") .addConst ("MeterMaxSignal", ARDOUR::MeterType(MeterMaxSignal)) .addConst ("MeterMaxPeak", ARDOUR::MeterType(MeterMaxPeak)) diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index c39a8ea4c2..be1db1416a 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -4556,7 +4556,7 @@ Route::shift (timepos_t const & pos, timecnt_t const & distance) } void -Route::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy) +Route::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op) { ControllableSet acs; automatables (acs); @@ -4571,14 +4571,27 @@ Route::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t } XMLNode &before = al->get_state (); - std::shared_ptr cl = copy ? al->copy (start, end) : al->cut (start, end); - if (!copy) { + std::shared_ptr cl; + if (op == CopyPasteSection) { + cl = al->copy (start, end); + } else if (op == CutPasteSection) { + cl = al->cut (start, end); + } else if (op == DeleteSection) { + al->clear (start, end); + } + + if (op == CutPasteSection || op == DeleteSection) { /* remove time (negative distance), ripple */ al->shift (start, end.distance (start)); } - /* make space at the inserion point */ - al->shift (to, start.distance (end)); - al->paste (*cl, to); + + if (op != DeleteSection) { + /* make space at the inserion point */ + al->shift (to, start.distance (end)); + } + if (op == CopyPasteSection || op == CutPasteSection) { + al->paste (*cl, to); + } XMLNode &after = al->get_state (); _session.add_command (new MementoCommand (*al.get(), &before, &after)); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 7a9f9fb993..36a3852dbf 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -7225,16 +7225,25 @@ Session::clear_object_selection () } void -Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy) +Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op) { std::list ltr; TimelineRange tlr (start, end, 0); ltr.push_back (tlr); - if (copy) { - begin_reversible_command (_("Copy Section")); - } else { - begin_reversible_command (_("Move Section")); + switch (op) { + case CopyPasteSection: + begin_reversible_command (_("Copy Section")); + break; + case CutPasteSection: + begin_reversible_command (_("Move Section")); + break; + case InsertSection: + begin_reversible_command (_("Insert Section")); + break; + case DeleteSection: + begin_reversible_command (_("Delete Section")); + break; } { @@ -7247,16 +7256,26 @@ Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos pl->clear_changes (); pl->clear_owned_changes (); - std::shared_ptr p = copy ? pl->copy (ltr) : pl->cut (ltr); - if (!copy) { + std::shared_ptr p; + if (op == CopyPasteSection) { + p = pl->copy (ltr); + } else if (op == CutPasteSection || op == DeleteSection) { + p = pl->cut (ltr); + } + + if (op == CutPasteSection || op == DeleteSection) { pl->ripple (start, end.distance(start), NULL); } - /* now make space at the insertion-point */ - pl->split (to); - pl->ripple (to, start.distance(end), NULL); + if (op != DeleteSection) { + /* now make space at the insertion-point */ + pl->split (to); + pl->ripple (to, start.distance(end), NULL); + } - pl->paste (p, to, 1); + if (op == CopyPasteSection || op == CutPasteSection) { + pl->paste (p, to, 1); + } vector cmds; pl->rdiff (cmds); @@ -7273,12 +7292,12 @@ Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos /* automation */ for (auto& r : *(routes.reader())) { - r->cut_copy_section (start, end, to, copy); + r->cut_copy_section (start, end, to, op); } { XMLNode &before = _locations->get_state(); - _locations->cut_copy_section (start, end, to, copy); + _locations->cut_copy_section (start, end, to, op); XMLNode &after = _locations->get_state(); add_command (new MementoCommand (*_locations, &before, &after)); } diff --git a/share/scripts/s_cut_copy_section.lua b/share/scripts/s_cut_copy_section.lua index 58bf3d93ad..62c9dffc82 100644 --- a/share/scripts/s_cut_copy_section.lua +++ b/share/scripts/s_cut_copy_section.lua @@ -4,5 +4,5 @@ function factory (params) return function () local start = Temporal.timepos_t(96000) local _end = Temporal.timepos_t(144000) local to = Temporal.timepos_t(480000) - Session:cut_copy_section (start, _end, to , true) + Session:cut_copy_section (start, _end, to , ARDOUR.SectionOperation.CopyPaste) end end